1 /***************************************************************************
2 * Copyright (C) 2007,2008 Øyvind Harboe *
3 * oyvind.harboe@zylin.com *
5 * Copyright (C) 2008 Free Software Foundation
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
23 /* some bits were copied from ahttpd which is under eCos license and
30 #include "replacements.h"
35 #include "telnet_server.h"
43 #include <sys/types.h>
48 #include <sys/types.h>
49 #include <sys/select.h>
50 #include <sys/socket.h>
51 #include <microhttpd.h>
56 #define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>"
58 int loadFile(const char *name
, void **data
, size_t *len
);
60 static const char *appendf(const char *prev
, const char *format
, ...)
64 char *string
= alloc_vprintf(format
, ap
);
70 string2
= alloc_printf("%s%s", (prev
== NULL
) ? "" : prev
, string
);
84 static const char *httpd_exec_cgi_tcl_error(Jim_Interp
*interp
)
89 t
= appendf(t
, "<html><body>\n");
91 t
= appendf(t
, "Runtime error, file \"%s\", line %d:<br>",
92 interp
->errorFileName
, interp
->errorLine
);
93 t
= appendf(t
, " %s<br>", Jim_GetString(interp
->result
, NULL
));
94 Jim_ListLength(interp
, interp
->stackTrace
, &len
);
95 for (i
= 0; i
< len
; i
+= 3)
98 const char *proc
, *file
, *line
;
100 Jim_ListIndex(interp
, interp
->stackTrace
, i
, &objPtr
, JIM_NONE
);
101 proc
= Jim_GetString(objPtr
, NULL
);
102 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 1, &objPtr
, JIM_NONE
);
103 file
= Jim_GetString(objPtr
, NULL
);
104 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 2, &objPtr
, JIM_NONE
);
105 line
= Jim_GetString(objPtr
, NULL
);
106 t
= appendf(t
, "In procedure '%s' called at file \"%s\", line %s<br>",
109 t
= appendf(t
, "</html></body>\n");
114 static int httpd_Jim_Command_writeform(Jim_Interp
*interp
, int argc
,
115 Jim_Obj
* const *argv
)
119 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
122 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
123 char *file
= (char*) Jim_GetString(argv
[2], NULL
);
131 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
133 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
134 free((void *) script
);
135 if (retcode
!= JIM_OK
)
138 data
= Jim_GetString(Jim_GetResult(interp
), &actual
);
140 FILE *f
= fopen(file
, "wb");
143 Jim_SetResultString(interp
, "Could not create file", -1);
147 int result
= fwrite(data
, 1, actual
, f
);
150 if (result
!= actual
)
152 Jim_SetResultString(interp
, "Could not write to file", -1);
160 httpd_Jim_Command_formfetch(Jim_Interp
*interp
,
162 Jim_Obj
*const *argv
)
166 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
169 char *name
= (char*)Jim_GetString(argv
[1], NULL
);
172 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
174 int retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
175 free((void *) script
);
176 if (retcode
!= JIM_OK
)
178 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
181 Jim_SetResult(interp
, Jim_GetResult(interp
));
190 struct MHD_PostProcessor
*postprocessor
;
194 int complete
; /* did we receive the entire post ? */
198 static void request_completed(void *cls
, struct MHD_Connection
*connection
,
199 void **con_cls
, enum MHD_RequestTerminationCode toe
)
201 struct httpd_request
*r
= (struct httpd_request
*) *con_cls
;
206 if (r
->postprocessor
)
208 MHD_destroy_post_processor(r
->postprocessor
);
215 /* append to said key in dictonary */
216 static void append_key(struct httpd_request
*r
, const char *key
,
217 const char *data
, size_t off
, size_t size
)
219 Jim_Obj
*keyObj
= Jim_NewStringObj(interp
, key
, -1);
220 Jim_Obj
*value
= NULL
;
222 Jim_Obj
*dict
= Jim_GetVariableStr(interp
, "httppostdata", 0);
226 if (Jim_DictKey(interp
, dict
, keyObj
, &value
, 0) != JIM_OK
)
232 value
= Jim_NewStringObj(interp
, "", -1);
234 /* create a new object we append to and insert into this location */
235 Jim_Obj
*newObj
= Jim_NewStringObj(interp
, "", -1);
236 Jim_AppendObj(interp
, newObj
, value
);
237 Jim_AppendString(interp
, newObj
, data
, size
);
238 /* uhh... use name here of dictionary */
239 Jim_SetDictKeysVector(interp
, Jim_NewStringObj(interp
, "httppostdata", -1), &keyObj
, 1, newObj
);
242 /* append data to each key */
243 static int iterate_post(void *con_cls
, enum MHD_ValueKind kind
,
244 const char *key
, const char *filename
, const char *content_type
,
245 const char *transfer_encoding
, const char *data
, uint64_t off
,
248 struct httpd_request
*r
= (struct httpd_request
*) con_cls
;
250 append_key(r
, key
, data
, off
, size
);
255 static int record_arg(void *cls
, enum MHD_ValueKind kind
, const char *key
,
258 struct httpd_request
*r
= (struct httpd_request
*) cls
;
259 append_key(r
, key
, value
, 0, strlen(value
));
264 int handle_request(struct MHD_Connection
* connection
, const char * url
)
266 struct MHD_Response
* response
;
270 suffix
= strrchr(url
, '.');
271 if ((suffix
!= NULL
) && (strcmp(suffix
, ".tcl") == 0))
273 printf("Run tcl %s\n", url
);
277 const char *script
= alloc_printf(
278 "global httpdata; source {%s}; set httpdata", url
);
279 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
280 free((void *) script
);
282 if (retcode
== JIM_ERR
)
284 printf("Tcl failed\n");
285 const char *t
= httpd_exec_cgi_tcl_error(interp
);
289 response
= MHD_create_response_from_data(strlen(t
), (void *) t
,
291 ret
= MHD_queue_response(connection
,
292 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
293 MHD_destroy_response(response
);
299 /* FIX!!! how to handle mime types??? */
302 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
304 response
= MHD_create_response_from_data(reslen
, (void *) result
,
306 ret
= MHD_queue_response(connection
,
307 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
308 MHD_destroy_response(response
);
317 int retval
= loadFile(url
, &data
, &len
);
318 if (retval
!= ERROR_OK
)
320 printf("Did not find %s\n", url
);
322 response
= MHD_create_response_from_data(strlen(PAGE_NOT_FOUND
),
323 (void *) PAGE_NOT_FOUND
, MHD_NO
, MHD_NO
);
324 ret
= MHD_queue_response(connection
, MHD_HTTP_NOT_FOUND
, response
);
325 MHD_destroy_response(response
);
329 LOG_DEBUG("Serving %s length=%u", url
, len
);
330 /* serve file directly */
331 response
= MHD_create_response_from_data(len
, data
, MHD_YES
, MHD_NO
);
332 MHD_add_response_header(response
, "Content-Type", "image/png");
334 ret
= MHD_queue_response(connection
, MHD_HTTP_OK
, response
);
335 MHD_destroy_response(response
);
342 static int ahc_echo(void * cls
, struct MHD_Connection
* connection
,
343 const char * url
, const char * method
, const char * version
,
344 const char * upload_data
, unsigned int * upload_data_size
, void ** ptr
)
348 if (0 == strcmp(method
, "POST"))
352 else if (0 == strcmp(method
, "GET"))
357 return MHD_NO
; /* unexpected method */
360 struct httpd_request
*r
;
363 /* The first time only the headers are valid,
364 do not respond in the first round... */
366 *ptr
= malloc(sizeof(struct httpd_request
));
369 memset(*ptr
, 0, sizeof(struct httpd_request
));
371 r
= (struct httpd_request
*) *ptr
;
374 Jim_SetVariableStr(interp
, "httppostdata", Jim_NewDictObj(interp
, NULL
, 0));
376 /* fill in url query strings in dictonary */
377 MHD_get_connection_values(connection
, MHD_GET_ARGUMENT_KIND
,
382 r
->postprocessor
= MHD_create_post_processor(connection
, 2048
383 * 1024, &iterate_post
, r
);
389 r
= (struct httpd_request
*) *ptr
;
393 /* consume post data */
394 if (*upload_data_size
)
396 MHD_post_process(r
->postprocessor
, upload_data
, *upload_data_size
);
397 *upload_data_size
= 0;
407 /* hand over to request who will be using it. */
411 /* FIX!!!! we need more advanced handling of url's to avoid them
412 * being subverted to evil purposes
415 const char *httpd_dir
=PKGLIBDIR
"/httpd";
419 url
++; /* skip '/' */
424 const char *file_name
=alloc_printf("%s/%s", httpd_dir
, url
);
425 int result
= handle_request(connection
, file_name
);
426 free((void *)file_name
);
430 static struct MHD_Daemon
* d
;
431 static pthread_mutex_t mutex
;
434 int httpd_start(void)
436 pthread_mutexattr_t attr
;
437 pthread_mutexattr_init( &attr
);
438 pthread_mutex_init( &mutex
, &attr
);
441 LOG_USER("Launching httpd server on port %d", port
);
442 d
= MHD_start_daemon(MHD_USE_SELECT_INTERNALLY
, port
, NULL
, NULL
,
443 &ahc_echo
, NULL
, /* could be data for handler, but we only have a single handler, use global variables instead */
444 MHD_OPTION_NOTIFY_COMPLETED
, request_completed
, NULL
, /* Closure... what's that??? */
449 Jim_CreateCommand(interp
,
451 httpd_Jim_Command_formfetch
,
455 Jim_CreateCommand(interp
,
457 httpd_Jim_Command_writeform
,
465 void httpd_stop(void)
468 pthread_mutex_destroy( &mutex
);
471 void openocd_sleep_prelude(void)
473 pthread_mutex_unlock( &mutex
);
476 void openocd_sleep_postlude(void)
478 pthread_mutex_lock( &mutex
);
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)