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