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 "telnet_server.h"
33 #include <microhttpd.h>
37 #define PAGE_NOT_FOUND "<html><head><title > File not found</title></head><body > File not found</body></html>"
39 int loadFile(const char *name
, void **data
, size_t *len
);
41 static const char *appendf(const char *prev
, const char *format
, ...)
45 char *string
= alloc_vprintf(format
, ap
);
51 string2
= alloc_printf("%s%s", (prev
== NULL
) ? "" : prev
, string
);
65 static const char *httpd_exec_cgi_tcl_error(Jim_Interp
*interp
)
70 t
= appendf(t
, "<html><body>\n");
72 t
= appendf(t
, "Runtime error, file \"%s\", line %d:<br>",
73 interp
->errorFileName
, interp
->errorLine
);
74 t
= appendf(t
, " %s < br>", Jim_GetString(interp
->result
, NULL
));
75 Jim_ListLength(interp
, interp
->stackTrace
, &len
);
76 for (i
= 0; i
< len
; i
+= 3)
79 const char *proc
, *file
, *line
;
81 Jim_ListIndex(interp
, interp
->stackTrace
, i
, &objPtr
, JIM_NONE
);
82 proc
= Jim_GetString(objPtr
, NULL
);
83 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 1, &objPtr
, JIM_NONE
);
84 file
= Jim_GetString(objPtr
, NULL
);
85 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 2, &objPtr
, JIM_NONE
);
86 line
= Jim_GetString(objPtr
, NULL
);
87 t
= appendf(t
, "In procedure '%s' called at file \"%s\", line %s < br>",
90 t
= appendf(t
, "</html></body>\n");
95 static int httpd_Jim_Command_writeform(Jim_Interp
*interp
, int argc
,
96 Jim_Obj
* const *argv
)
100 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
103 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
104 char *file
= (char*) Jim_GetString(argv
[2], NULL
);
112 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
114 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
115 free((void *) script
);
116 if (retcode
!= JIM_OK
)
119 data
= Jim_GetString(Jim_GetResult(interp
), &actual
);
121 FILE *f
= fopen(file
, "wb");
124 Jim_SetResultString(interp
, "Could not create file", -1);
128 int result
= fwrite(data
, 1, actual
, f
);
131 if (result
!= actual
)
133 Jim_SetResultString(interp
, "Could not write to file", -1);
141 httpd_Jim_Command_formfetch(Jim_Interp
*interp
,
143 Jim_Obj
*const *argv
)
147 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
150 char *name
= (char*)Jim_GetString(argv
[1], NULL
);
153 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
155 int retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
156 free((void *) script
);
157 if (retcode
!= JIM_OK
)
159 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
162 Jim_SetResult(interp
, Jim_GetResult(interp
));
171 struct MHD_PostProcessor
*postprocessor
;
175 int complete
; /* did we receive the entire post ? */
179 static void request_completed(void *cls
, struct MHD_Connection
*connection
,
180 void **con_cls
, enum MHD_RequestTerminationCode toe
)
182 struct httpd_request
*r
= (struct httpd_request
*) *con_cls
;
187 if (r
->postprocessor
)
189 MHD_destroy_post_processor(r
->postprocessor
);
196 /* append to said key in dictonary */
197 static void append_key(struct httpd_request
*r
, const char *key
,
198 const char *data
, size_t off
, size_t size
)
200 Jim_Obj
*keyObj
= Jim_NewStringObj(interp
, key
, -1);
201 Jim_Obj
*value
= NULL
;
203 Jim_Obj
*dict
= Jim_GetVariableStr(interp
, "httppostdata", 0);
207 if (Jim_DictKey(interp
, dict
, keyObj
, &value
, 0) != JIM_OK
)
213 value
= Jim_NewStringObj(interp
, "", -1);
215 /* create a new object we append to and insert into this location */
216 Jim_Obj
*newObj
= Jim_NewStringObj(interp
, "", -1);
217 Jim_AppendObj(interp
, newObj
, value
);
218 Jim_AppendString(interp
, newObj
, data
, size
);
219 /* uhh... use name here of dictionary */
220 Jim_SetDictKeysVector(interp
, Jim_NewStringObj(interp
, "httppostdata", -1), &keyObj
, 1, newObj
);
223 /* append data to each key */
224 static int iterate_post(void *con_cls
, enum MHD_ValueKind kind
,
225 const char *key
, const char *filename
, const char *content_type
,
226 const char *transfer_encoding
, const char *data
, uint64_t off
,
229 struct httpd_request
*r
= (struct httpd_request
*) con_cls
;
231 append_key(r
, key
, data
, off
, size
);
236 static int record_arg(void *cls
, enum MHD_ValueKind kind
, const char *key
,
239 struct httpd_request
*r
= (struct httpd_request
*) cls
;
240 append_key(r
, key
, value
, 0, strlen(value
));
245 int handle_request(struct MHD_Connection
* connection
, const char * url
)
247 struct MHD_Response
* response
;
251 suffix
= strrchr(url
, '.');
252 if ((suffix
!= NULL
) && (strcmp(suffix
, ".tcl") == 0))
254 printf("Run tcl %s\n", url
);
258 const char *script
= alloc_printf(
259 "global httpdata; source {%s}; set httpdata", url
);
260 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
261 free((void *) script
);
263 if (retcode
== JIM_ERR
)
265 printf("Tcl failed\n");
266 const char *t
= httpd_exec_cgi_tcl_error(interp
);
270 response
= MHD_create_response_from_data(strlen(t
), (void *) t
,
272 ret
= MHD_queue_response(connection
,
273 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
274 MHD_destroy_response(response
);
280 /* FIX!!! how to handle mime types??? */
283 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
285 response
= MHD_create_response_from_data(reslen
, (void *) result
,
287 ret
= MHD_queue_response(connection
,
288 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
289 MHD_destroy_response(response
);
298 int retval
= loadFile(url
, &data
, &len
);
299 if (retval
!= ERROR_OK
)
301 printf("Did not find %s\n", url
);
303 response
= MHD_create_response_from_data(strlen(PAGE_NOT_FOUND
),
304 (void *) PAGE_NOT_FOUND
, MHD_NO
, MHD_NO
);
305 ret
= MHD_queue_response(connection
, MHD_HTTP_NOT_FOUND
, response
);
306 MHD_destroy_response(response
);
310 LOG_DEBUG("Serving %s length=%zu", url
, len
);
311 /* serve file directly */
312 response
= MHD_create_response_from_data(len
, data
, MHD_YES
, MHD_NO
);
313 MHD_add_response_header(response
, "Content-Type", "image/png");
315 ret
= MHD_queue_response(connection
, MHD_HTTP_OK
, response
);
316 MHD_destroy_response(response
);
323 static int ahc_echo(void * cls
, struct MHD_Connection
* connection
,
324 const char * url
, const char * method
, const char * version
,
325 const char * upload_data
, unsigned int * upload_data_size
, void ** ptr
)
329 if (0 == strcmp(method
, "POST"))
333 else if (0 == strcmp(method
, "GET"))
338 return MHD_NO
; /* unexpected method */
341 struct httpd_request
*r
;
344 /* The first time only the headers are valid,
345 do not respond in the first round... */
347 *ptr
= malloc(sizeof(struct httpd_request
));
350 memset(*ptr
, 0, sizeof(struct httpd_request
));
352 r
= (struct httpd_request
*) *ptr
;
355 Jim_SetVariableStr(interp
, "httppostdata", Jim_NewDictObj(interp
, NULL
, 0));
357 /* fill in url query strings in dictonary */
358 MHD_get_connection_values(connection
, MHD_GET_ARGUMENT_KIND
,
363 r
->postprocessor
= MHD_create_post_processor(connection
, 2048
364 * 1024, &iterate_post
, r
);
370 r
= (struct httpd_request
*) *ptr
;
374 /* consume post data */
375 if (*upload_data_size
)
377 MHD_post_process(r
->postprocessor
, upload_data
, *upload_data_size
);
378 *upload_data_size
= 0;
388 /* hand over to request who will be using it. */
392 /* FIX!!!! we need more advanced handling of url's to avoid them
393 * being subverted to evil purposes
396 const char *httpd_dir
= PKGDATADIR
"/httpd";
400 url
++; /* skip '/' */
405 const char *file_name
= alloc_printf("%s/%s", httpd_dir
, url
);
406 int result
= handle_request(connection
, file_name
);
407 free((void *)file_name
);
411 static struct MHD_Daemon
* d
;
412 static pthread_mutex_t mutex
;
415 int httpd_start(void)
417 pthread_mutexattr_t attr
;
418 pthread_mutexattr_init(&attr
);
419 pthread_mutex_init(&mutex
, &attr
);
422 LOG_USER("Launching httpd server on port %d", port
);
423 d
= MHD_start_daemon(MHD_USE_SELECT_INTERNALLY
, port
, NULL
, NULL
,
424 &ahc_echo
, NULL
, /* could be data for handler, but we only have a single handler, use global variables instead */
425 MHD_OPTION_NOTIFY_COMPLETED
, request_completed
, NULL
, /* Closure... what's that??? */
430 Jim_CreateCommand(interp
,
432 httpd_Jim_Command_formfetch
,
436 Jim_CreateCommand(interp
,
438 httpd_Jim_Command_writeform
,
446 void httpd_stop(void)
449 pthread_mutex_destroy(&mutex
);
452 void openocd_sleep_prelude(void)
454 pthread_mutex_unlock(&mutex
);
457 void openocd_sleep_postlude(void)
459 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)