@@ -101,16 +101,149 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException
101101 GogsResults result = new GogsResults ();
102102
103103 try {
104- internalDoIndex (result , req , rsp );
104+ String event = req .getHeader ("X-Gogs-Event" );
105+ if ("push" .equals (event )) {
106+ internalDoIndex (result , req , rsp );
107+ }
108+ else if ("release" .equals (event )) {
109+ internalDoIndexRelease (result , req , rsp );
110+ }
111+ else {
112+ result .setStatus (403 , "Only push or release events are accepted." );
113+ exitWebHook (result , rsp );
114+ return ;
115+ }
105116
106117 } catch (final RuntimeException re ) {
107118 LOGGER .severe (re .toString ());
108- result .setStatus (500 , "GogsWebHook execution error." );
119+ result .setStatus (500 , re . toString () );
109120 exitWebHook (result , rsp );
110121 return ;
111122 }
112123 }
113124
125+ void internalDoIndexRelease (GogsResults result , StaplerRequest req , StaplerResponse rsp ) throws IOException {
126+ GogsPayloadProcessor payloadProcessor = new GogsPayloadProcessor ();
127+ //Check that we have something to process
128+ checkNotNull (req , "Null request submitted to doIndex method" );
129+ checkNotNull (rsp , "Null reply submitted to doIndex method" );
130+
131+ // Get X-Gogs-Delivery header with deliveryID
132+ String gogsDelivery = req .getHeader ("X-Gogs-Delivery" );
133+ if (gogsDelivery == null || gogsDelivery .isEmpty ()) {
134+ gogsDelivery = "Triggered by Jenkins-Gogs-Plugin. Delivery ID unknown." ;
135+ } else {
136+ gogsDelivery = "Gogs-ID: " + gogsDelivery ;
137+ }
138+
139+ // Get X-Gogs-Signature
140+ String gogsSignature = req .getHeader ("X-Gogs-Signature" );
141+ if (gogsSignature == null || gogsSignature .isEmpty ()) {
142+ gogsSignature = null ;
143+ }
144+
145+
146+ // Get queryStringMap from the URI
147+ String queryString = checkNotNull (req .getQueryString (), "The queryString in the request is null" );
148+ Map queryStringMap = checkNotNull (splitQuery (queryString ), "Null queryStringMap" );
149+
150+ //Do we have the job name parameter ?
151+ if (!queryStringMap .containsKey ("job" )) {
152+ result .setStatus (404 , "Parameter 'job' is missing." );
153+ exitWebHookRelease (result , rsp );
154+ return ;
155+ }
156+ Object jobObject = queryStringMap .get ("job" );
157+ String jobName ;
158+ if (jobObject == null ) {
159+ result .setStatus (404 , "No value assigned to parameter 'job'" );
160+ exitWebHookRelease (result , rsp );
161+ return ;
162+ } else {
163+ jobName = jobObject .toString ();
164+ }
165+
166+ final Object branchName = queryStringMap .get ("branch" );
167+
168+ String body = IOUtils .toString (req .getInputStream (), DEFAULT_CHARSET );
169+ if (!body .isEmpty () && req .getRequestURI ().contains ("/" + URLNAME + "/" )) {
170+ JSONObject jsonObject = JSONObject .fromObject (body );
171+
172+ JSONObject release = (JSONObject ) jsonObject .getJSONObject ("release" );
173+ String tagName = release .getString ("tag_name" );
174+ String contentType = req .getContentType ();
175+ if (contentType != null && contentType .startsWith ("application/x-www-form-urlencoded" )) {
176+ body = URLDecoder .decode (body , DEFAULT_CHARSET );
177+ }
178+ if (body .startsWith ("payload=" )) {
179+ body = body .substring (8 );
180+ }
181+
182+ String jSecret = null ;
183+ boolean foundJob = false ;
184+ payloadProcessor .setPayload ("ref" , tagName );
185+ SecurityContext saveCtx = ACL .impersonate (ACL .SYSTEM );
186+
187+ try {
188+ Job job = GogsUtils .find (jobName , Job .class );
189+
190+ if (job != null ) {
191+ foundJob = true ;
192+ /* secret is stored in the properties of Job */
193+ final GogsProjectProperty property = (GogsProjectProperty ) job .getProperty (GogsProjectProperty .class );
194+ if (property != null ) { /* only if Gogs secret is defined on the job */
195+ jSecret = Secret .toString (property .getGogsSecret ()); /* Secret provided by Jenkins */
196+ }
197+ }
198+
199+ if (job != null ) {
200+ foundJob = true ;
201+ /* secret is stored in the properties of Job */
202+ final GogsProjectProperty property = (GogsProjectProperty ) job .getProperty (GogsProjectProperty .class );
203+ if (property != null ) { /* only if Gogs secret is defined on the job */
204+ jSecret = Secret .toString (property .getGogsSecret ()); /* Secret provided by Jenkins */
205+ }
206+ }
207+ } finally {
208+ SecurityContextHolder .setContext (saveCtx );
209+ }
210+
211+ String gSecret = null ;
212+ if (gogsSignature == null ) {
213+ gSecret = jsonObject .optString ("secret" , null ); /* Secret provided by Gogs < 0.10.x */
214+ } else {
215+ try {
216+ if (gogsSignature .equals (encode (body , jSecret ))) {
217+ gSecret = jSecret ;
218+ // now hex is right, continue to old logic
219+ }
220+ } catch (Exception e ) {
221+ LOGGER .warning (e .getMessage ());
222+ }
223+ }
224+
225+ if (!foundJob ) {
226+ String msg = String .format ("Job '%s' is not defined in Jenkins" , jobName );
227+ result .setStatus (404 , msg );
228+ LOGGER .warning (msg );
229+ } else if (isNullOrEmpty (jSecret ) && isNullOrEmpty (gSecret )) {
230+ /* No password is set in Jenkins and Gogs, run without secrets */
231+ result = payloadProcessor .triggerJobs (jobName , gogsDelivery );
232+ } else if (!isNullOrEmpty (jSecret ) && jSecret .equals (gSecret )) {
233+ /* Password is set in Jenkins and Gogs, and is correct */
234+ result = payloadProcessor .triggerJobs (jobName , gogsDelivery );
235+ } else {
236+ /* Gogs and Jenkins secrets differs */
237+ result .setStatus (403 , "Incorrect secret" );
238+ }
239+ } else {
240+ result .setStatus (404 , "No payload or URI contains invalid entries." );
241+ }
242+
243+ exitWebHookRelease (result , rsp );
244+
245+
246+ }
114247 void internalDoIndex (GogsResults result , StaplerRequest req , StaplerResponse rsp ) throws IOException {
115248
116249 GogsPayloadProcessor payloadProcessor = new GogsPayloadProcessor ();
@@ -168,15 +301,16 @@ void internalDoIndex(GogsResults result, StaplerRequest req, StaplerResponse rsp
168301 String body = IOUtils .toString (req .getInputStream (), DEFAULT_CHARSET );
169302 if (!body .isEmpty () && req .getRequestURI ().contains ("/" + URLNAME + "/" )) {
170303 JSONObject jsonObject = JSONObject .fromObject (body );
171- JSONObject commits = (JSONObject ) jsonObject .getJSONArray ("commits" ).get (0 );
172- String message = (String ) commits .get ("message" );
173-
174- if (message .startsWith ("[IGNORE]" )) {
175- // Ignore commits starting with message "[IGNORE]"
176- result .setStatus (200 , "Ignoring push" );
177- exitWebHook (result , rsp );
178- return ;
179- }
304+
305+ JSONObject commits = (JSONObject ) jsonObject .getJSONArray ("commits" ).get (0 );
306+ String message = (String ) commits .get ("message" );
307+ if (message .startsWith ("[IGNORE]" )) {
308+ // Ignore commits starting with message "[IGNORE]"
309+ result .setStatus (200 , "Ignoring push" );
310+ exitWebHook (result , rsp );
311+ return ;
312+ }
313+
180314
181315 String ref = jsonObject .getString ("ref" );
182316 LOGGER .fine ("found ref " + ref );
@@ -304,6 +438,19 @@ private void exitWebHook(GogsResults result, StaplerResponse resp) throws IOExce
304438 printer .print (json .toString ());
305439 }
306440
441+
442+ private void exitWebHookRelease (GogsResults result , StaplerResponse resp ) throws IOException {
443+ if (result .getStatus () != 200 ) {
444+ LOGGER .warning (result .getMessage ());
445+ }
446+ //noinspection MismatchedQueryAndUpdateOfCollection
447+ JSONObject json = new JSONObject ();
448+ json .element ("result" , result .getStatus () == 200 ? "OK" : "ERROR" );
449+ resp .setStatus (result .getStatus ());
450+ resp .addHeader ("Content-Type" , "application/json" );
451+ PrintWriter printer = resp .getWriter ();
452+ printer .print (json .toString ());
453+ }
307454 /**
308455 * Converts Querystring into Map<String,String>
309456 *
0 commit comments