aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-bcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-bcd.c')
-rw-r--r--src/gns/gnunet-bcd.c533
1 files changed, 0 insertions, 533 deletions
diff --git a/src/gns/gnunet-bcd.c b/src/gns/gnunet-bcd.c
deleted file mode 100644
index a2e94089c..000000000
--- a/src/gns/gnunet-bcd.c
+++ /dev/null
@@ -1,533 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file gns/gnunet-bcd.c
23 * @author Christian Grothoff
24 * @brief HTTP server to create GNS business cards
25 */
26
27#include "platform.h"
28#include <microhttpd.h>
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31#include "gnunet_mhd_compat.h"
32
33/**
34 * Error page to display if submitted GNS key is invalid.
35 */
36#define INVALID_GNSKEY \
37 "<html><head><title>Error</title><body>Invalid GNS public key given.</body></html>"
38
39/**
40 * Error page to display on 404.
41 */
42#define NOT_FOUND \
43 "<html><head><title>Error</title><body>404 not found</body></html>"
44
45/**
46 * Handle to the HTTP server as provided by libmicrohttpd
47 */
48static struct MHD_Daemon *daemon_handle;
49
50/**
51 * Our configuration.
52 */
53static const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55/**
56 * Our primary task for the HTTPD.
57 */
58static struct GNUNET_SCHEDULER_Task *http_task;
59
60/**
61 * Our main website.
62 */
63static struct MHD_Response *main_response;
64
65/**
66 * Error: invalid gns key.
67 */
68static struct MHD_Response *invalid_gnskey_response;
69
70/**
71 * Error: 404
72 */
73static struct MHD_Response *not_found_response;
74
75/**
76 * Absolute name of the 'gns-bcd.tex' file.
77 */
78static char *resfile;
79
80/**
81 * Port number.
82 */
83static uint16_t port = 8888;
84
85
86struct Entry
87{
88 const char *formname;
89 const char *texname;
90};
91
92
93/**
94 * Main request handler.
95 */
96static MHD_RESULT
97access_handler_callback (void *cls,
98 struct MHD_Connection *connection,
99 const char *url,
100 const char *method,
101 const char *version,
102 const char *upload_data,
103 size_t *upload_data_size,
104 void **con_cls)
105{
106 static int dummy;
107 static const struct Entry map[] = { { "prefix", "prefix" },
108 { "name", "name" },
109 { "suffix", "suffix" },
110 { "street", "street" },
111 { "city", "city" },
112 { "phone", "phone" },
113 { "fax", "fax" },
114 { "email", "email" },
115 { "homepage", "homepage" },
116 { "orga", "orga" },
117 { "departmenti18n", "departmentde" },
118 { "departmenten", "departmenten" },
119 { "subdepartmenti18n",
120 "subdepartmentde" },
121 { "subdepartmenten", "subdepartmenten" },
122 { "jobtitlei18n", "jobtitlegerman" },
123 { "jobtitleen", "jobtitleenglish" },
124 { "subdepartmenten", "subdepartmenten" },
125 { NULL, NULL } };
126
127 (void) cls;
128 (void) version;
129 (void) upload_data;
130 (void) upload_data_size;
131 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
132 {
133 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
134 _ ("Refusing `%s' request to HTTP server\n"),
135 method);
136 return MHD_NO;
137 }
138 if (NULL == *con_cls)
139 {
140 (*con_cls) = &dummy;
141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n");
142 return MHD_YES; /* send 100 continue */
143 }
144 if (0 == strcasecmp (url, "/"))
145 return MHD_queue_response (connection, MHD_HTTP_OK, main_response);
146 if (0 == strcasecmp (url, "/submit.pdf"))
147 {
148 unsigned int i;
149 char *p;
150 char *tmp;
151 char *deffile;
152 struct GNUNET_IDENTITY_PublicKey pub;
153 size_t slen;
154 FILE *f;
155 struct stat st;
156 struct MHD_Response *response;
157 int fd;
158 MHD_RESULT ret;
159
160 const char *gpg_fp = MHD_lookup_connection_value (connection,
161 MHD_GET_ARGUMENT_KIND,
162 "gpgfingerprint");
163 const char *gns_nick = MHD_lookup_connection_value (connection,
164 MHD_GET_ARGUMENT_KIND,
165 "gnsnick");
166 const char *gnskey =
167 MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey");
168 if ((NULL == gnskey) ||
169 (GNUNET_OK !=
170 GNUNET_IDENTITY_public_key_from_string (gnskey,
171 &pub)))
172 {
173 return MHD_queue_response (connection,
174 MHD_HTTP_OK,
175 invalid_gnskey_response);
176 }
177 tmp = GNUNET_DISK_mkdtemp (gnskey);
178 if (NULL == tmp)
179 {
180 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey);
181 return MHD_NO;
182 }
183 GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex");
184 f = fopen (deffile, "w");
185 if (NULL == f)
186 {
187 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile);
188 GNUNET_free (deffile);
189 GNUNET_DISK_directory_remove (tmp);
190 GNUNET_free (tmp);
191 return MHD_NO;
192 }
193 for (i = 0; NULL != map[i].formname; i++)
194 {
195 const char *val = MHD_lookup_connection_value (connection,
196 MHD_GET_ARGUMENT_KIND,
197 map[i].formname);
198 if (NULL != val)
199 fprintf (f, "\\def\\%s{%s}\n", map[i].texname, val);
200 else
201 fprintf (f, "\\def\\%s{}\n", map[i].texname);
202 }
203 if (NULL != gpg_fp)
204 {
205 char *gpg1;
206 char *gpg2;
207
208 slen = strlen (gpg_fp);
209 gpg1 = GNUNET_strndup (gpg_fp, slen / 2);
210 gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]);
211 fprintf (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2);
212 GNUNET_free (gpg2);
213 GNUNET_free (gpg1);
214 }
215 fprintf (f,
216 "\\def\\gns{%s/%s}\n",
217 gnskey,
218 (NULL == gns_nick) ? "" : gns_nick);
219 fclose (f);
220 GNUNET_asprintf (
221 &p,
222 "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null",
223 tmp,
224 resfile);
225 GNUNET_free (deffile);
226 ret = system (p);
227 if (WIFSIGNALED (ret) || (0 != WEXITSTATUS (ret)))
228 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p);
229 GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf");
230 fd = open (deffile, O_RDONLY);
231 if (-1 == fd)
232 {
233 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile);
234 GNUNET_free (deffile);
235 GNUNET_free (p);
236 GNUNET_DISK_directory_remove (tmp);
237 GNUNET_free (tmp);
238 return MHD_NO;
239 }
240 GNUNET_break (0 == stat (deffile, &st));
241 if (NULL ==
242 (response = MHD_create_response_from_fd ((size_t) st.st_size, fd)))
243 {
244 GNUNET_break (0);
245 GNUNET_break (0 == close (fd));
246 GNUNET_free (deffile);
247 GNUNET_free (p);
248 GNUNET_DISK_directory_remove (tmp);
249 GNUNET_free (tmp);
250 return MHD_NO;
251 }
252 (void) MHD_add_response_header (response,
253 MHD_HTTP_HEADER_CONTENT_TYPE,
254 "application/pdf");
255 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
256 MHD_destroy_response (response);
257 GNUNET_free (deffile);
258 GNUNET_free (p);
259 GNUNET_DISK_directory_remove (tmp);
260 GNUNET_free (tmp);
261 return ret;
262 }
263 return MHD_queue_response (connection,
264 MHD_HTTP_NOT_FOUND,
265 not_found_response);
266}
267
268
269/**
270 * Function that queries MHD's select sets and
271 * starts the task waiting for them.
272 */
273static struct GNUNET_SCHEDULER_Task *
274prepare_daemon (struct MHD_Daemon *daemon_handle);
275
276
277/**
278 * Call MHD to process pending requests and then go back
279 * and schedule the next run.
280 */
281static void
282run_daemon (void *cls)
283{
284 struct MHD_Daemon *daemon_handle = cls;
285
286 http_task = NULL;
287 GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
288 http_task = prepare_daemon (daemon_handle);
289}
290
291
292/**
293 * Function that queries MHD's select sets and
294 * starts the task waiting for them.
295 */
296static struct GNUNET_SCHEDULER_Task *
297prepare_daemon (struct MHD_Daemon *daemon_handle)
298{
299 struct GNUNET_SCHEDULER_Task *ret;
300 fd_set rs;
301 fd_set ws;
302 fd_set es;
303 struct GNUNET_NETWORK_FDSet *wrs;
304 struct GNUNET_NETWORK_FDSet *wws;
305 int max;
306 MHD_UNSIGNED_LONG_LONG timeout;
307 int haveto;
308 struct GNUNET_TIME_Relative tv;
309
310 FD_ZERO (&rs);
311 FD_ZERO (&ws);
312 FD_ZERO (&es);
313 wrs = GNUNET_NETWORK_fdset_create ();
314 wws = GNUNET_NETWORK_fdset_create ();
315 max = -1;
316 GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
317 haveto = MHD_get_timeout (daemon_handle, &timeout);
318 if (haveto == MHD_YES)
319 tv.rel_value_us = (uint64_t) timeout * 1000LL;
320 else
321 tv = GNUNET_TIME_UNIT_FOREVER_REL;
322 GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
323 GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
324 ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
325 tv,
326 wrs,
327 wws,
328 &run_daemon,
329 daemon_handle);
330 GNUNET_NETWORK_fdset_destroy (wrs);
331 GNUNET_NETWORK_fdset_destroy (wws);
332 return ret;
333}
334
335
336/**
337 * Start server offering our hostlist.
338 *
339 * @return #GNUNET_OK on success
340 */
341static int
342server_start ()
343{
344 if (0 == port)
345 {
346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
347 _ ("Invalid port number %u. Exiting.\n"),
348 port);
349 return GNUNET_SYSERR;
350 }
351 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
352 _ ("Businesscard HTTP server starts on %u\n"),
353 port);
354 daemon_handle = MHD_start_daemon (MHD_USE_DUAL_STACK | MHD_USE_DEBUG,
355 port,
356 NULL /* accept_policy_callback */,
357 NULL,
358 &access_handler_callback,
359 NULL,
360 MHD_OPTION_CONNECTION_LIMIT,
361 (unsigned int) 512,
362 MHD_OPTION_PER_IP_CONNECTION_LIMIT,
363 (unsigned int) 2,
364 MHD_OPTION_CONNECTION_TIMEOUT,
365 (unsigned int) 60,
366 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
367 (size_t) (16 * 1024),
368 MHD_OPTION_END);
369 if (NULL == daemon_handle)
370 {
371 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
372 _ ("Could not start businesscard HTTP server on port %u\n"),
373 (unsigned int) port);
374 return GNUNET_SYSERR;
375 }
376 http_task = prepare_daemon (daemon_handle);
377 return GNUNET_OK;
378}
379
380
381/**
382 * Stop HTTP server.
383 */
384static void
385server_stop (void *cls)
386{
387 (void) cls;
388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HTTP server shutdown\n");
389 if (NULL != http_task)
390 {
391 GNUNET_SCHEDULER_cancel (http_task);
392 http_task = NULL;
393 }
394 if (NULL != daemon_handle)
395 {
396 MHD_stop_daemon (daemon_handle);
397 daemon_handle = NULL;
398 }
399 if (NULL != main_response)
400 {
401 MHD_destroy_response (main_response);
402 main_response = NULL;
403 }
404 if (NULL != invalid_gnskey_response)
405 {
406 MHD_destroy_response (invalid_gnskey_response);
407 invalid_gnskey_response = NULL;
408 }
409 if (NULL != not_found_response)
410 {
411 MHD_destroy_response (not_found_response);
412 not_found_response = NULL;
413 }
414 if (NULL != resfile)
415 {
416 GNUNET_free (resfile);
417 resfile = NULL;
418 }
419}
420
421
422/**
423 * Main function that will be run.
424 *
425 * @param cls closure
426 * @param args remaining command-line arguments
427 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
428 * @param c configuration
429 */
430static void
431run (void *cls,
432 char *const *args,
433 const char *cfgfile,
434 const struct GNUNET_CONFIGURATION_Handle *c)
435{
436 struct stat st;
437 char *dir;
438 char *fn;
439 int fd;
440
441 (void) cls;
442 (void) args;
443 (void) cfgfile;
444 cfg = c;
445 dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
446 GNUNET_assert (NULL != dir);
447 GNUNET_asprintf (&fn, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.html");
448 GNUNET_asprintf (&resfile, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.tex");
449 GNUNET_free (dir);
450 fd = open (fn, O_RDONLY);
451 if (-1 == fd)
452 {
453 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
454 GNUNET_free (fn);
455 return;
456 }
457 if (0 != stat (fn, &st))
458 {
459 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
460 GNUNET_free (fn);
461 GNUNET_break (0 == close (fd));
462 return;
463 }
464 GNUNET_free (fn);
465 if (NULL ==
466 (main_response = MHD_create_response_from_fd ((size_t) st.st_size, fd)))
467 {
468 GNUNET_break (0);
469 GNUNET_break (0 == close (fd));
470 return;
471 }
472 (void) MHD_add_response_header (main_response,
473 MHD_HTTP_HEADER_CONTENT_TYPE,
474 "text/html");
475 invalid_gnskey_response =
476 MHD_create_response_from_buffer (strlen (INVALID_GNSKEY),
477 INVALID_GNSKEY,
478 MHD_RESPMEM_PERSISTENT);
479 (void) MHD_add_response_header (invalid_gnskey_response,
480 MHD_HTTP_HEADER_CONTENT_TYPE,
481 "text/html");
482 not_found_response = MHD_create_response_from_buffer (strlen (NOT_FOUND),
483 NOT_FOUND,
484 MHD_RESPMEM_PERSISTENT);
485 (void) MHD_add_response_header (not_found_response,
486 MHD_HTTP_HEADER_CONTENT_TYPE,
487 "text/html");
488 if (GNUNET_OK != server_start ())
489 return;
490 GNUNET_SCHEDULER_add_shutdown (&server_stop, NULL);
491}
492
493
494/**
495 * The main function for gnunet-gns.
496 *
497 * @param argc number of arguments from the command line
498 * @param argv command line arguments
499 * @return 0 ok, 1 on error
500 */
501int
502main (int argc, char *const *argv)
503{
504 struct GNUNET_GETOPT_CommandLineOption options[] = {
505 GNUNET_GETOPT_option_uint16 ('p',
506 "port",
507 "PORT",
508 gettext_noop (
509 "Run HTTP serve on port PORT (default is 8888)"),
510 &port),
511 GNUNET_GETOPT_OPTION_END
512 };
513 int ret;
514
515 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
516 return 2;
517 GNUNET_log_setup ("gnunet-bcd", "WARNING", NULL);
518 ret = (GNUNET_OK ==
519 GNUNET_PROGRAM_run (argc,
520 argv,
521 "gnunet-bcd",
522 _ ("GNUnet HTTP server to create business cards"),
523 options,
524 &run,
525 NULL))
526 ? 0
527 : 1;
528 GNUNET_free_nz ((void *) argv);
529 return ret;
530}
531
532
533/* end of gnunet-bcd.c */