mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-03-19 17:30:27 +08:00
complete update of utilities: ncbyte, nclist, ncuri, nclog
This commit is contained in:
parent
9969af8aa5
commit
499f8d3a1c
@ -11,7 +11,7 @@ include_HEADERS += netcdf_par.h
|
||||
endif
|
||||
|
||||
noinst_HEADERS = nc_logging.h nc_tests.h fbits.h nc.h \
|
||||
nclist.h nc_uri.h utf8proc.h ncdispatch.h ncdimscale.h \
|
||||
nclist.h ncuri.h utf8proc.h ncdispatch.h ncdimscale.h \
|
||||
netcdf_f.h err_macros.h ncbytes.h nchashmap.h ceconstraints.h rnd.h \
|
||||
nclog.h ncconfigure.h nc4internal.h nctime.h nc3dispatch.h
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
|
||||
#ifndef NC_URI_H
|
||||
#define NC_URI_H
|
||||
|
||||
/*! This is an open structure meaning
|
||||
it is ok to directly access its fields*/
|
||||
typedef struct NC_URI {
|
||||
char* uri; /* as passed by the caller */
|
||||
char* protocol;
|
||||
char* user; /* from user:password@ */
|
||||
char* password; /* from user:password@ */
|
||||
char* host; /*!< host*/
|
||||
char* port; /*!< host */
|
||||
char* file; /*!< file */
|
||||
char* constraint; /*!< projection+selection */
|
||||
char* projection; /*!< without leading '?'*/
|
||||
char* selection; /*!< with leading '&'*/
|
||||
char* params; /* all params */
|
||||
char** paramlist; /*!<null terminated list */
|
||||
} NC_URI;
|
||||
|
||||
extern int nc_uriparse(const char* s, NC_URI** nc_uri);
|
||||
extern void nc_urifree(NC_URI* nc_uri);
|
||||
|
||||
/* Replace the constraints */
|
||||
extern void nc_urisetconstraints(NC_URI*,const char* constraints);
|
||||
|
||||
/* Construct a complete NC_ URI; caller frees returned string */
|
||||
|
||||
/* Define flags to control what is included */
|
||||
#define NC_URICONSTRAINTS 1
|
||||
#define NC_URIUSERPWD 2
|
||||
#define NC_URIPARAMS 4
|
||||
#define NC_URIALL (NC_URICONSTRAINTS|NC_URIUSERPWD|NC_URIPARAMS)
|
||||
|
||||
extern char* nc_uribuild(NC_URI*,const char* prefix, const char* suffix, int flags);
|
||||
|
||||
|
||||
/* Param Management */
|
||||
extern int nc_uridecodeparams(NC_URI* nc_uri);
|
||||
extern int nc_urisetparams(NC_URI* nc_uri,const char*);
|
||||
|
||||
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
|
||||
In any case, the result is imutable and should not be free'd.
|
||||
*/
|
||||
extern int nc_urilookup(NC_URI*, const char* param, const char** result);
|
||||
|
||||
#endif /*NC_URI_H*/
|
@ -36,7 +36,7 @@ EXTERNC int ncbytesset(NCbytes*,unsigned int,char);
|
||||
/* Append one byte */
|
||||
EXTERNC int ncbytesappend(NCbytes*,char); /* Add at Tail */
|
||||
/* Append n bytes */
|
||||
EXTERNC int ncbytesappendn(NCbytes*,void*,unsigned int); /* Add at Tail */
|
||||
EXTERNC int ncbytesappendn(NCbytes*,const void*,unsigned int); /* Add at Tail */
|
||||
|
||||
/* Null terminate the byte string without extending its length (for debugging) */
|
||||
EXTERNC int ncbytesnull(NCbytes*);
|
||||
@ -48,11 +48,11 @@ EXTERNC int ncbytescat(NCbytes*,const char*);
|
||||
EXTERNC int ncbytessetcontents(NCbytes*, char*, unsigned int);
|
||||
|
||||
/* Following are always "in-lined"*/
|
||||
#define ncbyteslength(bb) ((bb)?(bb)->length:0U)
|
||||
#define ncbytesalloc(bb) ((bb)?(bb)->alloc:0U)
|
||||
#define ncbytescontents(bb) ((bb && bb->content)?(bb)->content:(char*)"")
|
||||
#define ncbyteslength(bb) ((bb)!=NULL?(bb)->length:0U)
|
||||
#define ncbytesalloc(bb) ((bb)!=NULL?(bb)->alloc:0U)
|
||||
#define ncbytescontents(bb) (((bb)!=NULL && (bb)->content!=NULL)?(bb)->content:(char*)"")
|
||||
#define ncbytesextend(bb,len) ncbytessetalloc((bb),(len)+(bb->alloc))
|
||||
#define ncbytesclear(bb) ((bb)?(bb)->length=0:0U)
|
||||
#define ncbytesavail(bb,n) ((bb)?((bb)->alloc - (bb)->length) >= (n):0U)
|
||||
#define ncbytesclear(bb) ((bb)!=NULL?(bb)->length=0:0U)
|
||||
#define ncbytesavail(bb,n) ((bb)!=NULL?((bb)->alloc - (bb)->length) >= (n):0U)
|
||||
|
||||
#endif /*NCBYTES_H*/
|
||||
|
@ -19,7 +19,7 @@
|
||||
#endif
|
||||
#include "netcdf.h"
|
||||
#include "nc.h"
|
||||
#include "nc_uri.h"
|
||||
#include "ncuri.h"
|
||||
|
||||
#define longtype ((sizeof(long) == sizeof(int) ? NC_INT : NC_INT64))
|
||||
|
||||
|
@ -58,9 +58,7 @@ EXTERNC NClist* nclistclone(NClist*);
|
||||
/* Following are always "in-lined"*/
|
||||
#define nclistclear(l) nclistsetlength((l),0U)
|
||||
#define nclistextend(l,len) nclistsetalloc((l),(len)+(l->alloc))
|
||||
#define nclistcontents(l) ((l)->content)
|
||||
#define nclistlength(l) ((l)?(l)->length:0U)
|
||||
#define nclistcontents(l) ((l)==NULL?NULL:(l)->content)
|
||||
#define nclistlength(l) ((l)==NULL?0U:(l)->length)
|
||||
|
||||
#endif /*NCLIST_H*/
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef NCLOG_H
|
||||
#define NCLOG_H
|
||||
|
||||
#define ENVFLAG "NCLOGFILE"
|
||||
#define NCENVFLAG "NCLOGFILE"
|
||||
|
||||
/* Suggested tag values */
|
||||
#define NCLOGNOTE 0
|
||||
@ -16,7 +16,7 @@
|
||||
#define NCLOGDBG 3
|
||||
|
||||
extern void ncloginit(void);
|
||||
extern void ncsetlogging(int tf);
|
||||
extern int ncsetlogging(int tf);
|
||||
extern int nclogopen(const char* file);
|
||||
extern void nclogclose(void);
|
||||
|
||||
|
59
include/ncuri.h
Normal file
59
include/ncuri.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
|
||||
#ifndef NCURI_H
|
||||
#define NCURI_H
|
||||
|
||||
/*! This is an open structure meaning
|
||||
it is ok to directly access its fields*/
|
||||
typedef struct NCURI {
|
||||
char* uri; /* as passed by the caller */
|
||||
char* params; /* all params */
|
||||
char** paramlist; /*!<null terminated list */
|
||||
char* constraint; /*!< projection+selection */
|
||||
char* projection; /*!< without leading '?'*/
|
||||
char* selection; /*!< with leading '&'*/
|
||||
char* strings; /* first char of strings is always '\0' */
|
||||
/* Following all point into the strings field */
|
||||
char* protocol;
|
||||
char* user; /* from user:password@ */
|
||||
char* password; /* from user:password@ */
|
||||
char* host; /*!< host*/
|
||||
char* port; /*!< host */
|
||||
char* file; /*!< file */
|
||||
} NCURI;
|
||||
|
||||
extern int ncuriparse(const char* s, NCURI** ncuri);
|
||||
extern void ncurifree(NCURI* ncuri);
|
||||
|
||||
/* Replace the constraints */
|
||||
extern void ncurisetconstraints(NCURI*,const char* constraints);
|
||||
|
||||
/* Construct a complete NC URI; caller frees returned string */
|
||||
|
||||
/* Define flags to control what is included */
|
||||
#define NCURICONSTRAINTS 1
|
||||
#define NCURIUSERPWD 2
|
||||
#define NCURIPREFIXPARAMS 4
|
||||
#define NCURISUFFIXPARAMS 8
|
||||
#define NCURIPARAMS NCURIPREFIXPARAMS
|
||||
#define NCURIENCODE 16 /* If output should be encoded */
|
||||
#define NCURISTD (NCURICONSTRAINTS|NCURIUSERPWD)
|
||||
|
||||
extern char* ncuribuild(NCURI*,const char* prefix, const char* suffix, int flags);
|
||||
|
||||
|
||||
/* Param Management */
|
||||
extern int ncuridecodeparams(NCURI* ncuri);
|
||||
extern int ncurisetparams(NCURI* ncuri,const char*);
|
||||
|
||||
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
|
||||
In any case, the result is imutable and should not be free'd.
|
||||
*/
|
||||
extern int ncurilookup(NCURI*, const char* param, const char** result);
|
||||
|
||||
extern char* ncuriencode(char* s, char* allowable);
|
||||
extern char* ncuridecode(char* s);
|
||||
extern char* ncuridecodeonly(char* s, char*);
|
||||
|
||||
#endif /*NCURI_H*/
|
@ -364,7 +364,7 @@ makegetvar34(NCDAPCOMMON* nccomm, CDFnode* var, void* data, nc_type dsttype, Get
|
||||
}
|
||||
|
||||
int
|
||||
constrainable34(NC_URI* durl)
|
||||
constrainable34(NCURI* durl)
|
||||
{
|
||||
char** protocol = constrainableprotocols;
|
||||
for(;*protocol;protocol++) {
|
||||
|
@ -29,8 +29,8 @@ extern int oc_dumpnode(OClink, OCddsnode);
|
||||
int
|
||||
nc__testurl(const char* path, char** basenamep)
|
||||
{
|
||||
NC_URI* uri;
|
||||
int ok = nc_uriparse(path,&uri);
|
||||
NCURI* uri;
|
||||
int ok = ncuriparse(path,&uri);
|
||||
if(ok) {
|
||||
char* slash = strrchr(uri->file, '/');
|
||||
char* dot;
|
||||
@ -39,7 +39,7 @@ nc__testurl(const char* path, char** basenamep)
|
||||
dot = strrchr(slash, '.');
|
||||
if(dot != NULL && dot != slash) *dot = '\0';
|
||||
if(basenamep) *basenamep=slash ; else free(slash);
|
||||
nc_urifree(uri);
|
||||
ncurifree(uri);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@ -259,7 +259,7 @@ paramvalue34(NCDAPCOMMON* nccomm, const char* key)
|
||||
const char* value;
|
||||
|
||||
if(nccomm == NULL || key == NULL) return 0;
|
||||
if(!nc_urilookup(nccomm->oc.url,key,&value))
|
||||
if(!ncurilookup(nccomm->oc.url,key,&value))
|
||||
return NULL;
|
||||
return value;
|
||||
}
|
||||
@ -276,7 +276,7 @@ paramcheck34(NCDAPCOMMON* nccomm, const char* key, const char* subkey)
|
||||
char* p;
|
||||
|
||||
if(nccomm == NULL || key == NULL) return 0;
|
||||
if(!nc_urilookup(nccomm->oc.url,key,&value))
|
||||
if(!ncurilookup(nccomm->oc.url,key,&value))
|
||||
return 0;
|
||||
if(subkey == NULL) return 1;
|
||||
p = strstr(value,subkey);
|
||||
@ -711,7 +711,7 @@ dap_fetch(NCDAPCOMMON* nccomm, OClink conn, const char* ce,
|
||||
|
||||
if(SHOWFETCH) {
|
||||
/* Build uri string minus the constraint */
|
||||
char* baseurl = nc_uribuild(nccomm->oc.url,NULL,ext,0);
|
||||
char* baseurl = ncuribuild(nccomm->oc.url,NULL,ext,0);
|
||||
if(ce == NULL)
|
||||
LOG1(NCLOGNOTE,"fetch: %s",baseurl);
|
||||
else
|
||||
|
15
libdap2/env
15
libdap2/env
@ -8,19 +8,20 @@ PROG=./ncd
|
||||
|
||||
P=`pwd`
|
||||
|
||||
T="synth4"
|
||||
T="test.01"
|
||||
|
||||
|
||||
F="file://$TOP/ncdap_test/testdata3/$T"
|
||||
#F="http://motherlode.ucar.edu:8081/dts/$T"
|
||||
F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
|
||||
F="http://motherlode.ucar.edu:8081/dts/$T?f64"
|
||||
#F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
|
||||
#F="http://nomads.ncep.noaa.gov:9090/dods/gfs_hd/gfs_hd20120801/gfs_hd_00z"
|
||||
VAR=lat
|
||||
VAR=f64
|
||||
|
||||
PARMS="[log]"
|
||||
#PARMS="${PARMS}[netcdf3]"
|
||||
PARMS="${PARMS}[fetch=disk]"
|
||||
#PARMS="${PARMS}[cache]"
|
||||
#PARMS="${PARMS}[prefetch]"
|
||||
#PARMS="${PARMS}[fetch=disk]"
|
||||
PARMS="${PARMS}[cache]"
|
||||
PARMS="${PARMS}[prefetch]"
|
||||
#PARMS="${PARMS}[nocache]"
|
||||
#PARMS="${PARMS}[noprefetch]"
|
||||
#PARMS="${PARMS}[wholevar]"
|
||||
|
@ -118,7 +118,7 @@ typedef struct NCOC {
|
||||
OClink conn;
|
||||
char* rawurltext; /* as given to nc3d_open */
|
||||
char* urltext; /* as modified by nc3d_open */
|
||||
NC_URI* url; /* parse of rawuritext */
|
||||
NCURI* url; /* parse of rawuritext */
|
||||
OCdasnode ocdasroot;
|
||||
DCEconstraint* dapconstraint; /* from url */
|
||||
int inmemory; /* store fetched data in memory? */
|
||||
@ -303,7 +303,7 @@ extern void unattach34(CDFnode*);
|
||||
extern int nodematch34(CDFnode* node1, CDFnode* node2);
|
||||
extern int simplenodematch34(CDFnode* node1, CDFnode* node2);
|
||||
extern CDFnode* findxnode34(CDFnode* target, CDFnode* xroot);
|
||||
extern int constrainable34(NC_URI*);
|
||||
extern int constrainable34(NCURI*);
|
||||
extern char* makeconstraintstring34(DCEconstraint*);
|
||||
extern size_t estimatedataddssize34(CDFnode* datadds);
|
||||
extern void canonicalprojection34(NClist*, NClist*);
|
||||
|
@ -15,6 +15,8 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "oclog.h"
|
||||
|
||||
#include "nc3dispatch.h"
|
||||
#include "ncd3dispatch.h"
|
||||
#include "dapalign.h"
|
||||
@ -122,10 +124,10 @@ NCD3_open(const char * path, int mode,
|
||||
dapcomm->oc.rawurltext = strdup(path);
|
||||
#endif
|
||||
|
||||
nc_uriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url);
|
||||
ncuriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url);
|
||||
|
||||
/* parse the client parameters */
|
||||
nc_uridecodeparams(dapcomm->oc.url);
|
||||
ncuridecodeparams(dapcomm->oc.url);
|
||||
|
||||
if(!constrainable34(dapcomm->oc.url))
|
||||
SETFLAG(dapcomm->controls,NCF_UNCONSTRAINABLE);
|
||||
@ -164,9 +166,9 @@ NCD3_open(const char * path, int mode,
|
||||
} else
|
||||
dapcomm->oc.dapconstraint = NULL;
|
||||
|
||||
/* Construct a url for oc minus any constraint */
|
||||
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,
|
||||
(NC_URIALL ^ NC_URICONSTRAINTS));
|
||||
/* Construct a url for oc minus any constraint and params*/
|
||||
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,
|
||||
(NCURISTD ^ NCURICONSTRAINTS));
|
||||
|
||||
/* Pass to OC */
|
||||
ocstat = oc_open(dapcomm->oc.urltext,&dapcomm->oc.conn);
|
||||
@ -183,9 +185,9 @@ NCD3_open(const char * path, int mode,
|
||||
ncloginit();
|
||||
if(nclogopen(value))
|
||||
ncsetlogging(1);
|
||||
oc_loginit();
|
||||
if(oc_logopen(value))
|
||||
oc_setlogging(1);
|
||||
ocloginit();
|
||||
if(oclogopen(value))
|
||||
ocsetlogging(1);
|
||||
}
|
||||
|
||||
/* fetch and build the unconstrained DDS for use as
|
||||
@ -286,12 +288,12 @@ fprintf(stderr,"constrained dds: %s\n",dumptree(dapcomm->cdf.ddsroot));
|
||||
/* using the modified constraint, rebuild the constraint string */
|
||||
if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
|
||||
/* ignore all constraints */
|
||||
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,0);
|
||||
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,0);
|
||||
} else {
|
||||
char* constraintstring = buildconstraintstring3(dapcomm->oc.dapconstraint);
|
||||
nc_urisetconstraints(dapcomm->oc.url,constraintstring);
|
||||
ncurisetconstraints(dapcomm->oc.url,constraintstring);
|
||||
nullfree(constraintstring);
|
||||
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,NC_URICONSTRAINTS);
|
||||
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,NCURICONSTRAINTS);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "nclist.h"
|
||||
#include "nchashmap.h"
|
||||
#include "nclog.h"
|
||||
#include "nc_uri.h"
|
||||
#include "ncuri.h"
|
||||
|
||||
#include "fbits.h"
|
||||
#include "dceconstraints.h"
|
||||
|
@ -50,7 +50,7 @@ freeNCDAPCOMMON(NCDAPCOMMON* dapcomm)
|
||||
oc_root_free(dapcomm->oc.conn,dapcomm->oc.ocdasroot);
|
||||
dapcomm->oc.ocdasroot = NULL;
|
||||
oc_close(dapcomm->oc.conn); /* also reclaims remaining OC trees */
|
||||
nc_urifree(dapcomm->oc.url);
|
||||
ncurifree(dapcomm->oc.url);
|
||||
nullfree(dapcomm->oc.urltext);
|
||||
nullfree(dapcomm->oc.rawurltext);
|
||||
|
||||
|
@ -18,8 +18,8 @@ libdispatch_la_CPPFLAGS = ${AM_CPPFLAGS}
|
||||
libdispatch_la_SOURCES = dparallel.c dcopy.c dfile.c ddim.c datt.c \
|
||||
dattinq.c dattput.c dattget.c derror.c dvar.c dvarget.c dvarput.c \
|
||||
dvarinq.c ddispatch.c \
|
||||
dnclog.c dstring.c dutf8proc.c utf8proc_data.h \
|
||||
nc_uri.c nclist.c ncbytes.c nchashmap.c nctime.c \
|
||||
nclog.c dstring.c dutf8proc.c utf8proc_data.h \
|
||||
ncuri.c nclist.c ncbytes.c nchashmap.c nctime.c \
|
||||
dsubstrate.c
|
||||
|
||||
# Add functions only found in netCDF-4.
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "ncdispatch.h"
|
||||
#include "nc_uri.h"
|
||||
#include "ncuri.h"
|
||||
|
||||
extern int NCSUBSTRATE_intialize(void);
|
||||
|
||||
@ -92,7 +92,7 @@ int
|
||||
NC_testurl(const char* path)
|
||||
{
|
||||
int isurl = 0;
|
||||
NC_URI* tmpurl = NULL;
|
||||
NCURI* tmpurl = NULL;
|
||||
char* p;
|
||||
|
||||
if(path == NULL) return 0;
|
||||
@ -104,7 +104,7 @@ NC_testurl(const char* path)
|
||||
if(*p == '/') return 0; /* probably an absolute file path */
|
||||
|
||||
/* Ok, try to parse as a url */
|
||||
if(nc_uriparse(path,&tmpurl)) {
|
||||
if(ncuriparse(path,&tmpurl)) {
|
||||
/* Do some extra testing to make sure this really is a url */
|
||||
/* Look for a knownprotocol */
|
||||
struct NCPROTOCOLLIST* protolist;
|
||||
@ -114,7 +114,7 @@ NC_testurl(const char* path)
|
||||
break;
|
||||
}
|
||||
}
|
||||
nc_urifree(tmpurl);
|
||||
ncurifree(tmpurl);
|
||||
return isurl;
|
||||
}
|
||||
return 0;
|
||||
@ -129,20 +129,20 @@ int
|
||||
NC_urlmodel(const char* path)
|
||||
{
|
||||
int model = 0;
|
||||
NC_URI* tmpurl = NULL;
|
||||
NCURI* tmpurl = NULL;
|
||||
struct NCPROTOCOLLIST* protolist;
|
||||
|
||||
if(!nc_uriparse(path,&tmpurl)) goto done;
|
||||
if(!ncuriparse(path,&tmpurl)) goto done;
|
||||
|
||||
/* Look at any prefixed parameters */
|
||||
if(nc_urilookup(tmpurl,"netcdf4",NULL)
|
||||
|| nc_urilookup(tmpurl,"netcdf-4",NULL)) {
|
||||
if(ncurilookup(tmpurl,"netcdf4",NULL)
|
||||
|| ncurilookup(tmpurl,"netcdf-4",NULL)) {
|
||||
model = (NC_DISPATCH_NC4|NC_DISPATCH_NCD);
|
||||
} else if(nc_urilookup(tmpurl,"netcdf3",NULL)
|
||||
|| nc_urilookup(tmpurl,"netcdf-3",NULL)) {
|
||||
} else if(ncurilookup(tmpurl,"netcdf3",NULL)
|
||||
|| ncurilookup(tmpurl,"netcdf-3",NULL)) {
|
||||
model = (NC_DISPATCH_NC3|NC_DISPATCH_NCD);
|
||||
} else if(nc_urilookup(tmpurl,"cdmremote",NULL)
|
||||
|| nc_urilookup(tmpurl,"cdmr",NULL)) {
|
||||
} else if(ncurilookup(tmpurl,"cdmremote",NULL)
|
||||
|| ncurilookup(tmpurl,"cdmr",NULL)) {
|
||||
model = (NC_DISPATCH_NCR|NC_DISPATCH_NC4);
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ NC_urlmodel(const char* path)
|
||||
model |= (NC_DISPATCH_NC3 | NC_DISPATCH_NCD);
|
||||
|
||||
done:
|
||||
nc_urifree(tmpurl);
|
||||
ncurifree(tmpurl);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -1,466 +0,0 @@
|
||||
/*********************************************************************
|
||||
* Copyright 2010, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nc_uri.h"
|
||||
|
||||
#define NC_URIDEBUG
|
||||
|
||||
#define LBRACKET '['
|
||||
#define RBRACKET ']'
|
||||
|
||||
#ifndef FIX
|
||||
#define FIX(s) ((s)==NULL?"":(s))
|
||||
#endif
|
||||
|
||||
#ifndef NILLEN
|
||||
#define NILLEN(s) ((s)==NULL?0:strlen(s))
|
||||
#endif
|
||||
|
||||
|
||||
static char* legalprotocols[] = {
|
||||
"file:",
|
||||
"http:",
|
||||
"https:",
|
||||
"ftp:",
|
||||
NULL /* NULL terminate*/
|
||||
};
|
||||
|
||||
static void nc_paramfree(char** params);
|
||||
static int nc_find(char** params, const char* key);
|
||||
|
||||
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
|
||||
int
|
||||
nc_uriparse(const char* uri0, NC_URI** nc_urip)
|
||||
{
|
||||
NC_URI* nc_uri = NULL;
|
||||
char* uri;
|
||||
char** pp;
|
||||
char* p;
|
||||
char* p1;
|
||||
int c;
|
||||
|
||||
/* accumulate parse points*/
|
||||
char* protocol = NULL;
|
||||
char* params = NULL;
|
||||
char* host = NULL;
|
||||
char* port = NULL;
|
||||
char* constraint = NULL;
|
||||
char* user = NULL;
|
||||
char* pwd = NULL;
|
||||
char* file = NULL;
|
||||
|
||||
nc_uri = (NC_URI*)calloc(1,sizeof(NC_URI));
|
||||
if(nc_uri == NULL) return 0;
|
||||
|
||||
/* Temporary hack to remove escape characters inserted by Windows or MinGW */
|
||||
if(strchr(uri0,'\\') != NULL) {
|
||||
char* u = strdup(uri0);
|
||||
if(u == NULL) return 0;
|
||||
p = u;
|
||||
p1 = u;
|
||||
while((c=*p1++)) {if(c != '\\') *p++ = c;}
|
||||
uri0 = (const char*)u;
|
||||
}
|
||||
|
||||
/* make local copy of uri */
|
||||
uri = strdup(uri0);
|
||||
|
||||
/* remove all whitespace*/
|
||||
p = uri;
|
||||
p1 = uri;
|
||||
while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
|
||||
|
||||
p = uri;
|
||||
|
||||
/* break up the uri string into pieces*/
|
||||
|
||||
/* 1. leading bracketed parameters */
|
||||
if(*p == LBRACKET) {
|
||||
params = p+1;
|
||||
/* find end of the clientparams*/
|
||||
for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
|
||||
if(*p == 0) goto fail; /* malformed client params*/
|
||||
*p = '\0'; /* leave off the trailing rbracket for now */
|
||||
p++; /* move past the params*/
|
||||
}
|
||||
|
||||
/* verify that the uri starts with an acceptable protocol*/
|
||||
for(pp=legalprotocols;*pp;pp++) {
|
||||
if(strncmp(p,*pp,strlen(*pp))==0) break;
|
||||
}
|
||||
if(*pp == NULL) goto fail; /* illegal protocol*/
|
||||
/* save the protocol */
|
||||
protocol = *pp;
|
||||
|
||||
/* 4. skip protocol */
|
||||
p += strlen(protocol);
|
||||
|
||||
/* 5. skip // */
|
||||
if(*p != '/' && *(p+1) != '/')
|
||||
goto fail;
|
||||
p += 2;
|
||||
|
||||
/* 6. Mark the end of the host section */
|
||||
file = strchr(p,'/');
|
||||
if(file) {
|
||||
*file++ = '\0'; /* warning: we just overwrote the leading / */
|
||||
} else
|
||||
goto fail; /* url only has host part, no path */
|
||||
|
||||
/* 7. extract any user:pwd */
|
||||
p1 = strchr(p,'@');
|
||||
if(p1) {/* Assume we have user:pwd@ */
|
||||
*p1 = '\0';
|
||||
user = p;
|
||||
pwd = strchr(p,':');
|
||||
if(!pwd) goto fail; /* malformed */
|
||||
*pwd++ = '\0';
|
||||
p = pwd+strlen(pwd)+1;
|
||||
}
|
||||
|
||||
/* 8. extract host and port */
|
||||
host = p;
|
||||
port = strchr(p,':');
|
||||
if(port) {
|
||||
*port++ = '\0';
|
||||
}
|
||||
|
||||
/* 9. Look for '?' */
|
||||
constraint = strchr(file,'?');
|
||||
if(constraint) {
|
||||
*constraint++ = '\0';
|
||||
}
|
||||
|
||||
/* assemble the component pieces*/
|
||||
if(uri0 && strlen(uri0) > 0)
|
||||
nc_uri->uri = strdup(uri0);
|
||||
if(protocol && strlen(protocol) > 0) {
|
||||
nc_uri->protocol = strdup(protocol);
|
||||
/* remove trailing ':' */
|
||||
nc_uri->protocol[strlen(protocol)-1] = '\0';
|
||||
}
|
||||
if(user && strlen(user) > 0)
|
||||
nc_uri->user = strdup(user);
|
||||
if(pwd && strlen(pwd) > 0)
|
||||
nc_uri->password = strdup(pwd);
|
||||
if(host && strlen(host) > 0)
|
||||
nc_uri->host = strdup(host);
|
||||
if(port && strlen(port) > 0)
|
||||
nc_uri->port = strdup(port);
|
||||
if(file && strlen(file) > 0) {
|
||||
/* Add back the leading / */
|
||||
nc_uri->file = malloc(strlen(file)+2);
|
||||
strcpy(nc_uri->file,"/");
|
||||
strcat(nc_uri->file,file);
|
||||
}
|
||||
if(constraint && strlen(constraint) > 0)
|
||||
nc_uri->constraint = strdup(constraint);
|
||||
nc_urisetconstraints(nc_uri,constraint);
|
||||
if(params != NULL && strlen(params) > 0) {
|
||||
nc_uri->params = (char*)malloc(1+2+strlen(params));
|
||||
strcpy(nc_uri->params,"[");
|
||||
strcat(nc_uri->params,params);
|
||||
strcat(nc_uri->params,"]");
|
||||
}
|
||||
|
||||
#ifdef NC_XDEBUG
|
||||
{
|
||||
fprintf(stderr,"nc_uri:");
|
||||
fprintf(stderr," params=|%s|",FIX(nc_uri->params));
|
||||
fprintf(stderr," protocol=|%s|",FIX(nc_uri->protocol));
|
||||
fprintf(stderr," host=|%s|",FIX(nc_uri->host));
|
||||
fprintf(stderr," port=|%s|",FIX(nc_uri->port));
|
||||
fprintf(stderr," file=|%s|",FIX(nc_uri->file));
|
||||
fprintf(stderr," constraint=|%s|",FIX(nc_uri->constraint));
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
#endif
|
||||
free(uri);
|
||||
if(nc_urip != NULL) *nc_urip = nc_uri;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
if(nc_uri) nc_urifree(nc_uri);
|
||||
if(uri != NULL) free(uri);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nc_urifree(NC_URI* nc_uri)
|
||||
{
|
||||
if(nc_uri == NULL) return;
|
||||
if(nc_uri->uri != NULL) {free(nc_uri->uri);}
|
||||
if(nc_uri->protocol != NULL) {free(nc_uri->protocol);}
|
||||
if(nc_uri->user != NULL) {free(nc_uri->user);}
|
||||
if(nc_uri->password != NULL) {free(nc_uri->password);}
|
||||
if(nc_uri->host != NULL) {free(nc_uri->host);}
|
||||
if(nc_uri->port != NULL) {free(nc_uri->port);}
|
||||
if(nc_uri->file != NULL) {free(nc_uri->file);}
|
||||
if(nc_uri->constraint != NULL) {free(nc_uri->constraint);}
|
||||
if(nc_uri->projection != NULL) {free(nc_uri->projection);}
|
||||
if(nc_uri->selection != NULL) {free(nc_uri->selection);}
|
||||
if(nc_uri->params != NULL) {free(nc_uri->params);}
|
||||
if(nc_uri->paramlist != NULL) nc_paramfree(nc_uri->paramlist);
|
||||
free(nc_uri);
|
||||
}
|
||||
|
||||
/* Replace the constraints */
|
||||
void
|
||||
nc_urisetconstraints(NC_URI* duri,const char* constraints)
|
||||
{
|
||||
char* proj = NULL;
|
||||
char* select = NULL;
|
||||
const char* p;
|
||||
|
||||
if(duri->constraint == NULL) free(duri->constraint);
|
||||
if(duri->projection != NULL) free(duri->projection);
|
||||
if(duri->selection != NULL) free(duri->selection);
|
||||
duri->constraint = NULL;
|
||||
duri->projection = NULL;
|
||||
duri->selection = NULL;
|
||||
|
||||
if(constraints == NULL || strlen(constraints)==0) return;
|
||||
|
||||
duri->constraint = strdup(constraints);
|
||||
if(*duri->constraint == '?')
|
||||
strcpy(duri->constraint,duri->constraint+1);
|
||||
|
||||
p = duri->constraint;
|
||||
proj = (char*) p;
|
||||
select = strchr(proj,'&');
|
||||
if(select != NULL) {
|
||||
size_t plen = (select - proj);
|
||||
if(plen == 0) {
|
||||
proj = NULL;
|
||||
} else {
|
||||
proj = (char*)malloc(plen+1);
|
||||
memcpy((void*)proj,p,plen);
|
||||
proj[plen] = '\0';
|
||||
}
|
||||
select = nulldup(select);
|
||||
} else {
|
||||
proj = nulldup(proj);
|
||||
select = NULL;
|
||||
}
|
||||
duri->projection = proj;
|
||||
duri->selection = select;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a complete NC_ URI without the client params
|
||||
and optionally with the constraints;
|
||||
caller frees returned string
|
||||
*/
|
||||
|
||||
char*
|
||||
nc_uribuild(NC_URI* duri, const char* prefix, const char* suffix, int pieces)
|
||||
{
|
||||
size_t len = 0;
|
||||
char* newuri;
|
||||
int withparams = ((pieces&NC_URIPARAMS)
|
||||
&& duri->params != NULL);
|
||||
int withuserpwd = ((pieces&NC_URIUSERPWD)
|
||||
&& duri->user != NULL && duri->password != NULL);
|
||||
int withconstraints = ((pieces&NC_URICONSTRAINTS)
|
||||
&& duri->constraint != NULL);
|
||||
|
||||
if(prefix != NULL) len += NILLEN(prefix);
|
||||
if(withparams) {
|
||||
len += NILLEN(duri->params);
|
||||
}
|
||||
len += (NILLEN(duri->protocol)+NILLEN("://"));
|
||||
if(withuserpwd) {
|
||||
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
|
||||
}
|
||||
len += (NILLEN(duri->host));
|
||||
if(duri->port != NULL) {
|
||||
len += (NILLEN(":")+NILLEN(duri->port));
|
||||
}
|
||||
len += (NILLEN(duri->file));
|
||||
if(suffix != NULL) len += NILLEN(suffix);
|
||||
if(withconstraints) {
|
||||
len += (NILLEN("?")+NILLEN(duri->constraint));
|
||||
}
|
||||
len += 1; /* null terminator */
|
||||
|
||||
newuri = (char*)malloc(len);
|
||||
if(!newuri) return NULL;
|
||||
|
||||
newuri[0] = '\0';
|
||||
if(prefix != NULL) strcat(newuri,prefix);
|
||||
if(withparams) {
|
||||
strcat(newuri,duri->params);
|
||||
}
|
||||
strcat(newuri,duri->protocol);
|
||||
strcat(newuri,"://");
|
||||
if(withuserpwd) {
|
||||
strcat(newuri,duri->user);
|
||||
strcat(newuri,":");
|
||||
strcat(newuri,duri->password);
|
||||
strcat(newuri,"@");
|
||||
}
|
||||
if(duri->host != NULL) { /* may be null if using file: protocol */
|
||||
strcat(newuri,duri->host);
|
||||
}
|
||||
if(duri->port != NULL) {
|
||||
strcat(newuri,":");
|
||||
strcat(newuri,duri->port);
|
||||
}
|
||||
strcat(newuri,duri->file);
|
||||
if(suffix != NULL) strcat(newuri,suffix);
|
||||
if(withconstraints) {
|
||||
strcat(newuri,"?");
|
||||
strcat(newuri,duri->constraint);
|
||||
}
|
||||
return newuri;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Parameter support */
|
||||
|
||||
/*
|
||||
Client parameters are assumed to be
|
||||
one or more instances of bracketed pairs:
|
||||
e.g "[...][...]...".
|
||||
The bracket content in turn is assumed to be a
|
||||
comma separated list of <name>=<value> pairs.
|
||||
e.g. x=y,z=,a=b.
|
||||
If the same parameter is specifed more than once,
|
||||
then the first occurrence is used; this is so that
|
||||
is possible to forcibly override user specified
|
||||
parameters by prefixing.
|
||||
IMPORTANT: client parameter string is assumed to
|
||||
have blanks compress out.
|
||||
Returns 1 if parse suceeded, 0 otherwise;
|
||||
*/
|
||||
|
||||
int
|
||||
nc_uridecodeparams(NC_URI* nc_uri)
|
||||
{
|
||||
char* cp;
|
||||
char* cq;
|
||||
int c;
|
||||
int i;
|
||||
int nparams;
|
||||
char* params0;
|
||||
char* params;
|
||||
char* params1;
|
||||
char** plist;
|
||||
|
||||
if(nc_uri == NULL) return 0;
|
||||
if(nc_uri->params == NULL) return 1;
|
||||
|
||||
params0 = nc_uri->params;
|
||||
|
||||
/* Pass 1 to replace beginning '[' and ending ']' */
|
||||
if(params0[0] == '[')
|
||||
params = strdup(params0+1);
|
||||
else
|
||||
params = strdup(params0);
|
||||
|
||||
if(params[strlen(params)-1] == ']')
|
||||
params[strlen(params)-1] = '\0';
|
||||
|
||||
/* Pass 2 to replace "][" pairs with ','*/
|
||||
params1 = strdup(params);
|
||||
cp=params; cq = params1;
|
||||
while((c=*cp++)) {
|
||||
if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
|
||||
*cq++ = c;
|
||||
}
|
||||
*cq = '\0';
|
||||
free(params);
|
||||
params = params1;
|
||||
|
||||
/* Pass 3 to break string into pieces and count # of pairs */
|
||||
nparams=0;
|
||||
for(cp=params;(c=*cp);cp++) {
|
||||
if(c == ',') {*cp = '\0'; nparams++;}
|
||||
}
|
||||
nparams++; /* for last one */
|
||||
|
||||
/* plist is an env style list */
|
||||
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
|
||||
|
||||
/* Pass 4 to break up each pass into a (name,value) pair*/
|
||||
/* and insert into the param list */
|
||||
/* parameters of the form name name= are converted to name=""*/
|
||||
cp = params;
|
||||
for(i=0;i<nparams;i++) {
|
||||
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
|
||||
char* vp;
|
||||
/*break up the ith param*/
|
||||
vp = strchr(cp,'=');
|
||||
if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
|
||||
plist[2*i] = strdup(cp);
|
||||
plist[2*i+1] = strdup(vp);
|
||||
cp = next;
|
||||
}
|
||||
plist[2*nparams] = NULL;
|
||||
free(params);
|
||||
if(nc_uri->paramlist != NULL)
|
||||
nc_paramfree(nc_uri->paramlist);
|
||||
nc_uri->paramlist = plist;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
nc_urilookup(NC_URI* uri, const char* key, const char** resultp)
|
||||
{
|
||||
int i;
|
||||
char* value = NULL;
|
||||
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
|
||||
if(uri->paramlist == NULL) {
|
||||
i = nc_uridecodeparams(uri);
|
||||
if(!i) return 0;
|
||||
}
|
||||
i = nc_find(uri->paramlist,key);
|
||||
if(i < 0) return 0;
|
||||
value = uri->paramlist[(2*i)+1];
|
||||
if(resultp) *resultp = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
nc_urisetparams(NC_URI* uri, const char* newparams)
|
||||
{
|
||||
if(uri == NULL) return 0;
|
||||
if(uri->paramlist != NULL) nc_paramfree(uri->paramlist);
|
||||
uri->paramlist = NULL;
|
||||
if(uri->params != NULL) free(uri->params);
|
||||
uri->params = nulldup(newparams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Internal version of lookup; returns the paired index of the key */
|
||||
static int
|
||||
nc_find(char** params, const char* key)
|
||||
{
|
||||
int i;
|
||||
char** p;
|
||||
for(i=0,p=params;*p;p+=2,i++) {
|
||||
if(strcmp(key,*p)==0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
nc_paramfree(char** params)
|
||||
{
|
||||
char** p;
|
||||
if(params == NULL) return;
|
||||
for(p=params;*p;p+=2) {
|
||||
free(*p);
|
||||
if(p[1] != NULL) free(p[1]);
|
||||
}
|
||||
free(params);
|
||||
}
|
@ -50,6 +50,7 @@ ncbytessetalloc(NCbytes* bb, unsigned int sz)
|
||||
if(bb->alloc >= sz) return TRUE;
|
||||
if(bb->nonextendible) return ncbytesfail();
|
||||
newcontent=(char*)calloc(sz,sizeof(char));
|
||||
if(newcontent == NULL) return FALSE;
|
||||
if(bb->alloc > 0 && bb->length > 0 && bb->content != NULL) {
|
||||
memcpy((void*)newcontent,(void*)bb->content,sizeof(char)*bb->length);
|
||||
}
|
||||
@ -106,9 +107,13 @@ int
|
||||
ncbytesappend(NCbytes* bb, char elem)
|
||||
{
|
||||
if(bb == NULL) return ncbytesfail();
|
||||
if(bb->length >= bb->alloc) if(!ncbytessetalloc(bb,0)) return ncbytesfail();
|
||||
/* We need space for the char + null */
|
||||
while(bb->length+1 >= bb->alloc) {
|
||||
if(!ncbytessetalloc(bb,0)) return ncbytesfail();
|
||||
}
|
||||
bb->content[bb->length] = elem;
|
||||
bb->length++;
|
||||
bb->content[bb->length] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -124,13 +129,16 @@ ncbytescat(NCbytes* bb, const char* s)
|
||||
}
|
||||
|
||||
int
|
||||
ncbytesappendn(NCbytes* bb, void* elem, unsigned int n)
|
||||
ncbytesappendn(NCbytes* bb, const void* elem, unsigned int n)
|
||||
{
|
||||
if(bb == NULL || elem == NULL) return ncbytesfail();
|
||||
if(n == 0) {n = strlen((char*)elem);}
|
||||
while(!ncbytesavail(bb,n)) {if(!ncbytessetalloc(bb,0)) return ncbytesfail();}
|
||||
while(!ncbytesavail(bb,n+1)) {
|
||||
if(!ncbytessetalloc(bb,0)) return ncbytesfail();
|
||||
}
|
||||
memcpy((void*)&bb->content[bb->length],(void*)elem,n);
|
||||
bb->length += n;
|
||||
bb->content[bb->length] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
@ -18,9 +16,9 @@
|
||||
#define MAXTAGS 256
|
||||
#define NCTAGDFALT "Log";
|
||||
|
||||
static int ncinitlog = 0;
|
||||
static int nclogginginitialized = 0;
|
||||
static int nclogging = 0;
|
||||
static int ncsystemfile = 0;
|
||||
static int ncsystemfile = 0; /* 1 => we are logging to file we did not open */
|
||||
static char* nclogfile = NULL;
|
||||
static FILE* nclogstream = NULL;
|
||||
|
||||
@ -30,11 +28,17 @@ static char* nctagdfalt = NULL;
|
||||
static char* nctagsetdfalt[] = {"Warning","Error","Note","Debug"};
|
||||
static char* nctagname(int tag);
|
||||
|
||||
/*!\defgroup NClog NClog Management
|
||||
@{*/
|
||||
|
||||
/*!\internal
|
||||
*/
|
||||
|
||||
void
|
||||
ncloginit(void)
|
||||
{
|
||||
const char* file = getenv(ENVFLAG);
|
||||
ncinitlog = 1;
|
||||
const char* file = getenv(NCENVFLAG);
|
||||
nclogginginitialized = 1;
|
||||
ncsetlogging(0);
|
||||
nclogfile = NULL;
|
||||
nclogstream = NULL;
|
||||
@ -49,17 +53,38 @@ ncloginit(void)
|
||||
nctagset = nctagsetdfalt;
|
||||
}
|
||||
|
||||
void
|
||||
/*!
|
||||
Enable/Disable logging.
|
||||
|
||||
\param[in] tf If 1, then turn on logging, if 0, then turn off logging.
|
||||
|
||||
\return The previous value of the logging flag.
|
||||
*/
|
||||
|
||||
int
|
||||
ncsetlogging(int tf)
|
||||
{
|
||||
if(!ncinitlog) ncloginit();
|
||||
int was;
|
||||
if(!nclogginginitialized) ncloginit();
|
||||
was = nclogging;
|
||||
nclogging = tf;
|
||||
return was;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify a file into which to place logging output.
|
||||
|
||||
\param[in] file The name of the file into which to place logging output.
|
||||
If the file has the value NULL, then send logging output to
|
||||
stderr.
|
||||
|
||||
\return zero if the open failed, one otherwise.
|
||||
*/
|
||||
|
||||
int
|
||||
nclogopen(const char* file)
|
||||
{
|
||||
if(!ncinitlog) ncloginit();
|
||||
if(!nclogginginitialized) ncloginit();
|
||||
nclogclose();
|
||||
if(file == NULL || strlen(file) == 0) {
|
||||
/* use stderr*/
|
||||
@ -100,6 +125,7 @@ nclogopen(const char* file)
|
||||
void
|
||||
nclogclose(void)
|
||||
{
|
||||
if(!nclogginginitialized) ncloginit();
|
||||
if(nclogstream != NULL && !ncsystemfile) {
|
||||
fclose(nclogstream);
|
||||
}
|
||||
@ -109,11 +135,23 @@ nclogclose(void)
|
||||
ncsystemfile = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Send logging messages. This uses a variable
|
||||
number of arguments and operates like the stdio
|
||||
printf function.
|
||||
|
||||
\param[in] tag Indicate the kind of this log message.
|
||||
\param[in] format Format specification as with printf.
|
||||
*/
|
||||
|
||||
void
|
||||
nclog(int tag, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char* prefix;
|
||||
|
||||
if(!nclogginginitialized) ncloginit();
|
||||
|
||||
if(!nclogging || nclogstream == NULL) return;
|
||||
|
||||
prefix = nctagname(tag);
|
||||
@ -134,6 +172,13 @@ nclogtext(int tag, const char* text)
|
||||
nclogtextn(tag,text,strlen(text));
|
||||
}
|
||||
|
||||
/*!
|
||||
Send arbitrarily long text as a logging message.
|
||||
Each line will be sent using nclog with the specified tag.
|
||||
\param[in] tag Indicate the kind of this log message.
|
||||
\param[in] text Arbitrary text to send as a logging message.
|
||||
*/
|
||||
|
||||
void
|
||||
nclogtextn(int tag, const char* text, size_t count)
|
||||
{
|
||||
@ -167,3 +212,5 @@ nctagname(int tag)
|
||||
return nctagset[tag];
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
831
libdispatch/ncuri.c
Normal file
831
libdispatch/ncuri.c
Normal file
@ -0,0 +1,831 @@
|
||||
/*********************************************************************
|
||||
* Copyright 2010, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ncuri.h"
|
||||
|
||||
#define NCURIDEBUG
|
||||
|
||||
#ifdef NCURIDEBUG
|
||||
static int failpoint = 0;
|
||||
#define THROW(n) {failpoint=(n); goto fail;}
|
||||
#else
|
||||
#define THROW(n)
|
||||
#endif
|
||||
|
||||
|
||||
#define PADDING 8
|
||||
|
||||
#define LBRACKET '['
|
||||
#define RBRACKET ']'
|
||||
#define EOFCHAR '\0'
|
||||
|
||||
#ifndef FIX
|
||||
#define FIX(s) ((s)==NULL?"NULL":(s))
|
||||
#endif
|
||||
|
||||
#ifndef NILLEN
|
||||
#define NILLEN(s) ((s)==NULL?0:strlen(s))
|
||||
#endif
|
||||
|
||||
#ifndef nulldup
|
||||
#define nulldup(s) ((s)==NULL?NULL:strdup(s))
|
||||
#endif
|
||||
|
||||
#define terminate(p) {*(p) = EOFCHAR;}
|
||||
|
||||
#define endof(p) ((p)+strlen(p))
|
||||
|
||||
static struct NC_ProtocolInfo {
|
||||
char* name;
|
||||
int filelike; /* 1=>this protocol has no host, user+pwd, or port */
|
||||
} legalprotocols[] = {
|
||||
{"file",1},
|
||||
{"http",0},
|
||||
{"https",0},
|
||||
{"ftp",0},
|
||||
};
|
||||
|
||||
/* Allowable character sets for encode */
|
||||
static char* fileallow =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
|
||||
|
||||
static char* queryallow =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
|
||||
|
||||
/* Forward */
|
||||
static void ncparamfree(char** params);
|
||||
static int ncfind(char** params, const char* key);
|
||||
static void nclshift1(char* p);
|
||||
static void ncrshift1(char* p);
|
||||
static char* nclocate(char* p, const char* charlist);
|
||||
static void ncappendparams(char* newuri, char** p);
|
||||
|
||||
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
|
||||
int
|
||||
ncuriparse(const char* uri0, NCURI** ncurip)
|
||||
{
|
||||
NCURI* ncuri = NULL;
|
||||
char* uri = NULL;
|
||||
char* p;
|
||||
struct NC_ProtocolInfo* proto;
|
||||
int i,nprotos;
|
||||
|
||||
/* accumulate parse points*/
|
||||
char* protocol = NULL;
|
||||
char* host = NULL;
|
||||
char* port = NULL;
|
||||
char* constraint = NULL;
|
||||
char* user = NULL;
|
||||
char* pwd = NULL;
|
||||
char* file = NULL;
|
||||
char* prefixparams = NULL;
|
||||
char* suffixparams = NULL;
|
||||
|
||||
if(uri0 == NULL || strlen(uri0) == 0)
|
||||
{THROW(1); goto fail;}
|
||||
|
||||
ncuri = (NCURI*)calloc(1,sizeof(NCURI));
|
||||
if(ncuri == NULL)
|
||||
{THROW(2); goto fail;}
|
||||
|
||||
/* save original uri */
|
||||
ncuri->uri = nulldup(uri0);
|
||||
|
||||
/* make local copy of uri */
|
||||
uri = (char*)malloc(strlen(uri0)+1+PADDING); /* +1 for trailing null,
|
||||
+PADDING for shifting */
|
||||
if(uri == NULL)
|
||||
{THROW(3); goto fail;}
|
||||
|
||||
/* strings will be broken into pieces with intermixed '\0; characters;
|
||||
first char is guaranteed to be '\0' */
|
||||
|
||||
ncuri->strings = uri;
|
||||
uri++;
|
||||
|
||||
/* dup the incoming url */
|
||||
strcpy(uri,uri0);
|
||||
|
||||
/* Walk the uri and do the following:
|
||||
1. remove all whitespace
|
||||
2. remove all '\\' (Temp hack to remove escape characters
|
||||
inserted by Windows or MinGW)
|
||||
*/
|
||||
for(p=uri;*p;p++) {
|
||||
if(*p == '\\' || *p < ' ')
|
||||
nclshift1(p); /* compress out */
|
||||
}
|
||||
|
||||
p = uri;
|
||||
|
||||
/* break up the uri string into big chunks: prefixparams, protocol,
|
||||
host section, and the file section (i.e. remainder)
|
||||
*/
|
||||
|
||||
/* collect any prefix bracketed parameters */
|
||||
if(*p == LBRACKET) {
|
||||
prefixparams = p+1;
|
||||
/* find end of the clientparams; convert LB,RB to ';' */
|
||||
for(;*p;p++) {
|
||||
if(p[0] == RBRACKET && p[1] == LBRACKET) {
|
||||
p[0] = ';';
|
||||
nclshift1(p+1);
|
||||
} else if(p[0] == RBRACKET && p[1] != LBRACKET)
|
||||
break;
|
||||
}
|
||||
if(*p == 0)
|
||||
{THROW(4); goto fail; /* malformed client params*/}
|
||||
terminate(p); /* nul term the prefixparams (overwrites
|
||||
the final RBRACKET) */
|
||||
p++; /* move past the final RBRACKET */
|
||||
}
|
||||
|
||||
/* Tag the protocol */
|
||||
protocol = p;
|
||||
p = strchr(p,':');
|
||||
if(!p)
|
||||
{THROW(5); goto fail;}
|
||||
terminate(p); /*overwrite colon*/
|
||||
p++; /* skip the colon */
|
||||
|
||||
/* verify that the uri starts with an acceptable protocol*/
|
||||
nprotos = (sizeof(legalprotocols)/sizeof(struct NC_ProtocolInfo));
|
||||
proto = NULL;
|
||||
for(i=0;i<nprotos;i++) {
|
||||
if(strcmp(protocol,legalprotocols[i].name)==0) {
|
||||
proto = &legalprotocols[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(proto == NULL)
|
||||
{THROW(6); goto fail; /* illegal protocol*/}
|
||||
|
||||
/* skip // */
|
||||
if(p[0] != '/' && p[1] != '/')
|
||||
{THROW(7); goto fail;}
|
||||
p += 2;
|
||||
|
||||
/* If this is all we have (proto://) then fail */
|
||||
if(*p == EOFCHAR)
|
||||
{THROW(8); goto fail;}
|
||||
|
||||
/* establish the start of the file section */
|
||||
if(proto->filelike) {/* everything after proto:// */
|
||||
file = p;
|
||||
host = NULL; /* and no host section */
|
||||
} else { /*!proto->filelike => This means there should be a host section */
|
||||
/* locate the end of the host section and therefore the start
|
||||
of the file section */
|
||||
host = p;
|
||||
p = nclocate(p,"/?#");
|
||||
if(p == NULL) {
|
||||
file = endof(host); /* there is no file section */
|
||||
} else {
|
||||
ncrshift1(p); /* make room to terminate the host section
|
||||
without overwriting the leading character */
|
||||
terminate(p); /* terminate the host section */
|
||||
file = p+1; /* +1 becauseof the shift */
|
||||
}
|
||||
}
|
||||
|
||||
/* If you shift in the code below, you must reset file beginning */
|
||||
|
||||
if(host != NULL) {/* Parse the host section */
|
||||
/* Check for leading user:pwd@ */
|
||||
p = strchr(host,'@');
|
||||
if(p) {
|
||||
if(p == host)
|
||||
{THROW(9); goto fail; /* we have proto://@ */}
|
||||
user = host;
|
||||
terminate(p); /* overwrite '@' */
|
||||
host = p+1; /* start of host ip name */
|
||||
p = strchr(user,':');
|
||||
if(p == NULL)
|
||||
{THROW(10); goto fail; /* malformed */}
|
||||
terminate(p); /*overwrite colon */
|
||||
pwd = p+1;
|
||||
}
|
||||
|
||||
/* extract host and port */
|
||||
p = host;
|
||||
p = strchr(p,':');
|
||||
if(p != NULL) {
|
||||
terminate(p);
|
||||
p++;
|
||||
port = p;
|
||||
if(*port == EOFCHAR)
|
||||
{THROW(11); goto fail; /* we have proto://...:/ */}
|
||||
/* The port must look something like a number */
|
||||
for(;*p;p++) {
|
||||
if(strchr("0123456789-",*p) == NULL)
|
||||
{THROW(12); goto fail; /* probably not a real port, fail */}
|
||||
}
|
||||
} /* else *p == NULL */
|
||||
|
||||
|
||||
/* check for empty host section */
|
||||
if(*host == EOFCHAR)
|
||||
{THROW(13); goto fail;}
|
||||
|
||||
}
|
||||
|
||||
assert(file != NULL);
|
||||
p = file;
|
||||
|
||||
/* find the end of the file section and the start of the
|
||||
constraints and/or suffixparams
|
||||
*/
|
||||
p = nclocate(p,"?#");
|
||||
if(p != NULL) { /* we have constraint and/or suffixparams */
|
||||
char* fileend = p; /* save the end of the file section */
|
||||
char* constraintend = NULL;
|
||||
if(*p == '?')
|
||||
constraint = p+1;
|
||||
else
|
||||
constraint = NULL;
|
||||
p = strchr(p,'#'); /* may repeat effect of nclocate above */
|
||||
if(p != NULL) {
|
||||
constraintend = p;
|
||||
suffixparams = p+1;
|
||||
} else
|
||||
suffixparams = NULL;
|
||||
/* Ok, terminate the pieces */
|
||||
terminate(fileend); /* terminate file section */
|
||||
if(constraint != NULL && constraintend != NULL)
|
||||
terminate(constraintend);
|
||||
/* Suffix params are already terminated
|
||||
since they should be the last section
|
||||
of the original url
|
||||
*/
|
||||
}
|
||||
|
||||
/* check for empty sections */
|
||||
if(file != NULL && *file == EOFCHAR)
|
||||
file = NULL; /* empty file section */
|
||||
if(constraint != NULL && *constraint == EOFCHAR)
|
||||
constraint = NULL; /* empty constraint section */
|
||||
if(suffixparams != NULL && *suffixparams == EOFCHAR)
|
||||
suffixparams = NULL; /* empty suffixparams section */
|
||||
|
||||
if(suffixparams != NULL) {
|
||||
/* there really are suffix params; so rebuild the suffix params */
|
||||
p = suffixparams;
|
||||
/* There must be brackets */
|
||||
if(*p != LBRACKET)
|
||||
{THROW(14); goto fail;}
|
||||
suffixparams++; /* skip leading LBRACKET */
|
||||
p = suffixparams;
|
||||
/* convert RBRACKET LBRACKET to ';' */
|
||||
for(;*p;p++) {
|
||||
if(p[0] == RBRACKET && p[1] == LBRACKET) {
|
||||
p[0] = ';';
|
||||
nclshift1(p+1);
|
||||
} else if(p[0] == RBRACKET && p[1] != LBRACKET) {
|
||||
/* terminate suffixparams */
|
||||
*p = EOFCHAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*suffixparams == EOFCHAR)
|
||||
suffixparams = NULL; /* suffixparams are empty */
|
||||
}
|
||||
|
||||
/* do last minute empty check */
|
||||
if(protocol != NULL && *protocol == EOFCHAR) protocol = NULL;
|
||||
if(user != NULL && *user == EOFCHAR) user = NULL;
|
||||
if(pwd != NULL && *pwd == EOFCHAR) pwd = NULL;
|
||||
if(host != NULL && *host == EOFCHAR) host = NULL;
|
||||
if(port != NULL && *port == EOFCHAR) port = NULL;
|
||||
if(file != NULL && *file == EOFCHAR) file = NULL;
|
||||
if(constraint != NULL && *constraint == EOFCHAR) constraint = NULL;
|
||||
|
||||
/* assemble the component pieces */
|
||||
ncuri->protocol = protocol;
|
||||
ncuri->user = user;
|
||||
ncuri->password = pwd;
|
||||
ncuri->host = host;
|
||||
ncuri->port = port;
|
||||
ncuri->file = file;
|
||||
|
||||
ncurisetconstraints(ncuri,constraint);
|
||||
|
||||
/* concat suffix and prefix params */
|
||||
if(prefixparams != NULL || suffixparams != NULL) {
|
||||
int plen = prefixparams ? strlen(prefixparams) : 0;
|
||||
int slen = suffixparams ? strlen(suffixparams) : 0;
|
||||
int space = plen + slen + 1;
|
||||
/* add 1 for an extra comma if both are defined */
|
||||
space++;
|
||||
ncuri->params = (char*)malloc(space);
|
||||
ncuri->params[0] = EOFCHAR; /* so we can use strcat */
|
||||
if(plen > 0) {
|
||||
strcat(ncuri->params,prefixparams);
|
||||
if(slen > 0)
|
||||
strcat(ncuri->params,";");
|
||||
}
|
||||
if(slen > 0)
|
||||
strcat(ncuri->params,suffixparams);
|
||||
}
|
||||
|
||||
#ifdef NCXDEBUG
|
||||
{
|
||||
fprintf(stderr,"ncuri:");
|
||||
fprintf(stderr," params=|%s|",FIX(ncuri->params));
|
||||
fprintf(stderr," protocol=|%s|",FIX(ncuri->protocol));
|
||||
fprintf(stderr," host=|%s|",FIX(ncuri->host));
|
||||
fprintf(stderr," port=|%s|",FIX(ncuri->port));
|
||||
fprintf(stderr," file=|%s|",FIX(ncuri->file));
|
||||
fprintf(stderr," constraint=|%s|",FIX(ncuri->constraint));
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
#endif
|
||||
if(ncurip != NULL) *ncurip = ncuri;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
if(ncuri != NULL) {
|
||||
ncurifree(ncuri);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncurifree(NCURI* ncuri)
|
||||
{
|
||||
if(ncuri == NULL) return;
|
||||
if(ncuri->uri != NULL) {free(ncuri->uri);}
|
||||
if(ncuri->params != NULL) {free(ncuri->params);}
|
||||
if(ncuri->paramlist != NULL) ncparamfree(ncuri->paramlist);
|
||||
if(ncuri->strings != NULL) {free(ncuri->strings);}
|
||||
if(ncuri->constraint != NULL) {free(ncuri->constraint);}
|
||||
if(ncuri->projection != NULL) {free(ncuri->projection);}
|
||||
if(ncuri->selection != NULL) {free(ncuri->selection);}
|
||||
free(ncuri);
|
||||
}
|
||||
|
||||
/* Replace the constraints */
|
||||
void
|
||||
ncurisetconstraints(NCURI* duri,const char* constraints)
|
||||
{
|
||||
char* proj = NULL;
|
||||
char* select = NULL;
|
||||
const char* p;
|
||||
|
||||
if(duri->constraint != NULL) free(duri->constraint);
|
||||
if(duri->projection != NULL) free(duri->projection);
|
||||
if(duri->selection != NULL) free(duri->selection);
|
||||
duri->constraint = NULL;
|
||||
duri->projection = NULL;
|
||||
duri->selection = NULL;
|
||||
|
||||
if(constraints == NULL || strlen(constraints)==0) return;
|
||||
|
||||
duri->constraint = nulldup(constraints);
|
||||
if(*duri->constraint == '?')
|
||||
nclshift1(duri->constraint);
|
||||
|
||||
p = duri->constraint;
|
||||
proj = (char*) p;
|
||||
select = strchr(proj,'&');
|
||||
if(select != NULL) {
|
||||
size_t plen = (select - proj);
|
||||
if(plen == 0) {
|
||||
proj = NULL;
|
||||
} else {
|
||||
proj = (char*)malloc(plen+1);
|
||||
memcpy((void*)proj,p,plen);
|
||||
proj[plen] = EOFCHAR;
|
||||
}
|
||||
select = nulldup(select);
|
||||
} else {
|
||||
proj = nulldup(proj);
|
||||
select = NULL;
|
||||
}
|
||||
duri->projection = proj;
|
||||
duri->selection = select;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a complete NC URI.
|
||||
Optionally with the constraints.
|
||||
Optionally with the user parameters.
|
||||
Caller frees returned string.
|
||||
Optionally encode the pieces.
|
||||
*/
|
||||
|
||||
char*
|
||||
ncuribuild(NCURI* duri, const char* prefix, const char* suffix, int flags)
|
||||
{
|
||||
size_t len = 0;
|
||||
char* newuri;
|
||||
char* tmpfile;
|
||||
char* tmpsuffix;
|
||||
char* tmpquery;
|
||||
int nparams = 0;
|
||||
int paramslen = 0;
|
||||
|
||||
/* if both are specified, prefix has priority */
|
||||
int withsuffixparams = ((flags&NCURISUFFIXPARAMS)!=0
|
||||
&& duri->params != NULL);
|
||||
int withprefixparams = ((flags&NCURIPREFIXPARAMS)!=0
|
||||
&& duri->params != NULL);
|
||||
int withuserpwd = ((flags&NCURIUSERPWD)!=0
|
||||
&& duri->user != NULL && duri->password != NULL);
|
||||
int withconstraints = ((flags&NCURICONSTRAINTS)!=0
|
||||
&& duri->constraint != NULL);
|
||||
#ifdef NEWESCAPE
|
||||
int encode = (flags&NCURIENCODE);
|
||||
#else
|
||||
int encode = 0;
|
||||
#endif
|
||||
|
||||
if(prefix != NULL) len += NILLEN(prefix);
|
||||
len += (NILLEN(duri->protocol)+NILLEN("://"));
|
||||
if(withuserpwd) {
|
||||
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
|
||||
}
|
||||
len += (NILLEN(duri->host));
|
||||
if(duri->port != NULL) {
|
||||
len += (NILLEN(":")+NILLEN(duri->port));
|
||||
}
|
||||
|
||||
tmpfile = duri->file;
|
||||
if(encode)
|
||||
tmpfile = ncuriencode(tmpfile,fileallow);
|
||||
len += (NILLEN(tmpfile));
|
||||
|
||||
if(suffix != NULL) {
|
||||
tmpsuffix = (char*)suffix;
|
||||
if(encode)
|
||||
tmpsuffix = ncuriencode(tmpsuffix,fileallow);
|
||||
len += (NILLEN(tmpsuffix));
|
||||
}
|
||||
|
||||
if(withconstraints) {
|
||||
tmpquery = duri->constraint;
|
||||
if(encode)
|
||||
tmpquery = ncuriencode(tmpquery,queryallow);
|
||||
len += (NILLEN("?")+NILLEN(tmpquery));
|
||||
}
|
||||
|
||||
if(withprefixparams || withsuffixparams) {
|
||||
char** p;
|
||||
if(duri->paramlist == NULL)
|
||||
if(!ncuridecodeparams(duri))
|
||||
return NULL;
|
||||
for(paramslen=0,nparams=0,p=duri->paramlist;*p;p++) {
|
||||
nparams++;
|
||||
paramslen += NILLEN(*p);
|
||||
}
|
||||
if(nparams % 2 == 1)
|
||||
return NULL; /* malformed */
|
||||
nparams = (nparams / 2);
|
||||
len += paramslen;
|
||||
len += 3*nparams; /* for brackets for every param plus possible = */
|
||||
if(withsuffixparams)
|
||||
len += strlen("#");
|
||||
}
|
||||
|
||||
len += 1; /* null terminator */
|
||||
|
||||
newuri = (char*)malloc(len);
|
||||
if(newuri == NULL) return NULL;
|
||||
|
||||
newuri[0] = EOFCHAR;
|
||||
if(prefix != NULL) strcat(newuri,prefix);
|
||||
if(withprefixparams) {
|
||||
ncappendparams(newuri,duri->paramlist);
|
||||
}
|
||||
if(duri->protocol != NULL)
|
||||
strcat(newuri,duri->protocol);
|
||||
strcat(newuri,"://");
|
||||
if(withuserpwd) {
|
||||
strcat(newuri,duri->user);
|
||||
strcat(newuri,":");
|
||||
strcat(newuri,duri->password);
|
||||
strcat(newuri,"@");
|
||||
}
|
||||
if(duri->host != NULL) { /* may be null if using file: protocol */
|
||||
strcat(newuri,duri->host);
|
||||
}
|
||||
if(duri->port != NULL) {
|
||||
strcat(newuri,":");
|
||||
strcat(newuri,duri->port);
|
||||
}
|
||||
|
||||
if(tmpfile != NULL) {
|
||||
strcat(newuri,tmpfile);
|
||||
if(suffix != NULL) strcat(newuri,tmpsuffix);
|
||||
}
|
||||
if(withconstraints) {
|
||||
strcat(newuri,"?");
|
||||
strcat(newuri,tmpquery);
|
||||
}
|
||||
if(withsuffixparams & !withprefixparams) {
|
||||
strcat(newuri,"#");
|
||||
ncappendparams(newuri,duri->paramlist);
|
||||
}
|
||||
return newuri;
|
||||
}
|
||||
|
||||
static void
|
||||
ncappendparams(char* newuri, char** p)
|
||||
{
|
||||
while(*p) {
|
||||
strcat(newuri,"[");
|
||||
strcat(newuri,*p++);
|
||||
if(strlen(*p) > 0) {
|
||||
strcat(newuri,"=");
|
||||
strcat(newuri,*p);
|
||||
}
|
||||
p++;
|
||||
strcat(newuri,"]");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Parameter support */
|
||||
|
||||
/*
|
||||
In the original url, client parameters are assumed to be one
|
||||
or more instances of bracketed pairs: e.g "[...][...]...".
|
||||
They may occur either at the front, or suffixed after
|
||||
a trailing # character After processing, the list is
|
||||
converted to a semicolon separated list of the combination
|
||||
of prefix and suffix parameters.
|
||||
|
||||
After the url is parsed, the parameter list
|
||||
is converted to a semicolon separated list with all
|
||||
whitespace removed.
|
||||
In any case, each parameter in turn is assumed to be a
|
||||
of the form <name>=<value> or [<name>].
|
||||
e.g. [x=y][z][a=b][w]. If the same parameter is specified more
|
||||
than once, then the first occurrence is used; this is so
|
||||
that is possible to forcibly override user specified
|
||||
parameters by prefixing. IMPORTANT: client parameter string
|
||||
is assumed to have blanks compressed out. Returns 1 if parse
|
||||
suceeded, 0 otherwise; */
|
||||
|
||||
int
|
||||
ncuridecodeparams(NCURI* ncuri)
|
||||
{
|
||||
char* cp;
|
||||
int i,c;
|
||||
int nparams;
|
||||
char* params;
|
||||
char** plist;
|
||||
|
||||
if(ncuri == NULL) return 0;
|
||||
if(ncuri->params == NULL) return 1;
|
||||
|
||||
params = strdup(ncuri->params); /* so we can modify */
|
||||
|
||||
/* Pass 1 to break string into pieces at the semicolons
|
||||
and count # of pairs */
|
||||
nparams=0;
|
||||
for(cp=params;(c=*cp);cp++) {
|
||||
if(c == ';') {*cp = EOFCHAR; nparams++;}
|
||||
}
|
||||
nparams++; /* for last one */
|
||||
|
||||
/* plist is an env style list */
|
||||
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
|
||||
|
||||
/* Break up each param into a (name,value) pair*/
|
||||
/* and insert into the param list */
|
||||
/* parameters of the form name name= are converted to name=""*/
|
||||
for(cp=params,i=0;i<nparams;i++) {
|
||||
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
|
||||
char* vp;
|
||||
/*break up the ith param*/
|
||||
vp = strchr(cp,'=');
|
||||
if(vp != NULL) {*vp = EOFCHAR; vp++;} else {vp = "";}
|
||||
plist[2*i] = nulldup(cp);
|
||||
plist[2*i+1] = nulldup(vp);
|
||||
cp = next;
|
||||
}
|
||||
plist[2*nparams] = NULL;
|
||||
free(params);
|
||||
if(ncuri->paramlist != NULL)
|
||||
ncparamfree(ncuri->paramlist);
|
||||
ncuri->paramlist = plist;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ncurilookup(NCURI* uri, const char* key, const char** resultp)
|
||||
{
|
||||
int i;
|
||||
char* value = NULL;
|
||||
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
|
||||
if(uri->paramlist == NULL) {
|
||||
i = ncuridecodeparams(uri);
|
||||
if(!i) return 0;
|
||||
}
|
||||
i = ncfind(uri->paramlist,key);
|
||||
if(i < 0)
|
||||
return 0;
|
||||
value = uri->paramlist[(2*i)+1];
|
||||
if(resultp) *resultp = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ncurisetparams(NCURI* uri, const char* newparams)
|
||||
{
|
||||
if(uri == NULL) return 0;
|
||||
if(uri->paramlist != NULL) ncparamfree(uri->paramlist);
|
||||
uri->paramlist = NULL;
|
||||
if(uri->params != NULL) free(uri->params);
|
||||
uri->params = nulldup(newparams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Internal version of lookup; returns the paired index of the key */
|
||||
static int
|
||||
ncfind(char** params, const char* key)
|
||||
{
|
||||
int i;
|
||||
char** p;
|
||||
for(i=0,p=params;*p;p+=2,i++) {
|
||||
if(strcmp(key,*p)==0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
ncparamfree(char** params)
|
||||
{
|
||||
char** p;
|
||||
if(params == NULL) return;
|
||||
for(p=params;*p;p+=2) {
|
||||
free(*p);
|
||||
if(p[1] != NULL) free(p[1]);
|
||||
}
|
||||
free(params);
|
||||
}
|
||||
|
||||
|
||||
/* Return the ptr to the first occurrence of
|
||||
any char in the list. Return NULL if no
|
||||
occurrences
|
||||
*/
|
||||
static char*
|
||||
nclocate(char* p, const char* charlist)
|
||||
{
|
||||
for(;*p;p++) {
|
||||
if(strchr(charlist,*p) != NULL)
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Shift every char starting at p 1 place to the left */
|
||||
static void
|
||||
nclshift1(char* p)
|
||||
{
|
||||
if(p != NULL && *p != EOFCHAR) {
|
||||
char* q = p++;
|
||||
while((*q++=*p++));
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift every char starting at p 1 place to the right */
|
||||
static void
|
||||
ncrshift1(char* p)
|
||||
{
|
||||
char cur;
|
||||
cur = 0;
|
||||
do {
|
||||
char next = *p;
|
||||
*p++ = cur;
|
||||
cur = next;
|
||||
} while(cur != 0);
|
||||
*p = 0; /* make sure we are still null terminated */
|
||||
}
|
||||
|
||||
|
||||
/* Provide % encoders and decoders */
|
||||
|
||||
|
||||
static char* hexchars = "0123456789abcdefABCDEF";
|
||||
|
||||
static void
|
||||
toHex(unsigned int b, char hex[2])
|
||||
{
|
||||
hex[0] = hexchars[(b >> 4) & 0xff];
|
||||
hex[1] = hexchars[(b) & 0xff];
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
fromHex(int c)
|
||||
{
|
||||
if(c >= '0' && c <= '9') return (c - '0');
|
||||
if(c >= 'a' && c <= 'f') return (10 + (c - 'a'));
|
||||
if(c >= 'A' && c <= 'F') return (10 + (c - 'A'));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Return a string representing encoding of input; caller must free;
|
||||
watch out: will encode whole string, so watch what you give it.
|
||||
Allowable argument specifies characters that do not need escaping.
|
||||
*/
|
||||
|
||||
char*
|
||||
ncuriencode(char* s, char* allowable)
|
||||
{
|
||||
size_t slen;
|
||||
char* encoded;
|
||||
char* inptr;
|
||||
char* outptr;
|
||||
|
||||
if(s == NULL) return NULL;
|
||||
|
||||
slen = strlen(s);
|
||||
encoded = (char*)malloc((3*slen) + 1); /* max possible size */
|
||||
|
||||
for(inptr=s,outptr=encoded;*inptr;) {
|
||||
int c = *inptr++;
|
||||
if(c == ' ') {
|
||||
*outptr++ = '+';
|
||||
} else {
|
||||
/* search allowable */
|
||||
int c2;
|
||||
char* a = allowable;
|
||||
while((c2=*a++)) {
|
||||
if(c == c2) break;
|
||||
}
|
||||
if(c2) {*outptr++ = c;}
|
||||
else {
|
||||
char hex[2];
|
||||
toHex(c,hex);
|
||||
*outptr++ = '%';
|
||||
*outptr++ = hex[0];
|
||||
*outptr++ = hex[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
*outptr = EOFCHAR;
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/* Return a string representing decoding of input; caller must free;*/
|
||||
char*
|
||||
ncuridecode(char* s)
|
||||
{
|
||||
return ncuridecodeonly(s,NULL);
|
||||
}
|
||||
|
||||
/* Return a string representing decoding of input only for specified
|
||||
characters; caller must free
|
||||
*/
|
||||
char*
|
||||
ncuridecodeonly(char* s, char* only)
|
||||
{
|
||||
size_t slen;
|
||||
char* decoded;
|
||||
char* outptr;
|
||||
char* inptr;
|
||||
unsigned int c;
|
||||
|
||||
if (s == NULL) return NULL;
|
||||
if(only == NULL) only = "";
|
||||
|
||||
slen = strlen(s);
|
||||
decoded = (char*)malloc(slen+1); /* Should be max we need */
|
||||
|
||||
outptr = decoded;
|
||||
inptr = s;
|
||||
while((c = *inptr++)) {
|
||||
if(c == '+' && strchr(only,'+') != NULL)
|
||||
*outptr++ = ' ';
|
||||
else if(c == '%') {
|
||||
/* try to pull two hex more characters */
|
||||
if(inptr[0] != EOFCHAR && inptr[1] != EOFCHAR
|
||||
&& strchr(hexchars,inptr[0]) != NULL
|
||||
&& strchr(hexchars,inptr[1]) != NULL) {
|
||||
/* test conversion */
|
||||
int xc = (fromHex(inptr[0]) << 4) | (fromHex(inptr[1]));
|
||||
if(strchr(only,xc) != NULL) {
|
||||
inptr += 2; /* decode it */
|
||||
c = xc;
|
||||
}
|
||||
}
|
||||
}
|
||||
*outptr++ = c;
|
||||
}
|
||||
*outptr = EOFCHAR;
|
||||
return decoded;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -145,7 +143,7 @@ ocbytesappendn(OCbytes* bb, const void* elem, unsigned int n)
|
||||
}
|
||||
|
||||
int
|
||||
ocbytesprepend(OCbytes* bb, const char elem)
|
||||
ocbytesprepend(OCbytes* bb, char elem)
|
||||
{
|
||||
int i; /* do not make unsigned */
|
||||
if(bb == NULL) return ocbytesfail();
|
||||
@ -188,3 +186,14 @@ ocbytessetcontents(OCbytes* bb, char* contents, unsigned int alloc)
|
||||
bb->nonextendible = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Null terminate the byte string without extending its length */
|
||||
/* For debugging */
|
||||
int
|
||||
ocbytesnull(OCbytes* bb)
|
||||
{
|
||||
ocbytesappend(bb,'\0');
|
||||
bb->length--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -34,19 +34,23 @@ EXTERNC int ocbytesget(OCbytes*,unsigned int);
|
||||
EXTERNC int ocbytesset(OCbytes*,unsigned int,char);
|
||||
|
||||
/* Append one byte */
|
||||
EXTERNC int ocbytesappend(OCbytes*,const char); /* Add at Tail */
|
||||
EXTERNC int ocbytesappend(OCbytes*,char); /* Add at Tail */
|
||||
/* Append n bytes */
|
||||
EXTERNC int ocbytesappendn(OCbytes*,const void*,unsigned int); /* Add at Tail */
|
||||
|
||||
/* Null terminate the byte string without extending its length (for debugging) */
|
||||
EXTERNC int ocbytesnull(OCbytes*);
|
||||
|
||||
/* Concatenate a null-terminated string to the end of the buffer */
|
||||
EXTERNC int ocbytescat(OCbytes*,const char*);
|
||||
|
||||
/* Set the contents of the buffer; mark the buffer as non-extendible */
|
||||
EXTERNC int ocbytessetcontents(OCbytes*, char*, unsigned int);
|
||||
|
||||
/* Following are always "in-lined"*/
|
||||
#define ocbyteslength(bb) ((bb)!=NULL?(bb)->length:0U)
|
||||
#define ocbytesalloc(bb) ((bb)!=NULL?(bb)->alloc:0U)
|
||||
#define ocbytescontents(bb) (((bb) !=NULL && (bb)->content != NULL)?(bb)->content:(char*)"")
|
||||
#define ocbytescontents(bb) (((bb)!=NULL && (bb)->content!=NULL)?(bb)->content:(char*)"")
|
||||
#define ocbytesextend(bb,len) ocbytessetalloc((bb),(len)+(bb->alloc))
|
||||
#define ocbytesclear(bb) ((bb)!=NULL?(bb)->length=0:0U)
|
||||
#define ocbytesavail(bb,n) ((bb)!=NULL?((bb)->alloc - (bb)->length) >= (n):0U)
|
||||
|
@ -37,8 +37,11 @@ ocparamdecode(OCstate* state)
|
||||
const char*
|
||||
ocparamlookup(OCstate* state, const char* key)
|
||||
{
|
||||
const char* value = NULL;
|
||||
if(state == NULL || key == NULL || state->uri == NULL) return NULL;
|
||||
return ocurilookup(state->uri,key);
|
||||
if(!ocurilookup(state->uri,key,&value))
|
||||
value = NULL;
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -151,7 +151,7 @@ occompile1(OCstate* state, OCnode* xnode, XXDR* xxdrs, OCdata** datap)
|
||||
} else if(tmp[0] == EndOfSequence) {
|
||||
break; /* we are done with the this sequence instance*/
|
||||
} else {
|
||||
oc_log(LOGERR,"missing/invalid begin/end record marker\n");
|
||||
oclog(OCLOGERR,"missing/invalid begin/end record marker\n");
|
||||
ocstat = OC_EINVALCOORDS;
|
||||
goto fail;
|
||||
}
|
||||
@ -408,7 +408,7 @@ ocerrorstring(XXDR* xdrs)
|
||||
if(ocstrncmp(data,tag,sizeof(tag))==0) {
|
||||
char* p;
|
||||
if((p=strchr(data,'}')) != NULL) *(++p)='\0';
|
||||
oc_log(LOGERR,"Server error: %s",data);
|
||||
oclog(OCLOGERR,"Server error: %s",data);
|
||||
/* Since important, report to stderr as well */
|
||||
fprintf(stderr,"Server error: %s",data);
|
||||
return 1;
|
||||
|
@ -42,8 +42,8 @@ oc_curl_protocols(struct OCGLOBALSTATE* state)
|
||||
if(strcmp("http",*proto)==0) {state->curl.proto_https=1;break;}
|
||||
}
|
||||
if(ocdebug > 0) {
|
||||
oc_log(LOGNOTE,"Curl file:// support = %d",state->curl.proto_file);
|
||||
oc_log(LOGNOTE,"Curl https:// support = %d",state->curl.proto_https);
|
||||
oclog(OCLOGNOTE,"Curl file:// support = %d",state->curl.proto_file);
|
||||
oclog(OCLOGNOTE,"Curl https:// support = %d",state->curl.proto_https);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ combinecredentials(const char* user, const char* pwd)
|
||||
int userPassSize = strlen(user) + strlen(pwd) + 2;
|
||||
char *userPassword = malloc(sizeof(char) * userPassSize);
|
||||
if (!userPassword) {
|
||||
oc_log(LOGERR,"Out of Memory\n");
|
||||
oclog(OCLOGERR,"Out of Memory\n");
|
||||
return NULL;
|
||||
}
|
||||
strcpy(userPassword, user);
|
||||
|
@ -404,7 +404,7 @@ ocread(OCdata* data, XXDR* xdrs, char* memory, size_t memsize, size_t start, siz
|
||||
return OC_NOERR;
|
||||
|
||||
xdrfail:
|
||||
oc_log(LOGERR,"DAP DATADDS packet is apparently too short");
|
||||
oclog(OCLOGERR,"DAP DATADDS packet is apparently too short");
|
||||
return OCTHROW(OC_EDATADDS);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ octhrow(int err)
|
||||
int
|
||||
xdrerror(void)
|
||||
{
|
||||
oc_log(LOGERR,"xdr failure");
|
||||
oclog(OCLOGERR,"xdr failure");
|
||||
return OCTHROW(OC_EDATADDS);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ void*
|
||||
ocmalloc(size_t size)
|
||||
{
|
||||
void* memory = calloc(size,1); /* use calloc to zero memory*/
|
||||
if(memory == NULL) oc_log(LOGERR,"ocmalloc: out of memory");
|
||||
if(memory == NULL) oclog(OCLOGERR,"ocmalloc: out of memory");
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,10 @@
|
||||
|
||||
/* Need some syntactic trickery to make these macros work*/
|
||||
#ifdef OCDEBUG
|
||||
#define OCDBG(l,msg) {oc_log(LOGDBG,msg);}
|
||||
#define OCDBG1(l,msg,arg) {oc_log(LOGDBG,msg,arg);}
|
||||
#define OCDBG2(l,msg,arg1,arg2) {oc_log(LOGDBG,msg,arg1,arg2);}
|
||||
#define OCDBGTEXT(l,text) {oc_logtext(LOGNOTE,text);} else {}
|
||||
#define OCDBG(l,msg) {oclog(OCLOGDBG,msg);}
|
||||
#define OCDBG1(l,msg,arg) {oclog(OCLOGDBG,msg,arg);}
|
||||
#define OCDBG2(l,msg,arg1,arg2) {oclog(OCLOGDBG,msg,arg1,arg2);}
|
||||
#define OCDBGTEXT(l,text) {oclogtext(OCLOGNOTE,text);} else {}
|
||||
#define OCDBGCODE(l,code) {code;}
|
||||
|
||||
#else
|
||||
|
24
oc2/ochttp.c
24
oc2/ochttp.c
@ -68,7 +68,7 @@ ocfetchurl_file(CURL* curl, const char* url, FILE* stream,
|
||||
if (stat == OC_NOERR) {
|
||||
/* return the file size*/
|
||||
#ifdef OCDEBUG
|
||||
oc_log(LOGNOTE,"filesize: %lu bytes",fetchdata.size);
|
||||
oclog(OCLOGNOTE,"filesize: %lu bytes",fetchdata.size);
|
||||
#endif
|
||||
if (sizep != NULL)
|
||||
*sizep = fetchdata.size;
|
||||
@ -80,7 +80,7 @@ ocfetchurl_file(CURL* curl, const char* url, FILE* stream,
|
||||
return OCTHROW(stat);
|
||||
|
||||
fail:
|
||||
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
return OCTHROW(OC_ECURL);
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ ocfetchurl(CURL* curl, const char* url, OCbytes* buf, long* filetime)
|
||||
cstat = curl_easy_perform(curl);
|
||||
if(cstat == CURLE_PARTIAL_FILE) {
|
||||
/* Log it but otherwise ignore */
|
||||
oc_log(LOGWARN, "curl error: %s; ignored",
|
||||
oclog(OCLOGWARN, "curl error: %s; ignored",
|
||||
curl_easy_strerror(cstat));
|
||||
cstat = CURLE_OK;
|
||||
}
|
||||
@ -128,13 +128,13 @@ ocfetchurl(CURL* curl, const char* url, OCbytes* buf, long* filetime)
|
||||
ocbytesappend(buf, '\0');
|
||||
ocbytessetlength(buf, len); /* dont count null in buffer size*/
|
||||
#ifdef OCDEBUG
|
||||
oc_log(LOGNOTE,"buffersize: %lu bytes",(off_t)ocbyteslength(buf));
|
||||
oclog(OCLOGNOTE,"buffersize: %lu bytes",(off_t)ocbyteslength(buf));
|
||||
#endif
|
||||
|
||||
return OCTHROW(stat);
|
||||
|
||||
fail:
|
||||
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
return OCTHROW(OC_ECURL);
|
||||
}
|
||||
|
||||
@ -146,15 +146,15 @@ WriteFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
|
||||
struct Fetchdata* fetchdata;
|
||||
fetchdata = (struct Fetchdata*) data;
|
||||
if(realsize == 0)
|
||||
oc_log(LOGWARN,"WriteFileCallback: zero sized chunk");
|
||||
oclog(OCLOGWARN,"WriteFileCallback: zero sized chunk");
|
||||
count = fwrite(ptr, size, nmemb, fetchdata->stream);
|
||||
if (count > 0) {
|
||||
fetchdata->size += (count * size);
|
||||
} else {
|
||||
oc_log(LOGWARN,"WriteFileCallback: zero sized write");
|
||||
oclog(OCLOGWARN,"WriteFileCallback: zero sized write");
|
||||
}
|
||||
#ifdef OCPROGRESS
|
||||
oc_log(LOGNOTE,"callback: %lu bytes",(off_t)realsize);
|
||||
oclog(OCLOGNOTE,"callback: %lu bytes",(off_t)realsize);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
@ -165,7 +165,7 @@ WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
size_t realsize = size * nmemb;
|
||||
OCbytes* buf = (OCbytes*) data;
|
||||
if(realsize == 0)
|
||||
oc_log(LOGWARN,"WriteMemoryCallback: zero sized chunk");
|
||||
oclog(OCLOGWARN,"WriteMemoryCallback: zero sized chunk");
|
||||
/* Optimize for reading potentially large dods datasets */
|
||||
if(!ocbytesavail(buf,realsize)) {
|
||||
/* double the size of the packet */
|
||||
@ -173,7 +173,7 @@ WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
}
|
||||
ocbytesappendn(buf, ptr, realsize);
|
||||
#ifdef OCPROGRESS
|
||||
oc_log(LOGNOTE,"callback: %lu bytes",(off_t)realsize);
|
||||
oclog(OCLOGNOTE,"callback: %lu bytes",(off_t)realsize);
|
||||
#endif
|
||||
return realsize;
|
||||
}
|
||||
@ -283,7 +283,7 @@ ocfetchlastmodified(CURL* curl, char* url, long* filetime)
|
||||
return OCTHROW(stat);
|
||||
|
||||
fail:
|
||||
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
return OCTHROW(OC_ECURL);
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ done:
|
||||
ocbytesfree(buf);
|
||||
occurlclose(curl);
|
||||
if(cstat != CURLE_OK) {
|
||||
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
stat = OC_EDAPSVC;
|
||||
}
|
||||
return OCTHROW(stat);
|
||||
|
@ -68,7 +68,7 @@ ocinternalinitialize(void)
|
||||
/* Compute some xdr related flags */
|
||||
xxdr_init();
|
||||
|
||||
oc_loginit();
|
||||
ocloginit();
|
||||
|
||||
oc_curl_protocols(&ocglobalstate); /* see what protocols are supported */
|
||||
|
||||
@ -106,14 +106,14 @@ ocinternalinitialize(void)
|
||||
}
|
||||
}
|
||||
if(f == NULL) {
|
||||
oc_log(LOGDBG,"Cannot find runtime configuration file");
|
||||
oclog(OCLOGDBG,"Cannot find runtime configuration file");
|
||||
} else {
|
||||
OCASSERT(path != NULL);
|
||||
fclose(f);
|
||||
if(ocdebug > 1)
|
||||
fprintf(stderr, "DODS RC file: %s\n", path);
|
||||
if(ocdodsrc_read(*alias,path) == 0)
|
||||
oc_log(LOGERR, "Error parsing %s\n",path);
|
||||
oclog(OCLOGERR, "Error parsing %s\n",path);
|
||||
}
|
||||
if(path != NULL) free(path);
|
||||
}
|
||||
@ -144,7 +144,7 @@ ocopen(OCstate** statep, const char* url)
|
||||
state->trees = oclistnew();
|
||||
state->uri = tmpurl;
|
||||
if(!ocuridecodeparams(state->uri)) {
|
||||
oc_log(LOGWARN,"Could not parse client parameters");
|
||||
oclog(OCLOGWARN,"Could not parse client parameters");
|
||||
}
|
||||
state->packet = ocbytesnew();
|
||||
ocbytessetalloc(state->packet,DFALTPACKETSIZE); /*initial reasonable size*/
|
||||
@ -231,9 +231,9 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
|
||||
/* Obtain any http code */
|
||||
state->error.httpcode = ocfetchhttpcode(state->curl);
|
||||
if(state->error.httpcode >= 400) {
|
||||
oc_log(LOGWARN,"oc_open: Could not read url; http error = %l",state->error.httpcode);
|
||||
oclog(OCLOGWARN,"oc_open: Could not read url; http error = %l",state->error.httpcode);
|
||||
} else {
|
||||
oc_log(LOGWARN,"oc_open: Could not read url");
|
||||
oclog(OCLOGWARN,"oc_open: Could not read url");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
@ -242,7 +242,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
|
||||
stat = DAPparse(state,tree,tree->text);
|
||||
/* Check and report on an error return from the server */
|
||||
if(stat == OC_EDAPSVC && state->error.code != NULL) {
|
||||
oc_log(LOGERR,"oc_open: server error retrieving url: code=%s message=\"%s\"",
|
||||
oclog(OCLOGERR,"oc_open: server error retrieving url: code=%s message=\"%s\"",
|
||||
state->error.code,
|
||||
(state->error.message?state->error.message:""));
|
||||
}
|
||||
@ -319,11 +319,11 @@ createtempfile(OCstate* state, OCtree* tree)
|
||||
if(fd < 0)
|
||||
fd = createtempfile1(TMPPATH2,&name);
|
||||
if(fd < 0) {
|
||||
oc_log(LOGERR,"oc_open: attempt to open tmp file failed: %s",name);
|
||||
oclog(OCLOGERR,"oc_open: attempt to open tmp file failed: %s",name);
|
||||
return errno;
|
||||
}
|
||||
#ifdef OCDEBUG
|
||||
oc_log(LOGNOTE,"oc_open: using tmp file: %s",name);
|
||||
oclog(OCLOGNOTE,"oc_open: using tmp file: %s",name);
|
||||
#endif
|
||||
tree->data.filename = name; /* remember our tmp file name */
|
||||
tree->data.file = fdopen(fd,"w+");
|
||||
@ -532,7 +532,7 @@ ocsetcurlproperties(OCstate* state)
|
||||
|
||||
/* process the triple store wrt to this state */
|
||||
if(ocdodsrc_process(state) != OC_NOERR) {
|
||||
oc_log(LOGERR,"Malformed .opendaprc configuration file");
|
||||
oclog(OCLOGERR,"Malformed .opendaprc configuration file");
|
||||
goto fail;
|
||||
}
|
||||
if(state->creds.username == NULL && state->creds.password == NULL) {
|
||||
@ -548,6 +548,6 @@ ocsetcurlproperties(OCstate* state)
|
||||
|
||||
fail:
|
||||
if(cstat != CURLE_OK)
|
||||
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
|
||||
return;
|
||||
}
|
||||
|
79
oc2/oclist.c
79
oc2/oclist.c
@ -1,8 +1,5 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -24,7 +21,7 @@ int oclistnull(ocelem e) {return e == ocDATANULL;}
|
||||
#define DEFAULTALLOC 16
|
||||
#define ALLOCINCR 16
|
||||
|
||||
OClist* oclistnewn(int prealloc)
|
||||
OClist* oclistnew(void)
|
||||
{
|
||||
OClist* l;
|
||||
/*
|
||||
@ -33,13 +30,11 @@ OClist* oclistnewn(int prealloc)
|
||||
ocinitialized = 1;
|
||||
}
|
||||
*/
|
||||
if(prealloc < 0) prealloc = 0;
|
||||
l = (OClist*)malloc(sizeof(OClist));
|
||||
if(l) {
|
||||
l->alloc=prealloc;
|
||||
l->length=prealloc;
|
||||
l->content=(prealloc==0?NULL:(ocelem*)calloc(prealloc,sizeof(ocelem)));
|
||||
if(l == NULL) {free(l);return 0;}
|
||||
l->alloc=0;
|
||||
l->length=0;
|
||||
l->content=NULL;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
@ -65,8 +60,8 @@ oclistsetalloc(OClist* l, unsigned int sz)
|
||||
newcontent=(ocelem*)calloc(sz,sizeof(ocelem));
|
||||
if(l->alloc > 0 && l->length > 0 && l->content != NULL) {
|
||||
memcpy((void*)newcontent,(void*)l->content,sizeof(ocelem)*l->length);
|
||||
free(l->content);
|
||||
}
|
||||
if(l->content != NULL) free(l->content);
|
||||
l->content=newcontent;
|
||||
l->alloc=sz;
|
||||
return TRUE;
|
||||
@ -102,11 +97,11 @@ oclistset(OClist* l, unsigned int index, ocelem elem)
|
||||
int
|
||||
oclistinsert(OClist* l, unsigned int index, ocelem elem)
|
||||
{
|
||||
unsigned int i;
|
||||
int i; /* do not make unsigned */
|
||||
if(l == NULL) return FALSE;
|
||||
if(index > l->length) return FALSE;
|
||||
oclistsetalloc(l,0);
|
||||
for(i=l->length;i>index;i--) l->content[i] = l->content[i-1];
|
||||
for(i=(int)l->length;i>index;i--) l->content[i] = l->content[i-1];
|
||||
l->content[index] = elem;
|
||||
l->length++;
|
||||
return TRUE;
|
||||
@ -145,7 +140,7 @@ oclistremove(OClist* l, unsigned int i)
|
||||
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
|
||||
if(i >= len) return ocDATANULL;
|
||||
elem = l->content[i];
|
||||
for(i++;i<len;i++) l->content[i-1] = l->content[i];
|
||||
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
|
||||
l->length--;
|
||||
return elem;
|
||||
}
|
||||
@ -169,3 +164,61 @@ oclistcontains(OClist* list, ocelem elem)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove element by value; only removes first encountered */
|
||||
int
|
||||
oclistelemremove(OClist* l, ocelem elem)
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned int i;
|
||||
int found = 0;
|
||||
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
|
||||
for(i=0;i<oclistlength(l);i++) {
|
||||
ocelem candidate = l->content[i];
|
||||
if(elem == candidate) {
|
||||
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
|
||||
l->length--;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Extends oclist to include a unique operator
|
||||
which remove duplicate values; NULL values removed
|
||||
return value is always 1.
|
||||
*/
|
||||
|
||||
int
|
||||
oclistunique(OClist* list)
|
||||
{
|
||||
unsigned int i,j,k,len;
|
||||
ocelem* content;
|
||||
if(list == NULL || list->length == 0) return 1;
|
||||
len = list->length;
|
||||
content = list->content;
|
||||
for(i=0;i<len;i++) {
|
||||
for(j=i+1;j<len;j++) {
|
||||
if(content[i] == content[j]) {
|
||||
/* compress out jth element */
|
||||
for(k=j+1;k<len;k++) content[k-1] = content[k];
|
||||
len--;
|
||||
}
|
||||
}
|
||||
}
|
||||
list->length = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
OClist*
|
||||
oclistclone(OClist* list)
|
||||
{
|
||||
OClist* clone = oclistnew();
|
||||
*clone = *list;
|
||||
clone->content = oclistdup(list);
|
||||
return clone;
|
||||
}
|
||||
|
17
oc2/oclist.h
17
oc2/oclist.h
@ -21,7 +21,7 @@ typedef struct OClist {
|
||||
ocelem* content;
|
||||
} OClist;
|
||||
|
||||
EXTERNC OClist* oclistnewn(int);
|
||||
EXTERNC OClist* oclistnew(void);
|
||||
EXTERNC int oclistfree(OClist*);
|
||||
EXTERNC int oclistsetalloc(OClist*,unsigned int);
|
||||
EXTERNC int oclistsetlength(OClist*,unsigned int);
|
||||
@ -46,12 +46,19 @@ EXTERNC ocelem* oclistdup(OClist*);
|
||||
/* Look for value match */
|
||||
EXTERNC int oclistcontains(OClist*, ocelem);
|
||||
|
||||
/* Remove element by value; only removes first encountered */
|
||||
EXTERNC int oclistelemremove(OClist* l, ocelem elem);
|
||||
|
||||
/* remove duplicates */
|
||||
EXTERNC int oclistunique(OClist*);
|
||||
|
||||
/* Create a clone of a list */
|
||||
EXTERNC OClist* oclistclone(OClist*);
|
||||
|
||||
/* Following are always "in-lined"*/
|
||||
#define oclistnew() oclistnewn(0)
|
||||
#define oclistclear(l) oclistsetlength((l),0U)
|
||||
#define oclistextend(l,len) oclistsetalloc((l),(len)+(l->alloc))
|
||||
#define oclistcontents(l) ((l)->content)
|
||||
#define oclistlength(l) ((l!=NULL)?(l)->length:0U)
|
||||
#define oclistcontents(l) ((l)==NULL?NULL:(l)->content)
|
||||
#define oclistlength(l) ((l)==NULL?0U:(l)->length)
|
||||
|
||||
#endif /*OCLIST_H*/
|
||||
|
||||
|
145
oc2/oclog.c
145
oc2/oclog.c
@ -1,22 +1,33 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
/*********************************************************************
|
||||
* Copyright 2010, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ocinternal.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "oclog.h"
|
||||
|
||||
#define PREFIXLEN 8
|
||||
#define MAXTAGS 256
|
||||
#define OCTAGDFALT "Log";
|
||||
|
||||
#define ENVFLAG "OCLOGFILE"
|
||||
|
||||
static int ocloginit = 0;
|
||||
static int oclogginginitialized = 0;
|
||||
static int oclogging = 0;
|
||||
static int ocsystemfile = 0; /* 1 => we are logging something we did not open */
|
||||
static int ocsystemfile = 0; /* 1 => we are logging to file we did not open */
|
||||
static char* oclogfile = NULL;
|
||||
static FILE* oclogstream = NULL;
|
||||
|
||||
static int octagsize = 0;
|
||||
static char** octagset = NULL;
|
||||
static char* octagdfalt = NULL;
|
||||
static char* octagsetdfalt[] = {"Warning","Error","Note","Debug"};
|
||||
static char* octagname(int tag);
|
||||
|
||||
/*!\defgroup OClog OClog Management
|
||||
@{*/
|
||||
|
||||
@ -24,19 +35,22 @@ static FILE* oclogstream = NULL;
|
||||
*/
|
||||
|
||||
void
|
||||
oc_loginit(void)
|
||||
ocloginit(void)
|
||||
{
|
||||
const char* file = getenv(ENVFLAG); /* I hope this is portable*/
|
||||
ocloginit = 1;
|
||||
oc_setlogging(0);
|
||||
const char* file = getenv(OCENVFLAG);
|
||||
oclogginginitialized = 1;
|
||||
ocsetlogging(0);
|
||||
oclogfile = NULL;
|
||||
oclogstream = NULL;
|
||||
/* Use environment variables to preset oclogging state*/
|
||||
/* I hope this is portable*/
|
||||
if(file != NULL && strlen(file) > 0) {
|
||||
if(oc_logopen(file)) {
|
||||
oc_setlogging(1);
|
||||
if(oclogopen(file)) {
|
||||
ocsetlogging(1);
|
||||
}
|
||||
}
|
||||
octagdfalt = OCTAGDFALT;
|
||||
octagset = octagsetdfalt;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -48,10 +62,10 @@ Enable/Disable logging.
|
||||
*/
|
||||
|
||||
int
|
||||
oc_setlogging(int tf)
|
||||
ocsetlogging(int tf)
|
||||
{
|
||||
int was;
|
||||
if(!ocloginit) oc_loginit();
|
||||
if(!oclogginginitialized) ocloginit();
|
||||
was = oclogging;
|
||||
oclogging = tf;
|
||||
return was;
|
||||
@ -68,10 +82,10 @@ stderr.
|
||||
*/
|
||||
|
||||
int
|
||||
oc_logopen(const char* file)
|
||||
oclogopen(const char* file)
|
||||
{
|
||||
if(!ocloginit) oc_loginit();
|
||||
oc_logclose();
|
||||
if(!oclogginginitialized) ocloginit();
|
||||
oclogclose();
|
||||
if(file == NULL || strlen(file) == 0) {
|
||||
/* use stderr*/
|
||||
oclogstream = stderr;
|
||||
@ -89,8 +103,7 @@ oc_logopen(const char* file)
|
||||
ocsystemfile = 1;
|
||||
} else {
|
||||
int fd;
|
||||
oclogfile = (char*)malloc(strlen(file)+1);
|
||||
strcpy(oclogfile,file);
|
||||
oclogfile = strdup(file);
|
||||
oclogstream = NULL;
|
||||
/* We need to deal with this file carefully
|
||||
to avoid unauthorized access*/
|
||||
@ -100,24 +113,20 @@ oc_logopen(const char* file)
|
||||
} else {
|
||||
free(oclogfile);
|
||||
oclogfile = NULL;
|
||||
oc_setlogging(0);
|
||||
oclogstream = NULL;
|
||||
ocsetlogging(0);
|
||||
return 0;
|
||||
}
|
||||
ocsystemfile = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Close the logging output file (unless it is stderr).
|
||||
Logging is still enabled.
|
||||
*/
|
||||
|
||||
void
|
||||
oc_logclose(void)
|
||||
oclogclose(void)
|
||||
{
|
||||
if(!ocloginit) oc_loginit();
|
||||
if(!oclogginginitialized) ocloginit();
|
||||
if(oclogstream != NULL && !ocsystemfile) {
|
||||
assert(oclogfile != NULL && oclogstream != NULL);
|
||||
fclose(oclogstream);
|
||||
}
|
||||
if(oclogfile != NULL) free(oclogfile);
|
||||
@ -136,63 +145,71 @@ printf function.
|
||||
*/
|
||||
|
||||
void
|
||||
oc_log(int tag, const char* format, ...)
|
||||
oclog(int tag, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char* prefix;
|
||||
|
||||
if(!ocloginit) oc_loginit();
|
||||
if(!oclogginginitialized) ocloginit();
|
||||
|
||||
if(!oclogging || oclogstream == NULL) return;
|
||||
|
||||
switch (tag) {
|
||||
case LOGWARN: prefix = "Warning:"; break;
|
||||
case LOGERR: prefix = "Error: "; break;
|
||||
case LOGNOTE: prefix = "Note: "; break;
|
||||
case LOGDBG: prefix = "Debug: "; break;
|
||||
default:
|
||||
fprintf(oclogstream,"Error: Bad log prefix: %d\n",tag);
|
||||
prefix = "Error: ";
|
||||
break;
|
||||
}
|
||||
prefix = octagname(tag);
|
||||
fprintf(oclogstream,"%s:",prefix);
|
||||
|
||||
if(format != NULL) {
|
||||
va_start(args, format);
|
||||
vfprintf(oclogstream, format, args);
|
||||
if(fmt != NULL) {
|
||||
va_start(args, fmt);
|
||||
vfprintf(oclogstream, fmt, args);
|
||||
va_end( args );
|
||||
}
|
||||
fprintf(oclogstream, "\n" );
|
||||
fflush(oclogstream);
|
||||
}
|
||||
|
||||
void
|
||||
oclogtext(int tag, const char* text)
|
||||
{
|
||||
oclogtextn(tag,text,strlen(text));
|
||||
}
|
||||
|
||||
/*!
|
||||
Send arbitrarily long text as a logging message.
|
||||
Each line will be sent using oc_log with the specified tag.
|
||||
|
||||
Each line will be sent using oclog with the specified tag.
|
||||
\param[in] tag Indicate the kind of this log message.
|
||||
\param[in] text Arbitrary text to send as a logging message.
|
||||
*/
|
||||
|
||||
void
|
||||
oc_logtext(int tag, const char* text)
|
||||
oclogtextn(int tag, const char* text, size_t count)
|
||||
{
|
||||
char line[1024];
|
||||
size_t delta = 0;
|
||||
const char* eol = text;
|
||||
|
||||
if(!ocloginit) oc_loginit();
|
||||
if(!oclogging || oclogstream == NULL) return;
|
||||
fwrite(text,1,count,oclogstream);
|
||||
fflush(oclogstream);
|
||||
}
|
||||
|
||||
while(*text) {
|
||||
eol = strchr(text,'\n');
|
||||
if(eol == NULL)
|
||||
delta = strlen(text);
|
||||
else
|
||||
delta = (eol - text);
|
||||
if(delta > 0) memcpy(line,text,delta);
|
||||
line[delta] = '\0';
|
||||
fprintf(oclogstream," %s\n",line);
|
||||
text = eol+1;
|
||||
/* The tagset is null terminated */
|
||||
void
|
||||
oclogsettags(char** tagset, char* dfalt)
|
||||
{
|
||||
octagdfalt = dfalt;
|
||||
if(tagset == NULL) {
|
||||
octagsize = 0;
|
||||
} else {
|
||||
int i;
|
||||
/* Find end of the tagset */
|
||||
for(i=0;i<MAXTAGS;i++) {if(tagset[i]==NULL) break;}
|
||||
octagsize = i;
|
||||
}
|
||||
octagset = tagset;
|
||||
}
|
||||
|
||||
static char*
|
||||
octagname(int tag)
|
||||
{
|
||||
if(tag < 0 || tag >= octagsize) {
|
||||
return octagdfalt;
|
||||
} else {
|
||||
return octagset[tag];
|
||||
}
|
||||
}
|
||||
|
||||
|
35
oc2/oclog.h
35
oc2/oclog.h
@ -1,20 +1,31 @@
|
||||
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||||
See the COPYRIGHT file for more information. */
|
||||
/*********************************************************************
|
||||
* Copyright 2010, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef OCLOG_H
|
||||
#define OCLOG_H
|
||||
|
||||
#define LOGNOTE 0
|
||||
#define LOGWARN 1
|
||||
#define LOGERR 2
|
||||
#define LOGDBG 3
|
||||
#define OCENVFLAG "OCLOGFILE"
|
||||
|
||||
extern void oc_loginit(void);
|
||||
extern int oc_setlogging(int tf);
|
||||
extern int oc_logopen(const char* file);
|
||||
extern void oc_logclose(void);
|
||||
/* Suggested tag values */
|
||||
#define OCLOGNOTE 0
|
||||
#define OCLOGWARN 1
|
||||
#define OCLOGERR 2
|
||||
#define OCLOGDBG 3
|
||||
|
||||
extern void oc_log(int tag, const char* fmt, ...);
|
||||
extern void oc_logtext(int tag, const char* text);
|
||||
extern void ocloginit(void);
|
||||
extern int ocsetlogging(int tf);
|
||||
extern int oclogopen(const char* file);
|
||||
extern void oclogclose(void);
|
||||
|
||||
/* The tag value is an arbitrary integer */
|
||||
extern void oclog(int tag, const char* fmt, ...);
|
||||
extern void oclogtext(int tag, const char* text);
|
||||
extern void oclogtextn(int tag, const char* text, size_t count);
|
||||
|
||||
/* Provide printable names for tags */
|
||||
extern void oclogsettags(char** tagset, char* dfalt);
|
||||
|
||||
#endif /*OCLOG_H*/
|
||||
|
@ -143,7 +143,7 @@ makeattribute(char* name, OCtype ptype, OClist* values)
|
||||
static void
|
||||
marklostattribute(OCnode* att)
|
||||
{
|
||||
oc_log(LOGNOTE,"Lost attribute: %s",att->name);
|
||||
oclog(OCLOGNOTE,"Lost attribute: %s",att->name);
|
||||
}
|
||||
|
||||
void
|
||||
@ -288,7 +288,7 @@ ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
|
||||
OCnode* das2 = (OCnode*)oclistget(dasnodes,j);
|
||||
if(das->name == NULL || das2->name == NULL) continue;
|
||||
if(strcmp(das->name,das2->name)==0) {
|
||||
oc_log(LOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
|
||||
oclog(OCLOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
|
||||
}
|
||||
}
|
||||
oclistpush(dasnodes,(ocelem)das);
|
||||
|
48
oc2/ocrc.c
48
oc2/ocrc.c
@ -208,12 +208,12 @@ parseproxy(OCstate* state, char* v)
|
||||
state->proxy.password[p_len] = '\0';
|
||||
#endif /*0*/
|
||||
if (ocdebug > 1) {
|
||||
oc_log(LOGNOTE,"host name: %s", state->proxy.host);
|
||||
oc_log(LOGNOTE,"user name: %s", state->creds.username);
|
||||
oclog(OCLOGNOTE,"host name: %s", state->proxy.host);
|
||||
oclog(OCLOGNOTE,"user name: %s", state->creds.username);
|
||||
#ifdef INSECURE
|
||||
oc_log(LOGNOTE,"password: %s", state->creds.password);
|
||||
oclog(OCLOGNOTE,"password: %s", state->creds.password);
|
||||
#endif
|
||||
oc_log(LOGNOTE,"port number: %d", state->proxy.port);
|
||||
oclog(OCLOGNOTE,"port number: %d", state->proxy.port);
|
||||
}
|
||||
if(v) free(v);
|
||||
return OC_NOERR;
|
||||
@ -234,7 +234,7 @@ sorttriplestore(void)
|
||||
|
||||
sorted = (struct OCTriple*)malloc(sizeof(struct OCTriple)*ocdodsrc->ntriples);
|
||||
if(sorted == NULL) {
|
||||
oc_log(LOGERR,"sorttriplestore: out of memory");
|
||||
oclog(OCLOGERR,"sorttriplestore: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
if(ocdodsrc == NULL) {
|
||||
ocdodsrc = (struct OCTriplestore*)malloc(sizeof(struct OCTriplestore));
|
||||
if(ocdodsrc == NULL) {
|
||||
oc_log(LOGERR,"ocdodsrc_read: out of memory");
|
||||
oclog(OCLOGERR,"ocdodsrc_read: out of memory");
|
||||
return 0;
|
||||
}
|
||||
ocglobalstate.ocdodsrc = ocdodsrc;
|
||||
@ -294,7 +294,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
|
||||
in_file = fopen(path, "r"); /* Open the file to read it */
|
||||
if (in_file == NULL) {
|
||||
oc_log(LOGERR, "Could not open configuration file: %s",basename);
|
||||
oclog(OCLOGERR, "Could not open configuration file: %s",basename);
|
||||
return OC_EPERM;
|
||||
}
|
||||
|
||||
@ -303,7 +303,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
if(!rcreadline(in_file,line0,sizeof(line0))) break;
|
||||
linecount++;
|
||||
if(linecount >= MAXRCLINES) {
|
||||
oc_log(LOGERR, ".dodsrc has too many lines");
|
||||
oclog(OCLOGERR, ".dodsrc has too many lines");
|
||||
return 0;
|
||||
}
|
||||
line = line0;
|
||||
@ -312,7 +312,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
/* trim leading blanks */
|
||||
line = rctrimleft(line,TRIMCHARS);
|
||||
if(strlen(line) >= MAXRCLINESIZE) {
|
||||
oc_log(LOGERR, "%s line too long: %s",basename,line0);
|
||||
oclog(OCLOGERR, "%s line too long: %s",basename,line0);
|
||||
return 0;
|
||||
}
|
||||
/* parse the line */
|
||||
@ -321,7 +321,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
char* url = ++line;
|
||||
char* rtag = strchr(line,RTAG);
|
||||
if(rtag == NULL) {
|
||||
oc_log(LOGERR, "Malformed [url] in %s entry: %s",basename,line);
|
||||
oclog(OCLOGERR, "Malformed [url] in %s entry: %s",basename,line);
|
||||
continue;
|
||||
}
|
||||
line = rtag + 1;
|
||||
@ -338,7 +338,7 @@ ocdodsrc_read(char* basename, char* path)
|
||||
if(value == NULL) {
|
||||
/* add fake '=1' */
|
||||
if(strlen(line) + strlen("=1") >= MAXRCLINESIZE) {
|
||||
oc_log(LOGERR, "%s entry too long: %s",basename,line);
|
||||
oclog(OCLOGERR, "%s entry too long: %s",basename,line);
|
||||
continue;
|
||||
}
|
||||
strcat(line,"=1");
|
||||
@ -369,31 +369,31 @@ ocdodsrc_process(OCstate* state)
|
||||
if(value != NULL) {
|
||||
if(atoi(value)) state->curlflags.compress = 1;
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"Compression: %ld", state->curlflags.compress);
|
||||
oclog(OCLOGNOTE,"Compression: %ld", state->curlflags.compress);
|
||||
}
|
||||
if((value = curllookup("VERBOSE",url)) != NULL) {
|
||||
if(atoi(value)) state->curlflags.verbose = 1;
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"curl.verbose: %ld", state->curlflags.verbose);
|
||||
oclog(OCLOGNOTE,"curl.verbose: %ld", state->curlflags.verbose);
|
||||
}
|
||||
if((value = curllookup("TIMEOUT",url)) != NULL) {
|
||||
if(atoi(value)) state->curlflags.timeout = atoi(value);
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"curl.timeout: %ld", state->curlflags.timeout);
|
||||
oclog(OCLOGNOTE,"curl.timeout: %ld", state->curlflags.timeout);
|
||||
}
|
||||
|
||||
if((value = curllookup("COOKIEFILE",url)) != NULL) {
|
||||
state->curlflags.cookiefile = strdup(TRIM(value));
|
||||
if(!state->curlflags.cookiefile) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"COOKIEFILE: %s", state->curlflags.cookiefile);
|
||||
oclog(OCLOGNOTE,"COOKIEFILE: %s", state->curlflags.cookiefile);
|
||||
}
|
||||
if((value = curllookup("COOKIEJAR",url))
|
||||
|| (value = curllookup("COOKIE_JAR",url))) {
|
||||
state->curlflags.cookiejar = strdup(TRIM(value));
|
||||
if(!state->curlflags.cookiejar) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"COOKIEJAR: %s", state->curlflags.cookiejar);
|
||||
oclog(OCLOGNOTE,"COOKIEJAR: %s", state->curlflags.cookiejar);
|
||||
}
|
||||
|
||||
/* Some servers (e.g. thredds) appear to require a place
|
||||
@ -412,21 +412,21 @@ ocdodsrc_process(OCstate* state)
|
||||
if((value = curllookup("SSL.VALIDATE",url)) != NULL) {
|
||||
if(atoi(value)) state->ssl.validate = 1;
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"CURL.SSL.VALIDATE: %ld", state->ssl.validate);
|
||||
oclog(OCLOGNOTE,"CURL.SSL.VALIDATE: %ld", state->ssl.validate);
|
||||
}
|
||||
|
||||
if((value = curllookup("SSL.CERTIFICATE",url)) != NULL) {
|
||||
state->ssl.certificate = strdup(TRIM(value));
|
||||
if(!state->ssl.certificate) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"CREDENTIALS.SSL.CERTIFICATE: %s", state->ssl.certificate);
|
||||
oclog(OCLOGNOTE,"CREDENTIALS.SSL.CERTIFICATE: %s", state->ssl.certificate);
|
||||
}
|
||||
|
||||
if((value = curllookup("SSL.KEY",url)) != NULL) {
|
||||
state->ssl.key = strdup(TRIM(value));
|
||||
if(!state->ssl.key) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEY: %s", state->ssl.key);
|
||||
oclog(OCLOGNOTE,"CREDENTIALS.SSL.KEY: %s", state->ssl.key);
|
||||
}
|
||||
|
||||
if((value = curllookup("SSL.KEYPASSWORD",url)) != NULL) {
|
||||
@ -434,7 +434,7 @@ ocdodsrc_process(OCstate* state)
|
||||
if(!state->ssl.keypasswd) {stat = OC_ENOMEM; goto done;}
|
||||
#ifdef INSECURE
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
|
||||
oclog(OCLOGNOTE,"CREDENTIALS.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -442,14 +442,14 @@ ocdodsrc_process(OCstate* state)
|
||||
state->ssl.cainfo = strdup(TRIM(value));
|
||||
if(!state->ssl.cainfo) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"SSL.CAINFO: %s", state->ssl.cainfo);
|
||||
oclog(OCLOGNOTE,"SSL.CAINFO: %s", state->ssl.cainfo);
|
||||
}
|
||||
|
||||
if((value = curllookup("SSL.CAPATH",url)) != NULL) {
|
||||
state->ssl.capath = strdup(TRIM(value));
|
||||
if(!state->ssl.capath) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"SSL.CAPATH: %s", state->ssl.capath);
|
||||
oclog(OCLOGNOTE,"SSL.CAPATH: %s", state->ssl.capath);
|
||||
}
|
||||
|
||||
if((value = curllookup("SSL.VERIFYPEER",url)) != NULL) {
|
||||
@ -463,14 +463,14 @@ ocdodsrc_process(OCstate* state)
|
||||
tf = 1; /* default if not null */
|
||||
state->ssl.verifypeer = tf;
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"SSL.VERIFYPEER: %d", state->ssl.verifypeer);
|
||||
oclog(OCLOGNOTE,"SSL.VERIFYPEER: %d", state->ssl.verifypeer);
|
||||
}
|
||||
|
||||
if((value = curllookup("CREDENTIALS.USER",url)) != NULL) {
|
||||
state->creds.username = strdup(TRIM(value));
|
||||
if(!state->creds.username) {stat = OC_ENOMEM; goto done;}
|
||||
if(ocdebug > 0)
|
||||
oc_log(LOGNOTE,"CREDENTIALS.USER: %s", state->creds.username);
|
||||
oclog(OCLOGNOTE,"CREDENTIALS.USER: %s", state->creds.username);
|
||||
}
|
||||
|
||||
if((value = curllookup("CREDENTIALS.PASSWORD",url)) != NULL) {
|
||||
|
@ -186,7 +186,7 @@ readfile(const char* path, const char* suffix, OCbytes* packet)
|
||||
if(suffix != NULL) strcat(filename,suffix);
|
||||
fd = open(filename,O_RDONLY);
|
||||
if(fd < 0) {
|
||||
oc_log(LOGERR,"open failed:%s",filename);
|
||||
oclog(OCLOGERR,"open failed:%s",filename);
|
||||
return OCTHROW(OC_EOPEN);
|
||||
}
|
||||
size=0;
|
||||
@ -197,7 +197,7 @@ readfile(const char* path, const char* suffix, OCbytes* packet)
|
||||
break;
|
||||
else if(count < 0) {
|
||||
stat = OC_EIO;
|
||||
oc_log(LOGERR,"read failed: %s",filename);
|
||||
oclog(OCLOGERR,"read failed: %s",filename);
|
||||
break;
|
||||
}
|
||||
ocbytesappendn(packet,buf,count);
|
||||
|
669
oc2/ocuri.c
669
oc2/ocuri.c
@ -4,87 +4,53 @@
|
||||
* $Header$
|
||||
*********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "oc.h"
|
||||
#include "ocuri.h"
|
||||
|
||||
#define OCURIDEBUG
|
||||
|
||||
#ifdef OCURIDEBUG
|
||||
static int failpoint = 0;
|
||||
#define THROW(n) {failpoint=(n); goto fail;}
|
||||
#else
|
||||
#define THROW(n)
|
||||
#endif
|
||||
|
||||
|
||||
#define PADDING 8
|
||||
|
||||
#define LBRACKET '['
|
||||
#define RBRACKET ']'
|
||||
#define EOFCHAR '\0'
|
||||
|
||||
#ifndef FIX
|
||||
#define FIX(s) ((s)==NULL?"":(s))
|
||||
#define FIX(s) ((s)==NULL?"NULL":(s))
|
||||
#endif
|
||||
|
||||
#ifndef NILLEN
|
||||
#define NILLEN(s) ((s)==NULL?0:strlen(s))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRDUP
|
||||
# ifndef nulldup
|
||||
# define nulldup(s) ((s)==NULL?NULL:strdup(s))
|
||||
# endif
|
||||
#ifndef nulldup
|
||||
#define nulldup(s) ((s)==NULL?NULL:strdup(s))
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
static char* nulldup(char* s)
|
||||
{
|
||||
char* dup = NULL;
|
||||
if(s != NULL) {
|
||||
dup = (char*)malloc(strlen(s)+1);
|
||||
if(dup != NULL)
|
||||
strcpy(dup,s);
|
||||
}
|
||||
return dup;
|
||||
}
|
||||
#endif
|
||||
#define terminate(p) {*(p) = EOFCHAR;}
|
||||
|
||||
#ifdef OCIGNORE
|
||||
/* Not all systems have strndup, so provide one*/
|
||||
static char*
|
||||
ocstrndup(const char* s, size_t len)
|
||||
{
|
||||
char* dup;
|
||||
if(s == NULL) return NULL;
|
||||
dup = (char*)ocmalloc(len+1);
|
||||
MEMCHECK(dup,NULL);
|
||||
memcpy((void*)dup,s,len);
|
||||
dup[len] = '\0';
|
||||
return dup;
|
||||
}
|
||||
#endif
|
||||
#define endof(p) ((p)+strlen(p))
|
||||
|
||||
#if 0
|
||||
/* Do not trust strncmp */
|
||||
static int
|
||||
ocuristrncmp(const char* s1, const char* s2, size_t len)
|
||||
{
|
||||
const char *p,*q;
|
||||
if(s1 == s2) return 0;
|
||||
if(s1 == NULL) return -1;
|
||||
if(s2 == NULL) return +1;
|
||||
for(p=s1,q=s2;len > 0;p++,q++,len--) {
|
||||
if(*p != *q)
|
||||
return (*p - *q);
|
||||
if(*p == 0) return 0; /* *p == *q == 0 */
|
||||
}
|
||||
/* 1st len chars are same */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char* legalprotocols[] = {
|
||||
"file",
|
||||
"http",
|
||||
"https",
|
||||
"ftp",
|
||||
NULL /* NULL terminate*/
|
||||
static struct OC_ProtocolInfo {
|
||||
char* name;
|
||||
int filelike; /* 1=>this protocol has no host, user+pwd, or port */
|
||||
} legalprotocols[] = {
|
||||
{"file",1},
|
||||
{"http",0},
|
||||
{"https",0},
|
||||
{"ftp",0},
|
||||
};
|
||||
|
||||
/* Allowable character sets for encode */
|
||||
@ -94,8 +60,13 @@ static char* fileallow =
|
||||
static char* queryallow =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
|
||||
|
||||
/* Forward */
|
||||
static void ocparamfree(char** params);
|
||||
static int ocfind(char** params, const char* key);
|
||||
static void oclshift1(char* p);
|
||||
static void ocrshift1(char* p);
|
||||
static char* oclocate(char* p, const char* charlist);
|
||||
static void ocappendparams(char* newuri, char** p);
|
||||
|
||||
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
|
||||
int
|
||||
@ -103,10 +74,9 @@ ocuriparse(const char* uri0, OCURI** ocurip)
|
||||
{
|
||||
OCURI* ocuri = NULL;
|
||||
char* uri = NULL;
|
||||
char** pp;
|
||||
char* p;
|
||||
char* p1;
|
||||
int c;
|
||||
struct OC_ProtocolInfo* proto;
|
||||
int i,nprotos;
|
||||
|
||||
/* accumulate parse points*/
|
||||
char* protocol = NULL;
|
||||
@ -119,139 +89,250 @@ ocuriparse(const char* uri0, OCURI** ocurip)
|
||||
char* prefixparams = NULL;
|
||||
char* suffixparams = NULL;
|
||||
|
||||
|
||||
if(uri0 == NULL || strlen(uri0) == 0)
|
||||
goto fail;
|
||||
{THROW(1); goto fail;}
|
||||
|
||||
ocuri = (OCURI*)calloc(1,sizeof(OCURI));
|
||||
if(ocuri == NULL)
|
||||
goto fail;
|
||||
{THROW(2); goto fail;}
|
||||
|
||||
/* save original uri */
|
||||
ocuri->uri = nulldup(uri0);
|
||||
|
||||
/* make local copy of uri */
|
||||
uri = (char*)malloc(strlen(uri0)+2); /* +1 for trailing null, +1 if we
|
||||
need to append a char */
|
||||
uri = (char*)malloc(strlen(uri0)+1+PADDING); /* +1 for trailing null,
|
||||
+PADDING for shifting */
|
||||
if(uri == NULL)
|
||||
{THROW(3); goto fail;}
|
||||
|
||||
/* strings will be broken into pieces with intermixed '\0; characters;
|
||||
first char is guaranteed to be '\0' */
|
||||
|
||||
ocuri->strings = uri;
|
||||
uri++;
|
||||
|
||||
/* dup the incoming url */
|
||||
strcpy(uri,uri0);
|
||||
|
||||
/* remove all whitespace*/
|
||||
p = uri;
|
||||
p1 = uri;
|
||||
while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
|
||||
/* Walk the uri and do the following:
|
||||
1. remove all whitespace
|
||||
2. remove all '\\' (Temp hack to remove escape characters
|
||||
inserted by Windows or MinGW)
|
||||
*/
|
||||
for(p=uri;*p;p++) {
|
||||
if(*p == '\\' || *p < ' ')
|
||||
oclshift1(p); /* compress out */
|
||||
}
|
||||
|
||||
p = uri;
|
||||
|
||||
/* break up the uri string into pieces*/
|
||||
/* break up the uri string into big chunks: prefixparams, protocol,
|
||||
host section, and the file section (i.e. remainder)
|
||||
*/
|
||||
|
||||
/* leading bracketed parameters */
|
||||
/* collect any prefix bracketed parameters */
|
||||
if(*p == LBRACKET) {
|
||||
prefixparams = p+1;
|
||||
/* find end of the clientparams*/
|
||||
for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
|
||||
if(*p == 0) goto fail; /* malformed client params*/
|
||||
*p = '\0'; /* wipe out the last rbracket */
|
||||
p++; /* move past the params*/
|
||||
/* find end of the clientparams; convert LB,RB to ';' */
|
||||
for(;*p;p++) {
|
||||
if(p[0] == RBRACKET && p[1] == LBRACKET) {
|
||||
p[0] = ';';
|
||||
oclshift1(p+1);
|
||||
} else if(p[0] == RBRACKET && p[1] != LBRACKET)
|
||||
break;
|
||||
}
|
||||
if(*p == 0)
|
||||
{THROW(4); goto fail; /* malformed client params*/}
|
||||
terminate(p); /* nul term the prefixparams (overwrites
|
||||
the final RBRACKET) */
|
||||
p++; /* move past the final RBRACKET */
|
||||
}
|
||||
|
||||
/* Tag the protocol */
|
||||
protocol = p;
|
||||
p1 = strchr(p,':');
|
||||
if(!p1)
|
||||
goto fail;
|
||||
*p1 = '\0';
|
||||
p = p1+1;
|
||||
p = strchr(p,':');
|
||||
if(!p)
|
||||
{THROW(5); goto fail;}
|
||||
terminate(p); /*overwrite colon*/
|
||||
p++; /* skip the colon */
|
||||
|
||||
/* verify that the uri starts with an acceptable protocol*/
|
||||
for(pp=legalprotocols;*pp;pp++) {
|
||||
if(strcmp(protocol,*pp)==0) break;
|
||||
nprotos = (sizeof(legalprotocols)/sizeof(struct OC_ProtocolInfo));
|
||||
proto = NULL;
|
||||
for(i=0;i<nprotos;i++) {
|
||||
if(strcmp(protocol,legalprotocols[i].name)==0) {
|
||||
proto = &legalprotocols[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*pp == NULL) goto fail; /* illegal protocol*/
|
||||
if(proto == NULL)
|
||||
{THROW(6); goto fail; /* illegal protocol*/}
|
||||
|
||||
/* skip // */
|
||||
if(*p != '/' && *(p+1) != '/')
|
||||
goto fail;
|
||||
if(p[0] != '/' && p[1] != '/')
|
||||
{THROW(7); goto fail;}
|
||||
p += 2;
|
||||
|
||||
/* locate the end of the host section */
|
||||
file = strchr(p,'/');
|
||||
/* Temporarily overwrite the '/' */
|
||||
if(file != NULL)
|
||||
*file = '\0';
|
||||
/* If this is all we have (proto://) then fail */
|
||||
if(*p == EOFCHAR)
|
||||
{THROW(8); goto fail;}
|
||||
|
||||
/* establish the start of the file section */
|
||||
if(proto->filelike) {/* everything after proto:// */
|
||||
file = p;
|
||||
host = NULL; /* and no host section */
|
||||
} else { /*!proto->filelike => This means there should be a host section */
|
||||
/* locate the end of the host section and therefore the start
|
||||
of the file section */
|
||||
host = p;
|
||||
p = oclocate(p,"/?#");
|
||||
if(p == NULL) {
|
||||
file = endof(host); /* there is no file section */
|
||||
} else {
|
||||
ocrshift1(p); /* make room to terminate the host section
|
||||
without overwriting the leading character */
|
||||
terminate(p); /* terminate the host section */
|
||||
file = p+1; /* +1 becauseof the shift */
|
||||
}
|
||||
}
|
||||
|
||||
/* If you shift in the code below, you must reset file beginning */
|
||||
|
||||
if(host != NULL) {/* Parse the host section */
|
||||
/* Check for leading user:pwd@ */
|
||||
p = strchr(host,'@');
|
||||
if(p) {
|
||||
if(p == host)
|
||||
{THROW(9); goto fail; /* we have proto://@ */}
|
||||
user = host;
|
||||
terminate(p); /* overwrite '@' */
|
||||
host = p+1; /* start of host ip name */
|
||||
p = strchr(user,':');
|
||||
if(p == NULL)
|
||||
{THROW(10); goto fail; /* malformed */}
|
||||
terminate(p); /*overwrite colon */
|
||||
pwd = p+1;
|
||||
}
|
||||
|
||||
/* extract host and port */
|
||||
p = host;
|
||||
p = strchr(p,':');
|
||||
if(p != NULL) {
|
||||
terminate(p);
|
||||
p++;
|
||||
port = p;
|
||||
if(*port == EOFCHAR)
|
||||
{THROW(11); goto fail; /* we have proto://...:/ */}
|
||||
/* The port must look something like a number */
|
||||
for(;*p;p++) {
|
||||
if(strchr("0123456789-",*p) == NULL)
|
||||
{THROW(12); goto fail; /* probably not a real port, fail */}
|
||||
}
|
||||
} /* else *p == NULL */
|
||||
|
||||
|
||||
/* check for empty host section */
|
||||
if(*host == EOFCHAR)
|
||||
{THROW(13); goto fail;}
|
||||
|
||||
/* extract any user:pwd */
|
||||
host = p;
|
||||
p1 = strchr(p,'@');
|
||||
if(p1) {/* Assume we have user:pwd@ */
|
||||
*p1 = '\0';
|
||||
user = p;
|
||||
pwd = strchr(p,':');
|
||||
if(!pwd) goto fail; /* malformed */
|
||||
*pwd++ = '\0';
|
||||
}
|
||||
|
||||
/* extract host and port */
|
||||
p = host;
|
||||
port = strchr(p,':');
|
||||
if(port!=NULL)
|
||||
*port++ = '\0';
|
||||
assert(file != NULL);
|
||||
p = file;
|
||||
|
||||
/* Locate end of the file */
|
||||
constraint = strchr(file,'?');
|
||||
if(constraint!=NULL)
|
||||
suffixparams = strchr(constraint,'#');
|
||||
else
|
||||
suffixparams = strchr(file,'#');
|
||||
|
||||
if(constraint != NULL) {
|
||||
*constraint++ = '\0';
|
||||
p = constraint;
|
||||
/* find the end of the file section and the start of the
|
||||
constraints and/or suffixparams
|
||||
*/
|
||||
p = oclocate(p,"?#");
|
||||
if(p != NULL) { /* we have constraint and/or suffixparams */
|
||||
char* fileend = p; /* save the end of the file section */
|
||||
char* constraintend = NULL;
|
||||
if(*p == '?')
|
||||
constraint = p+1;
|
||||
else
|
||||
constraint = NULL;
|
||||
p = strchr(p,'#'); /* may repeat effect of oclocate above */
|
||||
if(p != NULL) {
|
||||
constraintend = p;
|
||||
suffixparams = p+1;
|
||||
} else
|
||||
suffixparams = NULL;
|
||||
/* Ok, terminate the pieces */
|
||||
terminate(fileend); /* terminate file section */
|
||||
if(constraint != NULL && constraintend != NULL)
|
||||
terminate(constraintend);
|
||||
/* Suffix params are already terminated
|
||||
since they should be the last section
|
||||
of the original url
|
||||
*/
|
||||
}
|
||||
|
||||
/* check for empty sections */
|
||||
if(file != NULL && *file == EOFCHAR)
|
||||
file = NULL; /* empty file section */
|
||||
if(constraint != NULL && *constraint == EOFCHAR)
|
||||
constraint = NULL; /* empty constraint section */
|
||||
if(suffixparams != NULL && *suffixparams == EOFCHAR)
|
||||
suffixparams = NULL; /* empty suffixparams section */
|
||||
|
||||
if(suffixparams != NULL) {
|
||||
*suffixparams++ = '\0';
|
||||
/* there really are suffix params; so rebuild the suffix params */
|
||||
p = suffixparams;
|
||||
/* There must be brackets */
|
||||
if(*p != LBRACKET)
|
||||
{THROW(14); goto fail;}
|
||||
suffixparams++; /* skip leading LBRACKET */
|
||||
p = suffixparams;
|
||||
/* convert RBRACKET LBRACKET to ';' */
|
||||
for(;*p;p++) {
|
||||
if(p[0] == RBRACKET && p[1] == LBRACKET) {
|
||||
p[0] = ';';
|
||||
oclshift1(p+1);
|
||||
} else if(p[0] == RBRACKET && p[1] != LBRACKET) {
|
||||
/* terminate suffixparams */
|
||||
*p = EOFCHAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*suffixparams == EOFCHAR)
|
||||
suffixparams = NULL; /* suffixparams are empty */
|
||||
}
|
||||
|
||||
/* assemble the component pieces*/
|
||||
if(uri0 && strlen(uri0) > 0)
|
||||
ocuri->uri = nulldup(uri0);
|
||||
if(protocol && strlen(protocol) > 0) {
|
||||
ocuri->protocol = nulldup(protocol);
|
||||
}
|
||||
if(user && strlen(user) > 0)
|
||||
ocuri->user = nulldup(user);
|
||||
if(pwd && strlen(pwd) > 0)
|
||||
ocuri->password = nulldup(pwd);
|
||||
if(host && strlen(host) > 0)
|
||||
ocuri->host = nulldup(host);
|
||||
if(port && strlen(port) > 0)
|
||||
ocuri->port = nulldup(port);
|
||||
if(file) {
|
||||
/* Add back the leading / */
|
||||
if(file) *file = '/';
|
||||
if(strlen(file) > 0)
|
||||
ocuri->file = nulldup(file);
|
||||
else
|
||||
file = NULL;
|
||||
}
|
||||
if(constraint && strlen(constraint) == 0)
|
||||
constraint = NULL;
|
||||
if(constraint && strlen(constraint) > 0)
|
||||
ocuri->constraint = nulldup(constraint);
|
||||
/* do last minute empty check */
|
||||
if(protocol != NULL && *protocol == EOFCHAR) protocol = NULL;
|
||||
if(user != NULL && *user == EOFCHAR) user = NULL;
|
||||
if(pwd != NULL && *pwd == EOFCHAR) pwd = NULL;
|
||||
if(host != NULL && *host == EOFCHAR) host = NULL;
|
||||
if(port != NULL && *port == EOFCHAR) port = NULL;
|
||||
if(file != NULL && *file == EOFCHAR) file = NULL;
|
||||
if(constraint != NULL && *constraint == EOFCHAR) constraint = NULL;
|
||||
|
||||
/* assemble the component pieces */
|
||||
ocuri->protocol = protocol;
|
||||
ocuri->user = user;
|
||||
ocuri->password = pwd;
|
||||
ocuri->host = host;
|
||||
ocuri->port = port;
|
||||
ocuri->file = file;
|
||||
|
||||
ocurisetconstraints(ocuri,constraint);
|
||||
|
||||
/* concat suffix and prefix params */
|
||||
if(prefixparams != NULL || suffixparams != NULL) {
|
||||
int space = prefixparams ? strlen(prefixparams) : 0;
|
||||
space += suffixparams ? strlen(suffixparams) : 0;
|
||||
space += (2 + 1);
|
||||
int plen = prefixparams ? strlen(prefixparams) : 0;
|
||||
int slen = suffixparams ? strlen(suffixparams) : 0;
|
||||
int space = plen + slen + 1;
|
||||
/* add 1 for an extra comma if both are defined */
|
||||
space++;
|
||||
ocuri->params = (char*)malloc(space);
|
||||
if(prefixparams && strlen(prefixparams) > 0) {
|
||||
strcpy(ocuri->params,"[");
|
||||
ocuri->params[0] = EOFCHAR; /* so we can use strcat */
|
||||
if(plen > 0) {
|
||||
strcat(ocuri->params,prefixparams);
|
||||
strcat(ocuri->params,"]");
|
||||
if(slen > 0)
|
||||
strcat(ocuri->params,";");
|
||||
}
|
||||
if(suffixparams && strlen(suffixparams) > 0) {
|
||||
strcat(ocuri->params,"[");
|
||||
if(slen > 0)
|
||||
strcat(ocuri->params,suffixparams);
|
||||
strcat(ocuri->params,"]");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OCXDEBUG
|
||||
@ -266,13 +347,13 @@ ocuriparse(const char* uri0, OCURI** ocurip)
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
#endif
|
||||
free(uri);
|
||||
if(ocurip != NULL) *ocurip = ocuri;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
if(ocuri) ocurifree(ocuri);
|
||||
if(uri != NULL) free(uri);
|
||||
if(ocuri != NULL) {
|
||||
ocurifree(ocuri);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -281,17 +362,12 @@ ocurifree(OCURI* ocuri)
|
||||
{
|
||||
if(ocuri == NULL) return;
|
||||
if(ocuri->uri != NULL) {free(ocuri->uri);}
|
||||
if(ocuri->protocol != NULL) {free(ocuri->protocol);}
|
||||
if(ocuri->user != NULL) {free(ocuri->user);}
|
||||
if(ocuri->password != NULL) {free(ocuri->password);}
|
||||
if(ocuri->host != NULL) {free(ocuri->host);}
|
||||
if(ocuri->port != NULL) {free(ocuri->port);}
|
||||
if(ocuri->file != NULL) {free(ocuri->file);}
|
||||
if(ocuri->params != NULL) {free(ocuri->params);}
|
||||
if(ocuri->paramlist != NULL) ocparamfree(ocuri->paramlist);
|
||||
if(ocuri->strings != NULL) {free(ocuri->strings);}
|
||||
if(ocuri->constraint != NULL) {free(ocuri->constraint);}
|
||||
if(ocuri->projection != NULL) {free(ocuri->projection);}
|
||||
if(ocuri->selection != NULL) {free(ocuri->selection);}
|
||||
if(ocuri->params != NULL) {free(ocuri->params);}
|
||||
if(ocuri->paramlist != NULL) ocparamfree(ocuri->paramlist);
|
||||
free(ocuri);
|
||||
}
|
||||
|
||||
@ -314,7 +390,7 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
|
||||
|
||||
duri->constraint = nulldup(constraints);
|
||||
if(*duri->constraint == '?')
|
||||
strcpy(duri->constraint,duri->constraint+1);
|
||||
oclshift1(duri->constraint);
|
||||
|
||||
p = duri->constraint;
|
||||
proj = (char*) p;
|
||||
@ -326,7 +402,7 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
|
||||
} else {
|
||||
proj = (char*)malloc(plen+1);
|
||||
memcpy((void*)proj,p,plen);
|
||||
proj[plen] = '\0';
|
||||
proj[plen] = EOFCHAR;
|
||||
}
|
||||
select = nulldup(select);
|
||||
} else {
|
||||
@ -338,9 +414,10 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
|
||||
}
|
||||
|
||||
|
||||
/* Construct a complete OC URI without the client params
|
||||
and optionally with the constraints;
|
||||
caller frees returned string.
|
||||
/* Construct a complete OC URI.
|
||||
Optionally with the constraints.
|
||||
Optionally with the user parameters.
|
||||
Caller frees returned string.
|
||||
Optionally encode the pieces.
|
||||
*/
|
||||
|
||||
@ -352,12 +429,17 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
|
||||
char* tmpfile;
|
||||
char* tmpsuffix;
|
||||
char* tmpquery;
|
||||
int nparams = 0;
|
||||
int paramslen = 0;
|
||||
|
||||
int withparams = ((flags&OCURIPARAMS)
|
||||
&& duri->params != NULL);
|
||||
int withuserpwd = ((flags&OCURIUSERPWD)
|
||||
/* if both are specified, prefix has priority */
|
||||
int withsuffixparams = ((flags&OCURISUFFIXPARAMS)!=0
|
||||
&& duri->params != NULL);
|
||||
int withprefixparams = ((flags&OCURIPREFIXPARAMS)!=0
|
||||
&& duri->params != NULL);
|
||||
int withuserpwd = ((flags&OCURIUSERPWD)!=0
|
||||
&& duri->user != NULL && duri->password != NULL);
|
||||
int withconstraints = ((flags&OCURICONSTRAINTS)
|
||||
int withconstraints = ((flags&OCURICONSTRAINTS)!=0
|
||||
&& duri->constraint != NULL);
|
||||
#ifdef NEWESCAPE
|
||||
int encode = (flags&OCURIENCODE);
|
||||
@ -366,10 +448,6 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
|
||||
#endif
|
||||
|
||||
if(prefix != NULL) len += NILLEN(prefix);
|
||||
if(withparams) {
|
||||
len += NILLEN("[]");
|
||||
len += NILLEN(duri->params);
|
||||
}
|
||||
len += (NILLEN(duri->protocol)+NILLEN("://"));
|
||||
if(withuserpwd) {
|
||||
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
|
||||
@ -398,17 +476,33 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
|
||||
len += (NILLEN("?")+NILLEN(tmpquery));
|
||||
}
|
||||
|
||||
if(withprefixparams || withsuffixparams) {
|
||||
char** p;
|
||||
if(duri->paramlist == NULL)
|
||||
if(!ocuridecodeparams(duri))
|
||||
return NULL;
|
||||
for(paramslen=0,nparams=0,p=duri->paramlist;*p;p++) {
|
||||
nparams++;
|
||||
paramslen += NILLEN(*p);
|
||||
}
|
||||
if(nparams % 2 == 1)
|
||||
return NULL; /* malformed */
|
||||
nparams = (nparams / 2);
|
||||
len += paramslen;
|
||||
len += 3*nparams; /* for brackets for every param plus possible = */
|
||||
if(withsuffixparams)
|
||||
len += strlen("#");
|
||||
}
|
||||
|
||||
len += 1; /* null terminator */
|
||||
|
||||
newuri = (char*)malloc(len);
|
||||
if(newuri == NULL) return NULL;
|
||||
|
||||
newuri[0] = '\0';
|
||||
newuri[0] = EOFCHAR;
|
||||
if(prefix != NULL) strcat(newuri,prefix);
|
||||
if(withparams) {
|
||||
strcat(newuri,"[");
|
||||
strcat(newuri,duri->params);
|
||||
strcat(newuri,"]");
|
||||
if(withprefixparams) {
|
||||
ocappendparams(newuri,duri->paramlist);
|
||||
}
|
||||
if(duri->protocol != NULL)
|
||||
strcat(newuri,duri->protocol);
|
||||
@ -427,92 +521,93 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
|
||||
strcat(newuri,duri->port);
|
||||
}
|
||||
|
||||
strcat(newuri,tmpfile);
|
||||
if(suffix != NULL) strcat(newuri,tmpsuffix);
|
||||
if(tmpfile != NULL) {
|
||||
strcat(newuri,tmpfile);
|
||||
if(suffix != NULL) strcat(newuri,tmpsuffix);
|
||||
}
|
||||
if(withconstraints) {
|
||||
strcat(newuri,"?");
|
||||
strcat(newuri,tmpquery);
|
||||
}
|
||||
if(withsuffixparams & !withprefixparams) {
|
||||
strcat(newuri,"#");
|
||||
ocappendparams(newuri,duri->paramlist);
|
||||
}
|
||||
return newuri;
|
||||
}
|
||||
|
||||
static void
|
||||
ocappendparams(char* newuri, char** p)
|
||||
{
|
||||
while(*p) {
|
||||
strcat(newuri,"[");
|
||||
strcat(newuri,*p++);
|
||||
if(strlen(*p) > 0) {
|
||||
strcat(newuri,"=");
|
||||
strcat(newuri,*p);
|
||||
}
|
||||
p++;
|
||||
strcat(newuri,"]");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Parameter support */
|
||||
|
||||
/*
|
||||
Client parameters are assumed to be
|
||||
one or more instances of bracketed pairs:
|
||||
e.g "[...][...]...".
|
||||
The bracket content in turn is assumed to be a
|
||||
comma separated list of <name>=<value> pairs.
|
||||
e.g. x=y,z=,a=b.
|
||||
If the same parameter is specifed more than once,
|
||||
then the first occurrence is used; this is so that
|
||||
is possible to forcibly override user specified
|
||||
parameters by prefixing.
|
||||
IMPORTANT: client parameter string is assumed to
|
||||
have blanks compress out.
|
||||
Returns 1 if parse suceeded, 0 otherwise;
|
||||
*/
|
||||
In the original url, client parameters are assumed to be one
|
||||
or more instances of bracketed pairs: e.g "[...][...]...".
|
||||
They may occur either at the front, or suffixed after
|
||||
a trailing # character After processing, the list is
|
||||
converted to a semicolon separated list of the combination
|
||||
of prefix and suffix parameters.
|
||||
|
||||
After the url is parsed, the parameter list
|
||||
is converted to a semicolon separated list with all
|
||||
whitespace removed.
|
||||
In any case, each parameter in turn is assumed to be a
|
||||
of the form <name>=<value> or [<name>].
|
||||
e.g. [x=y][z][a=b][w]. If the same parameter is specified more
|
||||
than once, then the first occurrence is used; this is so
|
||||
that is possible to forcibly override user specified
|
||||
parameters by prefixing. IMPORTANT: client parameter string
|
||||
is assumed to have blanks compressed out. Returns 1 if parse
|
||||
suceeded, 0 otherwise; */
|
||||
|
||||
int
|
||||
ocuridecodeparams(OCURI* ocuri)
|
||||
{
|
||||
char* cp;
|
||||
char* cq;
|
||||
int c;
|
||||
int i;
|
||||
int i,c;
|
||||
int nparams;
|
||||
char* params0;
|
||||
char* params;
|
||||
char* params1;
|
||||
char** plist;
|
||||
|
||||
if(ocuri == NULL) return 0;
|
||||
if(ocuri->params == NULL) return 1;
|
||||
|
||||
params0 = ocuri->params;
|
||||
params = strdup(ocuri->params); /* so we can modify */
|
||||
|
||||
/* Pass 1 to replace beginning '[' and ending ']' */
|
||||
if(params0[0] == '[')
|
||||
params = nulldup(params0+1);
|
||||
else
|
||||
params = nulldup(params0);
|
||||
|
||||
if(params[strlen(params)-1] == ']')
|
||||
params[strlen(params)-1] = '\0';
|
||||
|
||||
/* Pass 2 to replace "][" pairs with ','*/
|
||||
params1 = nulldup(params);
|
||||
cp=params; cq = params1;
|
||||
while((c=*cp++)) {
|
||||
if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
|
||||
*cq++ = c;
|
||||
}
|
||||
*cq = '\0';
|
||||
free(params);
|
||||
params = params1;
|
||||
|
||||
/* Pass 3 to break string into pieces and count # of pairs */
|
||||
/* Pass 1 to break string into pieces at the semicolons
|
||||
and count # of pairs */
|
||||
nparams=0;
|
||||
for(cp=params;(c=*cp);cp++) {
|
||||
if(c == ',') {*cp = '\0'; nparams++;}
|
||||
if(c == ';') {*cp = EOFCHAR; nparams++;}
|
||||
}
|
||||
nparams++; /* for last one */
|
||||
|
||||
/* plist is an env style list */
|
||||
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
|
||||
|
||||
/* Pass 4 to break up each pass into a (name,value) pair*/
|
||||
/* Break up each param into a (name,value) pair*/
|
||||
/* and insert into the param list */
|
||||
/* parameters of the form name name= are converted to name=""*/
|
||||
cp = params;
|
||||
for(i=0;i<nparams;i++) {
|
||||
for(cp=params,i=0;i<nparams;i++) {
|
||||
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
|
||||
char* vp;
|
||||
/*break up the ith param*/
|
||||
vp = strchr(cp,'=');
|
||||
if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
|
||||
if(vp != NULL) {*vp = EOFCHAR; vp++;} else {vp = "";}
|
||||
plist[2*i] = nulldup(cp);
|
||||
plist[2*i+1] = nulldup(vp);
|
||||
cp = next;
|
||||
@ -525,19 +620,22 @@ ocuridecodeparams(OCURI* ocuri)
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char*
|
||||
ocurilookup(OCURI* uri, const char* key)
|
||||
int
|
||||
ocurilookup(OCURI* uri, const char* key, const char** resultp)
|
||||
{
|
||||
int i;
|
||||
if(uri == NULL || key == NULL || uri->params == NULL) return NULL;
|
||||
char* value = NULL;
|
||||
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
|
||||
if(uri->paramlist == NULL) {
|
||||
i = ocuridecodeparams(uri);
|
||||
if(!i) return 0;
|
||||
}
|
||||
i = ocfind(uri->paramlist,key);
|
||||
if(i >= 0)
|
||||
return uri->paramlist[(2*i)+1];
|
||||
return NULL;
|
||||
if(i < 0)
|
||||
return 0;
|
||||
value = uri->paramlist[(2*i)+1];
|
||||
if(resultp) *resultp = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@ -575,81 +673,46 @@ ocparamfree(char** params)
|
||||
free(params);
|
||||
}
|
||||
|
||||
#ifdef OCIGNORE
|
||||
/*
|
||||
Delete the entry.
|
||||
return value = 1 => found and deleted;
|
||||
0 => param not found
|
||||
|
||||
/* Return the ptr to the first occurrence of
|
||||
any char in the list. Return NULL if no
|
||||
occurrences
|
||||
*/
|
||||
int
|
||||
ocparamdelete(char** params, const char* key)
|
||||
static char*
|
||||
oclocate(char* p, const char* charlist)
|
||||
{
|
||||
int i;
|
||||
char** p;
|
||||
char** q;
|
||||
if(params == NULL || key == NULL) return 0;
|
||||
i = ocfind(params,key);
|
||||
if(i < 0) return 0;
|
||||
p = params+(2*i);
|
||||
for(q=p+2;*q;) {
|
||||
*p++ = *q++;
|
||||
for(;*p;p++) {
|
||||
if(strchr(charlist,*p) != NULL)
|
||||
return p;
|
||||
}
|
||||
*p = NULL;
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
oclength(char** params)
|
||||
|
||||
/* Shift every char starting at p 1 place to the left */
|
||||
static void
|
||||
oclshift1(char* p)
|
||||
{
|
||||
int i = 0;
|
||||
if(params != NULL) {
|
||||
while(*params) {params+=2; i++;}
|
||||
if(p != NULL && *p != EOFCHAR) {
|
||||
char* q = p++;
|
||||
while((*q++=*p++));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
Insert new client param (name,value);
|
||||
return value = 1 => not already defined
|
||||
0 => param already defined (no change)
|
||||
*/
|
||||
char**
|
||||
ocparaminsert(char** params, const char* key, const char* value)
|
||||
/* Shift every char starting at p 1 place to the right */
|
||||
static void
|
||||
ocrshift1(char* p)
|
||||
{
|
||||
int i;
|
||||
char** newp;
|
||||
size_t len;
|
||||
if(params == NULL || key == NULL) return 0;
|
||||
i = ocfind(params,key);
|
||||
if(i >= 0) return 0;
|
||||
/* not found, append */
|
||||
i = oclength(params);
|
||||
len = sizeof(char*)*((2*i)+1);
|
||||
newp = realloc(params,len+2*sizeof(char*));
|
||||
memcpy(newp,params,len);
|
||||
newp[2*i] = nulldup(key);
|
||||
newp[2*i+1] = (value==NULL?NULL:nulldup(value));
|
||||
return newp;
|
||||
char cur;
|
||||
cur = 0;
|
||||
do {
|
||||
char next = *p;
|
||||
*p++ = cur;
|
||||
cur = next;
|
||||
} while(cur != 0);
|
||||
*p = 0; /* make sure we are still null terminated */
|
||||
}
|
||||
|
||||
/*
|
||||
Replace new client param (name,value);
|
||||
return value = 1 => replacement performed
|
||||
0 => key not found (no change)
|
||||
*/
|
||||
int
|
||||
ocparamreplace(char** params, const char* key, const char* value)
|
||||
{
|
||||
int i;
|
||||
if(params == NULL || key == NULL) return 0;
|
||||
i = ocfind(params,key);
|
||||
if(i < 0) return 0;
|
||||
if(params[2*i+1] != NULL) free(params[2*i+1]);
|
||||
params[2*i+1] = nulldup(value);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Provide % encoders and decoders */
|
||||
|
||||
@ -713,7 +776,7 @@ ocuriencode(char* s, char* allowable)
|
||||
}
|
||||
}
|
||||
}
|
||||
*outptr = '\0';
|
||||
*outptr = EOFCHAR;
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@ -749,7 +812,7 @@ ocuridecodeonly(char* s, char* only)
|
||||
*outptr++ = ' ';
|
||||
else if(c == '%') {
|
||||
/* try to pull two hex more characters */
|
||||
if(inptr[0] != '\0' && inptr[1] != '\0'
|
||||
if(inptr[0] != EOFCHAR && inptr[1] != EOFCHAR
|
||||
&& strchr(hexchars,inptr[0]) != NULL
|
||||
&& strchr(hexchars,inptr[1]) != NULL) {
|
||||
/* test conversion */
|
||||
@ -762,7 +825,7 @@ ocuridecodeonly(char* s, char* only)
|
||||
}
|
||||
*outptr++ = c;
|
||||
}
|
||||
*outptr = '\0';
|
||||
*outptr = EOFCHAR;
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
31
oc2/ocuri.h
31
oc2/ocuri.h
@ -8,17 +8,19 @@
|
||||
it is ok to directly access its fields*/
|
||||
typedef struct OCURI {
|
||||
char* uri; /* as passed by the caller */
|
||||
char* params; /* all params */
|
||||
char** paramlist; /*!<null terminated list */
|
||||
char* constraint; /*!< projection+selection */
|
||||
char* projection; /*!< without leading '?'*/
|
||||
char* selection; /*!< with leading '&'*/
|
||||
char* strings; /* first char of strings is always '\0' */
|
||||
/* Following all point into the strings field */
|
||||
char* protocol;
|
||||
char* user; /* from user:password@ */
|
||||
char* password; /* from user:password@ */
|
||||
char* host; /*!< host*/
|
||||
char* port; /*!< host */
|
||||
char* file; /*!< file */
|
||||
char* constraint; /*!< projection+selection */
|
||||
char* projection; /*!< without leading '?'*/
|
||||
char* selection; /*!< with leading '&'*/
|
||||
char* params; /* all params */
|
||||
char** paramlist; /*!<null terminated list */
|
||||
} OCURI;
|
||||
|
||||
extern int ocuriparse(const char* s, OCURI** ocuri);
|
||||
@ -30,20 +32,25 @@ extern void ocurisetconstraints(OCURI*,const char* constraints);
|
||||
/* Construct a complete OC URI; caller frees returned string */
|
||||
|
||||
/* Define flags to control what is included */
|
||||
#define OCURICONSTRAINTS 1
|
||||
#define OCURIUSERPWD 2
|
||||
#define OCURIPARAMS 4
|
||||
#define OCURIENCODE 8 /* If output should be encoded */
|
||||
#define OCURICONSTRAINTS 1
|
||||
#define OCURIUSERPWD 2
|
||||
#define OCURIPREFIXPARAMS 4
|
||||
#define OCURISUFFIXPARAMS 8
|
||||
#define OCURIPARAMS OCURIPREFIXPARAMS
|
||||
#define OCURIENCODE 16 /* If output should be encoded */
|
||||
#define OCURISTD (OCURICONSTRAINTS|OCURIUSERPWD)
|
||||
|
||||
extern char* ocuribuild(OCURI*,const char* prefix, const char* suffix, int flags);
|
||||
|
||||
|
||||
/* Param Management */
|
||||
extern int ocuridecodeparams(OCURI* ocuri);
|
||||
extern int ocurisetparams(OCURI* ocuri,const char*);
|
||||
|
||||
/*! NULL result => entry not found.
|
||||
Empty value should be represented as a zero length string */
|
||||
extern const char* ocurilookup(OCURI*, const char* param);
|
||||
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
|
||||
In any case, the result is imutable and should not be free'd.
|
||||
*/
|
||||
extern int ocurilookup(OCURI*, const char* param, const char** result);
|
||||
|
||||
extern char* ocuriencode(char* s, char* allowable);
|
||||
extern char* ocuridecode(char* s);
|
||||
|
@ -433,7 +433,7 @@ ocdataddsmsg(OCstate* state, OCtree* tree)
|
||||
if(c > 0 && (c < ' ' || c >= '\177'))
|
||||
contents[i+j] = ERRFILL;
|
||||
}
|
||||
oc_log(LOGERR,"DATADDS failure, possible message: '%s'\n",
|
||||
oclog(OCLOGERR,"DATADDS failure, possible message: '%s'\n",
|
||||
contents+i);
|
||||
goto done;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user