source: XIOS/dev/dev_olga/extern/src_netcdf4/nc_uri.c @ 1620

Last change on this file since 1620 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 11.8 KB
Line 
1/*********************************************************************
2 *   Copyright 2010, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header$
5 *********************************************************************/
6
7#include "config.h"
8
9#include <stdlib.h>
10#include <string.h>
11#include <stdio.h>
12
13#include "nc_uri.h"
14
15#define NC_URIDEBUG
16
17#define LBRACKET '['
18#define RBRACKET ']'
19
20#ifndef FIX
21#define FIX(s) ((s)==NULL?"":(s))
22#endif
23
24#ifndef NILLEN
25#define NILLEN(s) ((s)==NULL?0:strlen(s))
26#endif
27
28
29static char* legalprotocols[] = {
30"file:",
31"http:",
32"https:",
33"ftp:",
34NULL /* NULL terminate*/
35};
36
37static void nc_paramfree(char** params);
38static int nc_find(char** params, const char* key);
39
40/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
41int
42nc_uriparse(const char* uri0, NC_URI** nc_urip)
43{
44    NC_URI* nc_uri = NULL;
45    char* uri;
46    char** pp;
47    char* p;
48    char* p1;
49    int c;
50
51    /* accumulate parse points*/
52    char* protocol = NULL;
53    char* params = NULL;
54    char* host = NULL;
55    char* port = NULL;
56    char* constraint = NULL;
57    char* user = NULL;
58    char* pwd = NULL;
59    char* file = NULL;
60
61    nc_uri = (NC_URI*)calloc(1,sizeof(NC_URI));
62    if(nc_uri == NULL) return 0;   
63
64    /* Temporary hack to remove escape characters inserted by Windows or MinGW */
65    if(strchr(uri0,'\\') != NULL) {   
66        char* u = strdup(uri0);
67        if(u == NULL) return 0;
68        p = u;
69        p1 = u;
70        while((c=*p1++)) {if(c != '\\') *p++ = c;}
71        uri0 = (const char*)u;
72    }
73
74    /* make local copy of uri */
75    uri = strdup(uri0);
76
77    /* remove all whitespace*/
78    p = uri;
79    p1 = uri;
80    while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
81
82    p = uri;
83
84    /* break up the uri string into pieces*/
85
86    /* 1. leading bracketed parameters */
87    if(*p == LBRACKET) {
88        params = p+1;
89        /* find end of the clientparams*/
90        for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
91        if(*p == 0) goto fail; /* malformed client params*/
92        *p = '\0'; /* leave off the trailing rbracket for now */
93        p++; /* move past the params*/
94    }
95
96    /* verify that the uri starts with an acceptable protocol*/
97    for(pp=legalprotocols;*pp;pp++) {
98        if(strncmp(p,*pp,strlen(*pp))==0) break;
99    }
100    if(*pp == NULL) goto fail; /* illegal protocol*/
101    /* save the protocol */
102    protocol = *pp;
103
104    /* 4. skip protocol */
105    p += strlen(protocol);
106
107    /* 5. skip // */
108    if(*p != '/' && *(p+1) != '/')
109        goto fail;
110    p += 2;
111
112    /* 6. Mark the end of the host section */
113    file = strchr(p,'/');
114    if(file) {
115        *file++ = '\0'; /* warning: we just overwrote the leading / */
116    } else
117        goto fail; /* url only has host part, no path */
118
119    /* 7. extract any user:pwd */
120    p1 = strchr(p,'@');
121    if(p1) {/* Assume we have user:pwd@ */
122        *p1 = '\0';
123        user = p;
124        pwd = strchr(p,':');
125        if(!pwd) goto fail; /* malformed */
126        *pwd++ = '\0';
127        p = pwd+strlen(pwd)+1;
128    }
129
130    /* 8. extract host and port */
131    host = p;
132    port = strchr(p,':');
133    if(port) {
134        *port++ = '\0';
135    }
136
137    /* 9. Look for '?' */
138    constraint = strchr(file,'?');
139    if(constraint) {
140        *constraint++ = '\0';
141    }
142
143    /* assemble the component pieces*/
144    if(uri0 && strlen(uri0) > 0)
145        nc_uri->uri = strdup(uri0);
146    if(protocol && strlen(protocol) > 0) {
147        nc_uri->protocol = strdup(protocol);
148        /* remove trailing ':' */
149        nc_uri->protocol[strlen(protocol)-1] = '\0';
150    }
151    if(user && strlen(user) > 0)
152        nc_uri->user = strdup(user);
153    if(pwd && strlen(pwd) > 0)
154        nc_uri->password = strdup(pwd);
155    if(host && strlen(host) > 0)
156        nc_uri->host = strdup(host);
157    if(port && strlen(port) > 0)
158        nc_uri->port = strdup(port);
159    if(file && strlen(file) > 0) {
160        /* Add back the leading / */
161        nc_uri->file = malloc(strlen(file)+2);
162        strcpy(nc_uri->file,"/");
163        strcat(nc_uri->file,file);
164    }
165    if(constraint && strlen(constraint) > 0)
166        nc_uri->constraint = strdup(constraint);
167    nc_urisetconstraints(nc_uri,constraint);
168    if(params != NULL && strlen(params) > 0) {
169        nc_uri->params = (char*)malloc(1+2+strlen(params));
170        strcpy(nc_uri->params,"[");
171        strcat(nc_uri->params,params);
172        strcat(nc_uri->params,"]");
173    }
174
175#ifdef NC_XDEBUG
176        {
177        fprintf(stderr,"nc_uri:");
178        fprintf(stderr," params=|%s|",FIX(nc_uri->params));
179        fprintf(stderr," protocol=|%s|",FIX(nc_uri->protocol));
180        fprintf(stderr," host=|%s|",FIX(nc_uri->host));
181        fprintf(stderr," port=|%s|",FIX(nc_uri->port));
182        fprintf(stderr," file=|%s|",FIX(nc_uri->file));
183        fprintf(stderr," constraint=|%s|",FIX(nc_uri->constraint));
184        fprintf(stderr,"\n");
185    }
186#endif
187    free(uri);
188    if(nc_urip != NULL) *nc_urip = nc_uri;
189    return 1;
190
191fail:
192    if(nc_uri) nc_urifree(nc_uri);
193    if(uri != NULL) free(uri);
194    return 0;
195}
196
197void
198nc_urifree(NC_URI* nc_uri)
199{
200    if(nc_uri == NULL) return;
201    if(nc_uri->uri != NULL) {free(nc_uri->uri);}
202    if(nc_uri->protocol != NULL) {free(nc_uri->protocol);}
203    if(nc_uri->user != NULL) {free(nc_uri->user);}
204    if(nc_uri->password != NULL) {free(nc_uri->password);}
205    if(nc_uri->host != NULL) {free(nc_uri->host);}
206    if(nc_uri->port != NULL) {free(nc_uri->port);}
207    if(nc_uri->file != NULL) {free(nc_uri->file);}
208    if(nc_uri->constraint != NULL) {free(nc_uri->constraint);}
209    if(nc_uri->projection != NULL) {free(nc_uri->projection);}
210    if(nc_uri->selection != NULL) {free(nc_uri->selection);}
211    if(nc_uri->params != NULL) {free(nc_uri->params);}
212    if(nc_uri->paramlist != NULL) nc_paramfree(nc_uri->paramlist);
213    free(nc_uri);
214}
215
216/* Replace the constraints */
217void
218nc_urisetconstraints(NC_URI* duri,const char* constraints)
219{
220    char* proj = NULL;
221    char* select = NULL;
222    const char* p;
223
224    if(duri->constraint == NULL) free(duri->constraint);
225    if(duri->projection != NULL) free(duri->projection);
226    if(duri->selection != NULL) free(duri->selection);
227    duri->constraint = NULL;   
228    duri->projection = NULL;   
229    duri->selection = NULL;
230
231    if(constraints == NULL || strlen(constraints)==0) return;
232
233    duri->constraint = strdup(constraints);
234    if(*duri->constraint == '?')
235        strcpy(duri->constraint,duri->constraint+1);
236
237    p = duri->constraint;
238    proj = (char*) p;
239    select = strchr(proj,'&');
240    if(select != NULL) {
241        size_t plen = (select - proj);
242        if(plen == 0) {
243            proj = NULL;
244        } else {
245            proj = (char*)malloc(plen+1);
246            memcpy((void*)proj,p,plen);
247            proj[plen] = '\0';
248        }
249        select = nulldup(select);
250    } else {
251        proj = nulldup(proj);
252        select = NULL;
253    }
254    duri->projection = proj;
255    duri->selection = select;
256}
257
258
259/* Construct a complete NC_ URI without the client params
260   and optionally with the constraints;
261   caller frees returned string
262*/
263
264char*
265nc_uribuild(NC_URI* duri, const char* prefix, const char* suffix, int pieces)
266{
267    size_t len = 0;
268    char* newuri;
269    int withparams = ((pieces&NC_URIPARAMS)
270                        && duri->params != NULL);
271    int withuserpwd = ((pieces&NC_URIUSERPWD)
272                       && duri->user != NULL && duri->password != NULL);
273    int withconstraints = ((pieces&NC_URICONSTRAINTS)
274                           && duri->constraint != NULL);
275
276    if(prefix != NULL) len += NILLEN(prefix);
277    if(withparams) {
278        len += NILLEN(duri->params);
279    }
280    len += (NILLEN(duri->protocol)+NILLEN("://"));
281    if(withuserpwd) {
282        len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
283    }
284    len += (NILLEN(duri->host));
285    if(duri->port != NULL) {
286        len += (NILLEN(":")+NILLEN(duri->port));
287    }
288    len += (NILLEN(duri->file));
289    if(suffix != NULL) len += NILLEN(suffix);
290    if(withconstraints) {
291        len += (NILLEN("?")+NILLEN(duri->constraint));
292    }
293    len += 1; /* null terminator */
294   
295    newuri = (char*)malloc(len);
296    if(!newuri) return NULL;
297
298    newuri[0] = '\0';
299    if(prefix != NULL) strcat(newuri,prefix);
300    if(withparams) {
301        strcat(newuri,duri->params);
302    }
303    strcat(newuri,duri->protocol);
304    strcat(newuri,"://");
305    if(withuserpwd) {
306        strcat(newuri,duri->user);
307        strcat(newuri,":");
308        strcat(newuri,duri->password); 
309        strcat(newuri,"@");
310    }
311    if(duri->host != NULL) { /* may be null if using file: protocol */
312        strcat(newuri,duri->host);     
313    }
314    if(duri->port != NULL) {
315        strcat(newuri,":");
316        strcat(newuri,duri->port);
317    }
318    strcat(newuri,duri->file);
319    if(suffix != NULL) strcat(newuri,suffix);
320    if(withconstraints) {
321        strcat(newuri,"?");
322        strcat(newuri,duri->constraint);
323    }
324    return newuri;
325}
326
327/**************************************************/
328/* Parameter support */
329
330/*
331Client parameters are assumed to be
332one or more instances of bracketed pairs:
333e.g "[...][...]...".
334The bracket content in turn is assumed to be a
335comma separated list of <name>=<value> pairs.
336e.g. x=y,z=,a=b.
337If the same parameter is specifed more than once,
338then the first occurrence is used; this is so that
339is possible to forcibly override user specified
340parameters by prefixing.
341IMPORTANT: client parameter string is assumed to
342have blanks compress out.
343Returns 1 if parse suceeded, 0 otherwise;
344*/
345
346int
347nc_uridecodeparams(NC_URI* nc_uri)
348{
349    char* cp;
350    char* cq;
351    int c;
352    int i;
353    int nparams;
354    char* params0;
355    char* params;
356    char* params1;
357    char** plist;
358
359    if(nc_uri == NULL) return 0;
360    if(nc_uri->params == NULL) return 1;
361
362    params0 = nc_uri->params;
363
364    /* Pass 1 to replace beginning '[' and ending ']' */
365    if(params0[0] == '[') 
366        params = strdup(params0+1);
367    else
368        params = strdup(params0);       
369
370    if(params[strlen(params)-1] == ']')
371        params[strlen(params)-1] = '\0';
372
373    /* Pass 2 to replace "][" pairs with ','*/
374    params1 = strdup(params);
375    cp=params; cq = params1;
376    while((c=*cp++)) {
377        if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
378        *cq++ = c;
379    }
380    *cq = '\0';
381    free(params);
382    params = params1;
383
384    /* Pass 3 to break string into pieces and count # of pairs */
385    nparams=0;
386    for(cp=params;(c=*cp);cp++) {
387        if(c == ',') {*cp = '\0'; nparams++;}
388    }
389    nparams++; /* for last one */
390
391    /* plist is an env style list */
392    plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
393
394    /* Pass 4 to break up each pass into a (name,value) pair*/
395    /* and insert into the param list */
396    /* parameters of the form name name= are converted to name=""*/
397    cp = params;
398    for(i=0;i<nparams;i++) {
399        char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
400        char* vp;
401        /*break up the ith param*/
402        vp = strchr(cp,'=');
403        if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
404        plist[2*i] = strdup(cp);       
405        plist[2*i+1] = strdup(vp);
406        cp = next;
407    }
408    plist[2*nparams] = NULL;
409    free(params);
410    if(nc_uri->paramlist != NULL)
411        nc_paramfree(nc_uri->paramlist);
412    nc_uri->paramlist = plist;
413    return 1;
414}
415
416int
417nc_urilookup(NC_URI* uri, const char* key, const char** resultp)
418{
419    int i;
420    char* value = NULL;
421    if(uri == NULL || key == NULL || uri->params == NULL) return 0;
422    if(uri->paramlist == NULL) {
423        i = nc_uridecodeparams(uri);
424        if(!i) return 0;
425    }
426    i = nc_find(uri->paramlist,key);
427    if(i < 0) return 0;
428    value = uri->paramlist[(2*i)+1];
429    if(resultp) *resultp = value;
430    return 1;
431}
432
433int
434nc_urisetparams(NC_URI* uri, const char* newparams)
435{
436    if(uri == NULL) return 0;
437    if(uri->paramlist != NULL) nc_paramfree(uri->paramlist);
438    uri->paramlist = NULL;
439    if(uri->params != NULL) free(uri->params);
440    uri->params = nulldup(newparams);
441    return 1;
442}
443
444/* Internal version of lookup; returns the paired index of the key */
445static int
446nc_find(char** params, const char* key)
447{
448    int i;
449    char** p;
450    for(i=0,p=params;*p;p+=2,i++) {
451        if(strcmp(key,*p)==0) return i;
452    }
453    return -1;
454}
455
456static void
457nc_paramfree(char** params)
458{
459    char** p;
460    if(params == NULL) return;
461    for(p=params;*p;p+=2) {
462        free(*p);
463        if(p[1] != NULL) free(p[1]);
464    }
465    free(params);
466}
Note: See TracBrowser for help on using the repository browser.