diff options
Diffstat (limited to 'src/fs/gnunet-publish.c')
-rw-r--r-- | src/fs/gnunet-publish.c | 1008 |
1 files changed, 0 insertions, 1008 deletions
diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c deleted file mode 100644 index c62edcd61..000000000 --- a/src/fs/gnunet-publish.c +++ /dev/null | |||
@@ -1,1008 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-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 | * @file fs/gnunet-publish.c | ||
22 | * @brief publishing files on GNUnet | ||
23 | * @author Christian Grothoff | ||
24 | * @author Krista Bennett | ||
25 | * @author James Blackwell | ||
26 | * @author Igor Wronsky | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_fs_service.h" | ||
30 | #include "gnunet_identity_service.h" | ||
31 | |||
32 | /** | ||
33 | * Global return value from #main(). | ||
34 | */ | ||
35 | static int ret; | ||
36 | |||
37 | /** | ||
38 | * Command line option 'verbose' set | ||
39 | */ | ||
40 | static unsigned int verbose; | ||
41 | |||
42 | /** | ||
43 | * Handle to our configuration. | ||
44 | */ | ||
45 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | |||
47 | /** | ||
48 | * Handle for interaction with file-sharing service. | ||
49 | */ | ||
50 | static struct GNUNET_FS_Handle *ctx; | ||
51 | |||
52 | /** | ||
53 | * Handle to FS-publishing operation. | ||
54 | */ | ||
55 | static struct GNUNET_FS_PublishContext *pc; | ||
56 | |||
57 | /** | ||
58 | * Meta-data provided via command-line option. | ||
59 | */ | ||
60 | static struct GNUNET_CONTAINER_MetaData *meta; | ||
61 | |||
62 | /** | ||
63 | * Keywords provided via command-line option. | ||
64 | */ | ||
65 | static struct GNUNET_FS_Uri *topKeywords; | ||
66 | |||
67 | /** | ||
68 | * Options we set for published blocks. | ||
69 | */ | ||
70 | static struct GNUNET_FS_BlockOptions bo = { { 0LL }, 1, 365, 1 }; | ||
71 | |||
72 | /** | ||
73 | * Value of URI provided on command-line (when not publishing | ||
74 | * a file but just creating UBlocks to refer to an existing URI). | ||
75 | */ | ||
76 | static char *uri_string; | ||
77 | |||
78 | /** | ||
79 | * Value of URI provided on command-line (when not publishing | ||
80 | * a file but just creating UBlocks to refer to an existing URI); | ||
81 | * parsed version of 'uri_string'. | ||
82 | */ | ||
83 | static struct GNUNET_FS_Uri *uri; | ||
84 | |||
85 | /** | ||
86 | * Command-line option for namespace publishing: identifier for updates | ||
87 | * to this publication. | ||
88 | */ | ||
89 | static char *next_id; | ||
90 | |||
91 | /** | ||
92 | * Command-line option for namespace publishing: identifier for this | ||
93 | * publication. | ||
94 | */ | ||
95 | static char *this_id; | ||
96 | |||
97 | /** | ||
98 | * Command-line option identifying the pseudonym to use for the publication. | ||
99 | */ | ||
100 | static char *pseudonym; | ||
101 | |||
102 | /** | ||
103 | * Command-line option for 'inserting' | ||
104 | */ | ||
105 | static int do_insert; | ||
106 | |||
107 | /** | ||
108 | * Command-line option to disable meta data extraction. | ||
109 | */ | ||
110 | static int disable_extractor; | ||
111 | |||
112 | /** | ||
113 | * Command-line option to merely simulate publishing operation. | ||
114 | */ | ||
115 | static int do_simulate; | ||
116 | |||
117 | /** | ||
118 | * Command-line option to only perform meta data extraction, but not publish. | ||
119 | */ | ||
120 | static int extract_only; | ||
121 | |||
122 | /** | ||
123 | * Command-line option to disable adding creation time. | ||
124 | */ | ||
125 | static int enable_creation_time; | ||
126 | |||
127 | /** | ||
128 | * Handle to the directory scanner (for recursive insertions). | ||
129 | */ | ||
130 | static struct GNUNET_FS_DirScanner *ds; | ||
131 | |||
132 | /** | ||
133 | * Which namespace do we publish to? NULL if we do not publish to | ||
134 | * a namespace. | ||
135 | */ | ||
136 | static struct GNUNET_IDENTITY_Ego *namespace; | ||
137 | |||
138 | /** | ||
139 | * Handle to identity service. | ||
140 | */ | ||
141 | static struct GNUNET_IDENTITY_Handle *identity; | ||
142 | |||
143 | |||
144 | /** | ||
145 | * We are finished with the publishing operation, clean up all | ||
146 | * FS state. | ||
147 | * | ||
148 | * @param cls NULL | ||
149 | */ | ||
150 | static void | ||
151 | do_stop_task (void *cls) | ||
152 | { | ||
153 | struct GNUNET_FS_PublishContext *p; | ||
154 | |||
155 | if (NULL != ds) | ||
156 | { | ||
157 | GNUNET_FS_directory_scan_abort (ds); | ||
158 | ds = NULL; | ||
159 | } | ||
160 | if (NULL != identity) | ||
161 | { | ||
162 | GNUNET_IDENTITY_disconnect (identity); | ||
163 | identity = NULL; | ||
164 | } | ||
165 | if (NULL != pc) | ||
166 | { | ||
167 | p = pc; | ||
168 | pc = NULL; | ||
169 | GNUNET_FS_publish_stop (p); | ||
170 | } | ||
171 | if (NULL != ctx) | ||
172 | { | ||
173 | GNUNET_FS_stop (ctx); | ||
174 | ctx = NULL; | ||
175 | } | ||
176 | if (NULL != meta) | ||
177 | { | ||
178 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
179 | meta = NULL; | ||
180 | } | ||
181 | if (NULL != uri) | ||
182 | { | ||
183 | GNUNET_FS_uri_destroy (uri); | ||
184 | uri = NULL; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Called by FS client to give information about the progress of an | ||
191 | * operation. | ||
192 | * | ||
193 | * @param cls closure | ||
194 | * @param info details about the event, specifying the event type | ||
195 | * and various bits about the event | ||
196 | * @return client-context (for the next progress call | ||
197 | * for this operation; should be set to NULL for | ||
198 | * SUSPEND and STOPPED events). The value returned | ||
199 | * will be passed to future callbacks in the respective | ||
200 | * field in the GNUNET_FS_ProgressInfo struct. | ||
201 | */ | ||
202 | static void * | ||
203 | progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) | ||
204 | { | ||
205 | const char *s; | ||
206 | char *suri; | ||
207 | |||
208 | switch (info->status) | ||
209 | { | ||
210 | case GNUNET_FS_STATUS_PUBLISH_START: | ||
211 | break; | ||
212 | |||
213 | case GNUNET_FS_STATUS_PUBLISH_PROGRESS: | ||
214 | if (verbose) | ||
215 | { | ||
216 | s = GNUNET_STRINGS_relative_time_to_string (info->value.publish.eta, | ||
217 | GNUNET_YES); | ||
218 | fprintf (stdout, | ||
219 | _ ("Publishing `%s' at %llu/%llu (%s remaining)\n"), | ||
220 | info->value.publish.filename, | ||
221 | (unsigned long long) info->value.publish.completed, | ||
222 | (unsigned long long) info->value.publish.size, | ||
223 | s); | ||
224 | } | ||
225 | break; | ||
226 | |||
227 | case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: | ||
228 | if (verbose) | ||
229 | { | ||
230 | s = GNUNET_STRINGS_relative_time_to_string (info->value.publish.specifics | ||
231 | .progress_directory.eta, | ||
232 | GNUNET_YES); | ||
233 | fprintf (stdout, | ||
234 | _ ("Publishing `%s' at %llu/%llu (%s remaining)\n"), | ||
235 | info->value.publish.filename, | ||
236 | (unsigned long long) | ||
237 | info->value.publish.specifics.progress_directory.completed, | ||
238 | (unsigned long long) | ||
239 | info->value.publish.specifics.progress_directory.total, | ||
240 | s); | ||
241 | } | ||
242 | break; | ||
243 | |||
244 | case GNUNET_FS_STATUS_PUBLISH_ERROR: | ||
245 | fprintf (stderr, | ||
246 | _ ("Error publishing: %s.\n"), | ||
247 | info->value.publish.specifics.error.message); | ||
248 | ret = 1; | ||
249 | GNUNET_SCHEDULER_shutdown (); | ||
250 | break; | ||
251 | |||
252 | case GNUNET_FS_STATUS_PUBLISH_COMPLETED: | ||
253 | fprintf (stdout, | ||
254 | _ ("Publishing `%s' done.\n"), | ||
255 | info->value.publish.filename); | ||
256 | suri = | ||
257 | GNUNET_FS_uri_to_string (info->value.publish.specifics.completed.chk_uri); | ||
258 | fprintf (stdout, _ ("URI is `%s'.\n"), suri); | ||
259 | GNUNET_free (suri); | ||
260 | if (NULL != info->value.publish.specifics.completed.sks_uri) | ||
261 | { | ||
262 | suri = GNUNET_FS_uri_to_string ( | ||
263 | info->value.publish.specifics.completed.sks_uri); | ||
264 | fprintf (stdout, _ ("Namespace URI is `%s'.\n"), suri); | ||
265 | GNUNET_free (suri); | ||
266 | } | ||
267 | if (NULL == info->value.publish.pctx) | ||
268 | { | ||
269 | ret = 0; | ||
270 | GNUNET_SCHEDULER_shutdown (); | ||
271 | } | ||
272 | break; | ||
273 | |||
274 | case GNUNET_FS_STATUS_PUBLISH_STOPPED: | ||
275 | GNUNET_break (NULL == pc); | ||
276 | return NULL; | ||
277 | |||
278 | case GNUNET_FS_STATUS_UNINDEX_START: | ||
279 | fprintf (stderr, "%s", _ ("Starting cleanup after abort\n")); | ||
280 | return NULL; | ||
281 | |||
282 | case GNUNET_FS_STATUS_UNINDEX_PROGRESS: | ||
283 | return NULL; | ||
284 | |||
285 | case GNUNET_FS_STATUS_UNINDEX_COMPLETED: | ||
286 | fprintf (stderr, "%s", _ ("Cleanup after abort completed.\n")); | ||
287 | GNUNET_FS_unindex_stop (info->value.unindex.uc); | ||
288 | return NULL; | ||
289 | |||
290 | case GNUNET_FS_STATUS_UNINDEX_ERROR: | ||
291 | fprintf (stderr, "%s", _ ("Cleanup after abort failed.\n")); | ||
292 | GNUNET_FS_unindex_stop (info->value.unindex.uc); | ||
293 | return NULL; | ||
294 | |||
295 | case GNUNET_FS_STATUS_UNINDEX_STOPPED: | ||
296 | return NULL; | ||
297 | |||
298 | default: | ||
299 | fprintf (stderr, _ ("Unexpected status: %d\n"), info->status); | ||
300 | return NULL; | ||
301 | } | ||
302 | return ""; /* non-null */ | ||
303 | } | ||
304 | |||
305 | |||
306 | /** | ||
307 | * Print metadata entries (except binary | ||
308 | * metadata and the filename). | ||
309 | * | ||
310 | * @param cls closure | ||
311 | * @param plugin_name name of the plugin that generated the meta data | ||
312 | * @param type type of the meta data | ||
313 | * @param format format of data | ||
314 | * @param data_mime_type mime type of @a data | ||
315 | * @param data value of the meta data | ||
316 | * @param data_size number of bytes in @a data | ||
317 | * @return always 0 | ||
318 | */ | ||
319 | static int | ||
320 | meta_printer (void *cls, | ||
321 | const char *plugin_name, | ||
322 | enum EXTRACTOR_MetaType type, | ||
323 | enum EXTRACTOR_MetaFormat format, | ||
324 | const char *data_mime_type, | ||
325 | const char *data, | ||
326 | size_t data_size) | ||
327 | { | ||
328 | if ((EXTRACTOR_METAFORMAT_UTF8 != format) && | ||
329 | (EXTRACTOR_METAFORMAT_C_STRING != format)) | ||
330 | return 0; | ||
331 | if (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type) | ||
332 | return 0; | ||
333 | #if HAVE_LIBEXTRACTOR | ||
334 | fprintf (stdout, "\t%s - %s\n", EXTRACTOR_metatype_to_string (type), data); | ||
335 | #else | ||
336 | fprintf (stdout, "\t%d - %s\n", type, data); | ||
337 | #endif | ||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Iterator printing keywords | ||
344 | * | ||
345 | * @param cls closure | ||
346 | * @param keyword the keyword | ||
347 | * @param is_mandatory is the keyword mandatory (in a search) | ||
348 | * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to abort | ||
349 | */ | ||
350 | static int | ||
351 | keyword_printer (void *cls, const char *keyword, int is_mandatory) | ||
352 | { | ||
353 | fprintf (stdout, "\t%s\n", keyword); | ||
354 | return GNUNET_OK; | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Function called on all entries before the publication. This is | ||
360 | * where we perform modifications to the default based on command-line | ||
361 | * options. | ||
362 | * | ||
363 | * @param cls closure | ||
364 | * @param fi the entry in the publish-structure | ||
365 | * @param length length of the file or directory | ||
366 | * @param m metadata for the file or directory (can be modified) | ||
367 | * @param uri pointer to the keywords that will be used for this entry (can be modified) | ||
368 | * @param bo block options | ||
369 | * @param do_index should we index? | ||
370 | * @param client_info pointer to client context set upon creation (can be modified) | ||
371 | * @return #GNUNET_OK to continue, #GNUNET_NO to remove | ||
372 | * this entry from the directory, #GNUNET_SYSERR | ||
373 | * to abort the iteration | ||
374 | */ | ||
375 | static int | ||
376 | publish_inspector (void *cls, | ||
377 | struct GNUNET_FS_FileInformation *fi, | ||
378 | uint64_t length, | ||
379 | struct GNUNET_CONTAINER_MetaData *m, | ||
380 | struct GNUNET_FS_Uri **uri, | ||
381 | struct GNUNET_FS_BlockOptions *bo, | ||
382 | int *do_index, | ||
383 | void **client_info) | ||
384 | { | ||
385 | char *fn; | ||
386 | char *fs; | ||
387 | struct GNUNET_FS_Uri *new_uri; | ||
388 | |||
389 | if (cls == fi) | ||
390 | return GNUNET_OK; | ||
391 | if ((disable_extractor) && (NULL != *uri)) | ||
392 | { | ||
393 | GNUNET_FS_uri_destroy (*uri); | ||
394 | *uri = NULL; | ||
395 | } | ||
396 | if (NULL != topKeywords) | ||
397 | { | ||
398 | if (NULL != *uri) | ||
399 | { | ||
400 | new_uri = GNUNET_FS_uri_ksk_merge (topKeywords, *uri); | ||
401 | GNUNET_FS_uri_destroy (*uri); | ||
402 | *uri = new_uri; | ||
403 | GNUNET_FS_uri_destroy (topKeywords); | ||
404 | } | ||
405 | else | ||
406 | { | ||
407 | *uri = topKeywords; | ||
408 | } | ||
409 | topKeywords = NULL; | ||
410 | } | ||
411 | if (NULL != meta) | ||
412 | { | ||
413 | GNUNET_CONTAINER_meta_data_merge (m, meta); | ||
414 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
415 | meta = NULL; | ||
416 | } | ||
417 | if (enable_creation_time) | ||
418 | GNUNET_CONTAINER_meta_data_add_publication_date (m); | ||
419 | if (extract_only) | ||
420 | { | ||
421 | fn = GNUNET_CONTAINER_meta_data_get_by_type ( | ||
422 | m, | ||
423 | EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); | ||
424 | fs = GNUNET_STRINGS_byte_size_fancy (length); | ||
425 | fprintf (stdout, _ ("Meta data for file `%s' (%s)\n"), fn, fs); | ||
426 | GNUNET_CONTAINER_meta_data_iterate (m, &meta_printer, NULL); | ||
427 | fprintf (stdout, _ ("Keywords for file `%s' (%s)\n"), fn, fs); | ||
428 | GNUNET_free (fn); | ||
429 | GNUNET_free (fs); | ||
430 | if (NULL != *uri) | ||
431 | GNUNET_FS_uri_ksk_get_keywords (*uri, &keyword_printer, NULL); | ||
432 | fprintf (stdout, "%s", "\n"); | ||
433 | } | ||
434 | if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (m)) | ||
435 | GNUNET_FS_file_information_inspect (fi, &publish_inspector, fi); | ||
436 | return GNUNET_OK; | ||
437 | } | ||
438 | |||
439 | |||
440 | /** | ||
441 | * Function called upon completion of the publishing | ||
442 | * of the UBLOCK for the SKS URI. As this is the last | ||
443 | * step, stop our interaction with FS (clean up). | ||
444 | * | ||
445 | * @param cls NULL (closure) | ||
446 | * @param sks_uri URI for the block that was published | ||
447 | * @param emsg error message, NULL on success | ||
448 | */ | ||
449 | static void | ||
450 | uri_sks_continuation (void *cls, | ||
451 | const struct GNUNET_FS_Uri *sks_uri, | ||
452 | const char *emsg) | ||
453 | { | ||
454 | if (NULL != emsg) | ||
455 | { | ||
456 | fprintf (stderr, "%s\n", emsg); | ||
457 | ret = 1; | ||
458 | } | ||
459 | GNUNET_SCHEDULER_shutdown (); | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Function called upon completion of the publishing | ||
465 | * of the UBLOCK for the KSK URI. Continue with | ||
466 | * publishing the SKS URI (if applicable) or clean up. | ||
467 | * | ||
468 | * @param cls NULL (closure) | ||
469 | * @param ksk_uri URI for the block that was published | ||
470 | * @param emsg error message, NULL on success | ||
471 | */ | ||
472 | static void | ||
473 | uri_ksk_continuation (void *cls, | ||
474 | const struct GNUNET_FS_Uri *ksk_uri, | ||
475 | const char *emsg) | ||
476 | { | ||
477 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; | ||
478 | const struct GNUNET_IDENTITY_PrivateKey *pk; | ||
479 | |||
480 | if (NULL != emsg) | ||
481 | { | ||
482 | fprintf (stderr, "%s\n", emsg); | ||
483 | ret = 1; | ||
484 | } | ||
485 | if (NULL == namespace) | ||
486 | { | ||
487 | GNUNET_SCHEDULER_shutdown (); | ||
488 | return; | ||
489 | } | ||
490 | pk = GNUNET_IDENTITY_ego_get_private_key (namespace); | ||
491 | if (GNUNET_IDENTITY_TYPE_ECDSA != ntohl (pk->type)) | ||
492 | return; | ||
493 | priv = &pk->ecdsa_key; | ||
494 | GNUNET_FS_publish_sks (ctx, | ||
495 | priv, | ||
496 | this_id, | ||
497 | next_id, | ||
498 | meta, | ||
499 | uri, | ||
500 | &bo, | ||
501 | GNUNET_FS_PUBLISH_OPTION_NONE, | ||
502 | &uri_sks_continuation, | ||
503 | NULL); | ||
504 | } | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Iterate over the results from the directory scan and extract | ||
509 | * the desired information for the publishing operation. | ||
510 | * | ||
511 | * @param item root with the data from the directory scan | ||
512 | * @return handle with the information for the publishing operation | ||
513 | */ | ||
514 | static struct GNUNET_FS_FileInformation * | ||
515 | get_file_information (struct GNUNET_FS_ShareTreeItem *item) | ||
516 | { | ||
517 | struct GNUNET_FS_FileInformation *fi; | ||
518 | struct GNUNET_FS_FileInformation *fic; | ||
519 | struct GNUNET_FS_ShareTreeItem *child; | ||
520 | |||
521 | if (GNUNET_YES == item->is_directory) | ||
522 | { | ||
523 | if (NULL == item->meta) | ||
524 | item->meta = GNUNET_CONTAINER_meta_data_create (); | ||
525 | GNUNET_CONTAINER_meta_data_delete (item->meta, | ||
526 | EXTRACTOR_METATYPE_MIMETYPE, | ||
527 | NULL, | ||
528 | 0); | ||
529 | GNUNET_FS_meta_data_make_directory (item->meta); | ||
530 | if (NULL == item->ksk_uri) | ||
531 | { | ||
532 | const char *mime = GNUNET_FS_DIRECTORY_MIME; | ||
533 | item->ksk_uri = GNUNET_FS_uri_ksk_create_from_args (1, &mime); | ||
534 | } | ||
535 | else | ||
536 | GNUNET_FS_uri_ksk_add_keyword (item->ksk_uri, | ||
537 | GNUNET_FS_DIRECTORY_MIME, | ||
538 | GNUNET_NO); | ||
539 | fi = GNUNET_FS_file_information_create_empty_directory (ctx, | ||
540 | NULL, | ||
541 | item->ksk_uri, | ||
542 | item->meta, | ||
543 | &bo, | ||
544 | item->filename); | ||
545 | for (child = item->children_head; child; child = child->next) | ||
546 | { | ||
547 | fic = get_file_information (child); | ||
548 | GNUNET_break (GNUNET_OK == GNUNET_FS_file_information_add (fi, fic)); | ||
549 | } | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | fi = GNUNET_FS_file_information_create_from_file (ctx, | ||
554 | NULL, | ||
555 | item->filename, | ||
556 | item->ksk_uri, | ||
557 | item->meta, | ||
558 | ! do_insert, | ||
559 | &bo); | ||
560 | } | ||
561 | return fi; | ||
562 | } | ||
563 | |||
564 | |||
565 | /** | ||
566 | * We've finished scanning the directory and optimized the meta data. | ||
567 | * Begin the publication process. | ||
568 | * | ||
569 | * @param directory_scan_result result from the directory scan, freed in this function | ||
570 | */ | ||
571 | static void | ||
572 | directory_trim_complete (struct GNUNET_FS_ShareTreeItem *directory_scan_result) | ||
573 | { | ||
574 | struct GNUNET_FS_FileInformation *fi; | ||
575 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; | ||
576 | const struct GNUNET_IDENTITY_PrivateKey *pk; | ||
577 | |||
578 | fi = get_file_information (directory_scan_result); | ||
579 | GNUNET_FS_share_tree_free (directory_scan_result); | ||
580 | if (NULL == fi) | ||
581 | { | ||
582 | fprintf (stderr, "%s", _ ("Could not publish\n")); | ||
583 | ret = 1; | ||
584 | GNUNET_SCHEDULER_shutdown (); | ||
585 | return; | ||
586 | } | ||
587 | GNUNET_FS_file_information_inspect (fi, &publish_inspector, NULL); | ||
588 | if (extract_only) | ||
589 | { | ||
590 | GNUNET_FS_file_information_destroy (fi, NULL, NULL); | ||
591 | GNUNET_SCHEDULER_shutdown (); | ||
592 | return; | ||
593 | } | ||
594 | priv = NULL; | ||
595 | if (NULL != namespace) | ||
596 | { | ||
597 | pk = GNUNET_IDENTITY_ego_get_private_key (namespace); | ||
598 | GNUNET_assert (GNUNET_IDENTITY_TYPE_ECDSA == ntohl (pk->type)); | ||
599 | priv = &pk->ecdsa_key; | ||
600 | } | ||
601 | pc = GNUNET_FS_publish_start (ctx, | ||
602 | fi, | ||
603 | priv, | ||
604 | this_id, | ||
605 | next_id, | ||
606 | (do_simulate) | ||
607 | ? GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY | ||
608 | : GNUNET_FS_PUBLISH_OPTION_NONE); | ||
609 | if (NULL == pc) | ||
610 | { | ||
611 | fprintf (stderr, "%s", _ ("Could not start publishing.\n")); | ||
612 | ret = 1; | ||
613 | GNUNET_SCHEDULER_shutdown (); | ||
614 | return; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Function called by the directory scanner as we build the tree | ||
621 | * that we will need to publish later. | ||
622 | * | ||
623 | * @param cls closure | ||
624 | * @param filename which file we are making progress on | ||
625 | * @param is_directory #GNUNET_YES if this is a directory, | ||
626 | * #GNUNET_NO if this is a file | ||
627 | * #GNUNET_SYSERR if it is neither (or unknown) | ||
628 | * @param reason kind of progress we are making | ||
629 | */ | ||
630 | static void | ||
631 | directory_scan_cb (void *cls, | ||
632 | const char *filename, | ||
633 | int is_directory, | ||
634 | enum GNUNET_FS_DirScannerProgressUpdateReason reason) | ||
635 | { | ||
636 | struct GNUNET_FS_ShareTreeItem *directory_scan_result; | ||
637 | |||
638 | switch (reason) | ||
639 | { | ||
640 | case GNUNET_FS_DIRSCANNER_FILE_START: | ||
641 | if (verbose > 1) | ||
642 | { | ||
643 | if (is_directory == GNUNET_YES) | ||
644 | fprintf (stdout, _ ("Scanning directory `%s'.\n"), filename); | ||
645 | else | ||
646 | fprintf (stdout, _ ("Scanning file `%s'.\n"), filename); | ||
647 | } | ||
648 | break; | ||
649 | |||
650 | case GNUNET_FS_DIRSCANNER_FILE_IGNORED: | ||
651 | fprintf (stderr, | ||
652 | _ ("There was trouble processing file `%s', skipping it.\n"), | ||
653 | filename); | ||
654 | break; | ||
655 | |||
656 | case GNUNET_FS_DIRSCANNER_ALL_COUNTED: | ||
657 | if (verbose) | ||
658 | fprintf (stdout, "%s", _ ("Preprocessing complete.\n")); | ||
659 | break; | ||
660 | |||
661 | case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED: | ||
662 | if (verbose > 2) | ||
663 | fprintf (stdout, | ||
664 | _ ("Extracting meta data from file `%s' complete.\n"), | ||
665 | filename); | ||
666 | break; | ||
667 | |||
668 | case GNUNET_FS_DIRSCANNER_FINISHED: | ||
669 | if (verbose > 1) | ||
670 | fprintf (stdout, "%s", _ ("Meta data extraction has finished.\n")); | ||
671 | directory_scan_result = GNUNET_FS_directory_scan_get_result (ds); | ||
672 | ds = NULL; | ||
673 | GNUNET_FS_share_tree_trim (directory_scan_result); | ||
674 | directory_trim_complete (directory_scan_result); | ||
675 | break; | ||
676 | |||
677 | case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: | ||
678 | fprintf (stdout, "%s", _ ("Error scanning directory.\n")); | ||
679 | ret = 1; | ||
680 | GNUNET_SCHEDULER_shutdown (); | ||
681 | break; | ||
682 | |||
683 | default: | ||
684 | GNUNET_assert (0); | ||
685 | break; | ||
686 | } | ||
687 | fflush (stdout); | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Continuation proceeding with initialization after identity subsystem | ||
693 | * has been initialized. | ||
694 | * | ||
695 | * @param args0 filename to publish | ||
696 | */ | ||
697 | static void | ||
698 | identity_continuation (const char *args0) | ||
699 | { | ||
700 | char *ex; | ||
701 | char *emsg; | ||
702 | |||
703 | if ((NULL != pseudonym) && (NULL == namespace)) | ||
704 | { | ||
705 | fprintf (stderr, _ ("Selected pseudonym `%s' unknown\n"), pseudonym); | ||
706 | ret = 1; | ||
707 | GNUNET_SCHEDULER_shutdown (); | ||
708 | return; | ||
709 | } | ||
710 | if (NULL != uri_string) | ||
711 | { | ||
712 | emsg = NULL; | ||
713 | if (NULL == (uri = GNUNET_FS_uri_parse (uri_string, &emsg))) | ||
714 | { | ||
715 | fprintf (stderr, _ ("Failed to parse URI: %s\n"), emsg); | ||
716 | GNUNET_free (emsg); | ||
717 | ret = 1; | ||
718 | GNUNET_SCHEDULER_shutdown (); | ||
719 | return; | ||
720 | } | ||
721 | GNUNET_FS_publish_ksk (ctx, | ||
722 | topKeywords, | ||
723 | meta, | ||
724 | uri, | ||
725 | &bo, | ||
726 | GNUNET_FS_PUBLISH_OPTION_NONE, | ||
727 | &uri_ksk_continuation, | ||
728 | NULL); | ||
729 | return; | ||
730 | } | ||
731 | if (GNUNET_OK != | ||
732 | GNUNET_CONFIGURATION_get_value_string (cfg, "FS", "EXTRACTORS", &ex)) | ||
733 | ex = NULL; | ||
734 | if (0 != access (args0, R_OK)) | ||
735 | { | ||
736 | fprintf (stderr, | ||
737 | _ ("Failed to access `%s': %s\n"), | ||
738 | args0, | ||
739 | strerror (errno)); | ||
740 | GNUNET_free (ex); | ||
741 | return; | ||
742 | } | ||
743 | ds = GNUNET_FS_directory_scan_start (args0, | ||
744 | disable_extractor, | ||
745 | ex, | ||
746 | &directory_scan_cb, | ||
747 | NULL); | ||
748 | if (NULL == ds) | ||
749 | { | ||
750 | fprintf ( | ||
751 | stderr, | ||
752 | "%s", | ||
753 | _ ( | ||
754 | "Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed?\n")); | ||
755 | GNUNET_free (ex); | ||
756 | return; | ||
757 | } | ||
758 | GNUNET_free (ex); | ||
759 | } | ||
760 | |||
761 | |||
762 | /** | ||
763 | * Function called by identity service with known pseudonyms. | ||
764 | * | ||
765 | * @param cls closure with 'const char *' of filename to publish | ||
766 | * @param ego ego handle | ||
767 | * @param ctx context for application to store data for this ego | ||
768 | * (during the lifetime of this process, initially NULL) | ||
769 | * @param name name assigned by the user for this ego, | ||
770 | * NULL if the user just deleted the ego and it | ||
771 | * must thus no longer be used | ||
772 | */ | ||
773 | static void | ||
774 | identity_cb (void *cls, | ||
775 | struct GNUNET_IDENTITY_Ego *ego, | ||
776 | void **ctx, | ||
777 | const char *name) | ||
778 | { | ||
779 | const char *args0 = cls; | ||
780 | |||
781 | if (NULL == ego) | ||
782 | { | ||
783 | identity_continuation (args0); | ||
784 | return; | ||
785 | } | ||
786 | if (NULL == name) | ||
787 | return; | ||
788 | if (0 == strcmp (name, pseudonym)) | ||
789 | namespace = ego; | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Main function that will be run by the scheduler. | ||
795 | * | ||
796 | * @param cls closure | ||
797 | * @param args remaining command-line arguments | ||
798 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
799 | * @param c configuration | ||
800 | */ | ||
801 | static void | ||
802 | run (void *cls, | ||
803 | char *const *args, | ||
804 | const char *cfgfile, | ||
805 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
806 | { | ||
807 | /* check arguments */ | ||
808 | if ((NULL != uri_string) && (extract_only)) | ||
809 | { | ||
810 | printf (_ ("Cannot extract metadata from a URI!\n")); | ||
811 | ret = -1; | ||
812 | return; | ||
813 | } | ||
814 | if (((NULL == uri_string) || (extract_only)) && | ||
815 | ((NULL == args[0]) || (NULL != args[1]))) | ||
816 | { | ||
817 | printf (_ ("You must specify one and only one filename for insertion.\n")); | ||
818 | ret = -1; | ||
819 | return; | ||
820 | } | ||
821 | if ((NULL != uri_string) && (NULL != args[0])) | ||
822 | { | ||
823 | printf (_ ("You must NOT specify an URI and a filename.\n")); | ||
824 | ret = -1; | ||
825 | return; | ||
826 | } | ||
827 | if (NULL != pseudonym) | ||
828 | { | ||
829 | if (NULL == this_id) | ||
830 | { | ||
831 | fprintf (stderr, | ||
832 | _ ("Option `%s' is required when using option `%s'.\n"), | ||
833 | "-t", | ||
834 | "-P"); | ||
835 | ret = -1; | ||
836 | return; | ||
837 | } | ||
838 | } | ||
839 | else | ||
840 | { /* ordinary insertion checks */ | ||
841 | if (NULL != next_id) | ||
842 | { | ||
843 | fprintf (stderr, | ||
844 | _ ("Option `%s' makes no sense without option `%s'.\n"), | ||
845 | "-N", | ||
846 | "-P"); | ||
847 | ret = -1; | ||
848 | return; | ||
849 | } | ||
850 | if (NULL != this_id) | ||
851 | { | ||
852 | fprintf (stderr, | ||
853 | _ ("Option `%s' makes no sense without option `%s'.\n"), | ||
854 | "-t", | ||
855 | "-P"); | ||
856 | ret = -1; | ||
857 | return; | ||
858 | } | ||
859 | } | ||
860 | cfg = c; | ||
861 | ctx = GNUNET_FS_start (cfg, | ||
862 | "gnunet-publish", | ||
863 | &progress_cb, | ||
864 | NULL, | ||
865 | GNUNET_FS_FLAGS_NONE, | ||
866 | GNUNET_FS_OPTIONS_END); | ||
867 | if (NULL == ctx) | ||
868 | { | ||
869 | fprintf (stderr, _ ("Could not initialize `%s' subsystem.\n"), "FS"); | ||
870 | ret = 1; | ||
871 | return; | ||
872 | } | ||
873 | GNUNET_SCHEDULER_add_shutdown (&do_stop_task, NULL); | ||
874 | if (NULL != pseudonym) | ||
875 | identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, args[0]); | ||
876 | else | ||
877 | identity_continuation (args[0]); | ||
878 | } | ||
879 | |||
880 | |||
881 | /** | ||
882 | * The main function to publish content to GNUnet. | ||
883 | * | ||
884 | * @param argc number of arguments from the command line | ||
885 | * @param argv command line arguments | ||
886 | * @return 0 ok, 1 on error | ||
887 | */ | ||
888 | int | ||
889 | main (int argc, char *const *argv) | ||
890 | { | ||
891 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
892 | { GNUNET_GETOPT_option_uint ('a', | ||
893 | "anonymity", | ||
894 | "LEVEL", | ||
895 | gettext_noop ( | ||
896 | "set the desired LEVEL of sender-anonymity"), | ||
897 | &bo.anonymity_level), | ||
898 | GNUNET_GETOPT_option_flag ( | ||
899 | 'D', | ||
900 | "disable-extractor", | ||
901 | gettext_noop ("do not use libextractor to add keywords or metadata"), | ||
902 | &disable_extractor), | ||
903 | GNUNET_GETOPT_option_flag ('E', | ||
904 | "enable-creation-time", | ||
905 | gettext_noop ( | ||
906 | "enable adding the creation time to the " | ||
907 | "metadata of the uploaded file"), | ||
908 | &enable_creation_time), | ||
909 | GNUNET_GETOPT_option_flag ('e', | ||
910 | "extract", | ||
911 | gettext_noop ( | ||
912 | "print list of extracted keywords that would " | ||
913 | "be used, but do not perform upload"), | ||
914 | &extract_only), | ||
915 | GNUNET_FS_GETOPT_KEYWORDS ( | ||
916 | 'k', | ||
917 | "key", | ||
918 | "KEYWORD", | ||
919 | gettext_noop ( | ||
920 | "add an additional keyword for the top-level " | ||
921 | "file or directory (this option can be specified multiple times)"), | ||
922 | &topKeywords), | ||
923 | GNUNET_FS_GETOPT_METADATA ( | ||
924 | 'm', | ||
925 | "meta", | ||
926 | "TYPE:VALUE", | ||
927 | gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), | ||
928 | &meta), | ||
929 | GNUNET_GETOPT_option_flag ( | ||
930 | 'n', | ||
931 | "noindex", | ||
932 | gettext_noop ("do not index, perform full insertion (stores " | ||
933 | "entire file in encrypted form in GNUnet database)"), | ||
934 | &do_insert), | ||
935 | GNUNET_GETOPT_option_string ( | ||
936 | 'N', | ||
937 | "next", | ||
938 | "ID", | ||
939 | gettext_noop ("specify ID of an updated version to be " | ||
940 | "published in the future (for namespace insertions only)"), | ||
941 | &next_id), | ||
942 | GNUNET_GETOPT_option_uint ('p', | ||
943 | "priority", | ||
944 | "PRIORITY", | ||
945 | gettext_noop ( | ||
946 | "specify the priority of the content"), | ||
947 | &bo.content_priority), | ||
948 | GNUNET_GETOPT_option_string ('P', | ||
949 | "pseudonym", | ||
950 | "NAME", | ||
951 | gettext_noop ( | ||
952 | "publish the files under the pseudonym " | ||
953 | "NAME (place file into namespace)"), | ||
954 | &pseudonym), | ||
955 | GNUNET_GETOPT_option_uint ('r', | ||
956 | "replication", | ||
957 | "LEVEL", | ||
958 | gettext_noop ( | ||
959 | "set the desired replication LEVEL"), | ||
960 | &bo.replication_level), | ||
961 | GNUNET_GETOPT_option_flag ('s', | ||
962 | "simulate-only", | ||
963 | gettext_noop ( | ||
964 | "only simulate the process but do not do " | ||
965 | "any actual publishing (useful to compute URIs)"), | ||
966 | &do_simulate), | ||
967 | GNUNET_GETOPT_option_string ('t', | ||
968 | "this", | ||
969 | "ID", | ||
970 | gettext_noop ( | ||
971 | "set the ID of this version of the publication " | ||
972 | "(for namespace insertions only)"), | ||
973 | &this_id), | ||
974 | GNUNET_GETOPT_option_string ( | ||
975 | 'u', | ||
976 | "uri", | ||
977 | "URI", | ||
978 | gettext_noop ( | ||
979 | "URI to be published (can be used instead of passing a " | ||
980 | "file to add keywords to the file with the respective URI)"), | ||
981 | &uri_string), | ||
982 | |||
983 | GNUNET_GETOPT_option_verbose (&verbose), | ||
984 | |||
985 | GNUNET_GETOPT_OPTION_END }; | ||
986 | |||
987 | bo.expiration_time = | ||
988 | GNUNET_TIME_year_to_time (GNUNET_TIME_get_current_year () + 2); | ||
989 | |||
990 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
991 | return 2; | ||
992 | ret = | ||
993 | (GNUNET_OK == | ||
994 | GNUNET_PROGRAM_run (argc, | ||
995 | argv, | ||
996 | "gnunet-publish [OPTIONS] FILENAME", | ||
997 | gettext_noop ("Publish a file or directory on GNUnet"), | ||
998 | options, | ||
999 | &run, | ||
1000 | NULL)) | ||
1001 | ? ret | ||
1002 | : 1; | ||
1003 | GNUNET_free_nz ((void *) argv); | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | /* end of gnunet-publish.c */ | ||