cbd9339c9bfd112b83f230378811a1b060031196
[oweals/gnunet.git] / src / fs / fs_getopt.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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
19 /**
20  * @file fs/fs_getopt.c
21  * @brief helper functions for command-line argument processing
22  * @author Igor Wronsky, Christian Grothoff
23  */
24 #include "platform.h"
25 #include "gnunet_fs_service.h"
26 #include "gnunet_getopt_lib.h"
27 #include "fs_api.h"
28
29 /* ******************** command-line option parsing API ******************** */
30
31 /**
32  * Command-line option parser function that allows the user
33  * to specify one or more '-k' options with keywords.  Each
34  * specified keyword will be added to the URI.  A pointer to
35  * the URI must be passed as the "scls" argument.
36  *
37  * @param ctx command line processor context
38  * @param scls must be of type "struct GNUNET_FS_Uri **"
39  * @param option name of the option (typically 'k')
40  * @param value command line argument given
41  * @return #GNUNET_OK on success
42  */
43 static int
44 getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
45                      void *scls,
46                      const char *option,
47                      const char *value)
48 {
49   struct GNUNET_FS_Uri **uri = scls;
50   struct GNUNET_FS_Uri *u = *uri;
51   char *val;
52   size_t slen;
53
54   if (NULL == u)
55   {
56     u = GNUNET_new (struct GNUNET_FS_Uri);
57     *uri = u;
58     u->type = GNUNET_FS_URI_KSK;
59     u->data.ksk.keywordCount = 0;
60     u->data.ksk.keywords = NULL;
61   }
62   else
63   {
64     GNUNET_assert (GNUNET_FS_URI_KSK == u->type);
65   }
66   slen = strlen (value);
67   if (0 == slen)
68     return GNUNET_SYSERR;       /* cannot be empty */
69   if (value[0] == '+')
70   {
71     /* simply preserve the "mandatory" flag */
72     if (slen < 2)
73       return GNUNET_SYSERR;     /* empty keywords not allowed */
74     if ((value[1] == '"') && (slen > 3) && (value[slen - 1] == '"'))
75     {
76       /* remove the quotes, keep the '+' */
77       val = GNUNET_malloc (slen - 1);
78       val[0] = '+';
79       GNUNET_memcpy (&val[1],
80                      &value[2],
81                      slen - 3);
82       val[slen - 2] = '\0';
83     }
84     else
85     {
86       /* no quotes, just keep the '+' */
87       val = GNUNET_strdup (value);
88     }
89   }
90   else
91   {
92     if ((value[0] == '"') && (slen > 2) && (value[slen - 1] == '"'))
93     {
94       /* remove the quotes, add a space */
95       val = GNUNET_malloc (slen);
96       val[0] = ' ';
97       GNUNET_memcpy (&val[1],
98                      &value[1],
99                      slen - 2);
100       val[slen - 1] = '\0';
101     }
102     else
103     {
104       /* add a space to indicate "not mandatory" */
105       val = GNUNET_malloc (slen + 2);
106       strcpy (val, " ");
107       strcat (val, value);
108     }
109   }
110   GNUNET_array_append (u->data.ksk.keywords,
111                        u->data.ksk.keywordCount,
112                        val);
113   return GNUNET_OK;
114 }
115
116
117 /**
118  * Allow user to specify keywords.
119  *
120  * @param shortName short name of the option
121  * @param name long name of the option
122  * @param argumentHelp help text for the option argument
123  * @param description long help text for the option
124  * @param[out] topKeywords set to the desired value
125  */
126 struct GNUNET_GETOPT_CommandLineOption
127 GNUNET_FS_GETOPT_KEYWORDS (char shortName,
128                            const char *name,
129                            const char *argumentHelp,
130                            const char *description,
131                            struct GNUNET_FS_Uri **topKeywords)
132 {
133   struct GNUNET_GETOPT_CommandLineOption clo = {
134     .shortName = shortName,
135     .name = name,
136     .argumentHelp = argumentHelp,
137     .description = description,
138     .require_argument = 1,
139     .processor = &getopt_set_keywords,
140     .scls = (void *) topKeywords  
141   };
142
143   return clo;
144 }
145
146
147 /**
148  * Command-line option parser function that allows the user to specify
149  * one or more '-m' options with metadata.  Each specified entry of
150  * the form "type=value" will be added to the metadata.  A pointer to
151  * the metadata must be passed as the "scls" argument.
152  *
153  * @param ctx command line processor context
154  * @param scls must be of type "struct GNUNET_MetaData **"
155  * @param option name of the option (typically 'k')
156  * @param value command line argument given
157  * @return #GNUNET_OK on success
158  */
159 static int
160 getopt_set_metadata (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
161                      void *scls,
162                      const char *option,
163                      const char *value)
164 {
165   struct GNUNET_CONTAINER_MetaData **mm = scls;
166 #if HAVE_EXTRACTOR_H && HAVE_LIBEXTRACTOR
167   enum EXTRACTOR_MetaType type;
168   const char *typename;
169   const char *typename_i18n;
170 #endif
171   struct GNUNET_CONTAINER_MetaData *meta;
172   char *tmp;
173
174   meta = *mm;
175   if (meta == NULL)
176   {
177     meta = GNUNET_CONTAINER_meta_data_create ();
178     *mm = meta;
179   }
180
181   /* Use GNUNET_STRINGS_get_utf8_args() in main() to acquire utf-8-encoded
182    * commandline arguments, so that the following line is not needed.
183    */
184   /*tmp = GNUNET_STRINGS_to_utf8 (value, strlen (value), locale_charset ());*/
185   tmp = GNUNET_strdup (value);
186 #if HAVE_EXTRACTOR_H && HAVE_LIBEXTRACTOR
187   type = EXTRACTOR_metatype_get_max ();
188   while (type > 0)
189   {
190     type--;
191     typename = EXTRACTOR_metatype_to_string (type);
192     typename_i18n = dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, typename);
193     if ((strlen (tmp) >= strlen (typename) + 1) &&
194         (tmp[strlen (typename)] == ':') &&
195         (0 == strncmp (typename, tmp, strlen (typename))))
196     {
197       GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", type,
198                                          EXTRACTOR_METAFORMAT_UTF8,
199                                          "text/plain",
200                                          &tmp[strlen (typename) + 1],
201                                          strlen (&tmp[strlen (typename) + 1]) +
202                                          1);
203       GNUNET_free (tmp);
204       tmp = NULL;
205       break;
206     }
207     if ((strlen (tmp) >= strlen (typename_i18n) + 1) &&
208         (tmp[strlen (typename_i18n)] == ':') &&
209         (0 == strncmp (typename_i18n, tmp, strlen (typename_i18n))))
210     {
211       GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", type,
212                                          EXTRACTOR_METAFORMAT_UTF8,
213                                          "text/plain",
214                                          &tmp[strlen (typename_i18n) + 1],
215                                          strlen (&tmp
216                                                  [strlen (typename_i18n) + 1]) +
217                                          1);
218       GNUNET_free (tmp);
219       tmp = NULL;
220       break;
221     }
222   }
223 #endif
224
225   if (NULL != tmp)
226   {
227     GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>",
228                                        EXTRACTOR_METATYPE_UNKNOWN,
229                                        EXTRACTOR_METAFORMAT_UTF8, "text/plain",
230                                        tmp, strlen (tmp) + 1);
231     GNUNET_free (tmp);
232     printf (_
233             ("Unknown metadata type in metadata option `%s'.  Using metadata type `unknown' instead.\n"),
234             value);
235   }
236   return GNUNET_OK;
237 }
238
239 /**
240  * Allow user to specify metadata.
241  *
242  * @param shortName short name of the option
243  * @param name long name of the option
244  * @param argumentHelp help text for the option argument
245  * @param description long help text for the option
246  * @param[out] metadata set to the desired value
247  */
248 struct GNUNET_GETOPT_CommandLineOption
249 GNUNET_FS_GETOPT_METADATA (char shortName,
250                            const char *name,
251                            const char *argumentHelp,
252                            const char *description,
253                            struct GNUNET_CONTAINER_MetaData **meta)
254 {
255   struct GNUNET_GETOPT_CommandLineOption clo = {
256     .shortName = shortName,
257     .name = name,
258     .argumentHelp = argumentHelp,
259     .description = description,
260     .require_argument = 1,
261     .processor = &getopt_set_metadata,
262     .scls = (void *) meta
263   };
264
265   return clo;
266 }
267
268
269
270
271 /* end of fs_getopt.c */