Merged latest trunk into branch

This commit is contained in:
Ward Fisher 2012-08-13 19:57:51 +00:00
commit ffb7dc6f0d
50 changed files with 1817 additions and 677 deletions

2
cf
View File

@ -7,7 +7,7 @@ if test $# != 0 ; then
cmds=$@
fi
HDF5=1
#HDF5=1
DAP=1
#CDMR=1
#RPC=1

View File

@ -15,7 +15,7 @@ AC_REVISION([$Id: configure.ac,v 1.450 2010/05/28 19:42:47 dmh Exp $])
AC_PREREQ([2.59])
# Initialize with name, version, and support email address.
AC_INIT([netCDF], [4.3], [support-netcdf@unidata.ucar.edu])
AC_INIT([netCDF], [4.2.1.1], [support-netcdf@unidata.ucar.edu])
# Create the VERSION file, which contains the package version from
# AC_INIT.

View File

@ -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

View File

@ -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*/

View File

@ -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*/

View File

@ -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))

View File

@ -11,7 +11,7 @@
#define EXTERNC extern
#endif
typedef unsigned long ncelem;
typedef void* ncelem;
EXTERNC int nclistnull(ncelem);
@ -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*/

View File

@ -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
View 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*/

View File

@ -1,34 +1,26 @@
#NETCDF4=1
#CURLLIB=-L/opt/csw/lib -lcurl
# for irix
#CURLLIB=/upc/share/stdinstall/local/flip/lib/libcurl.a -llber -lldap -lz
#CURLLIB=-L/opt/csw/lib -lcurl -lidn -lssl -lcrypto -llber -lldap -lnsl
#CURLINCL=-I/opt/csw/include
#RPCLIB=-lnsl
#ZLIB=-L/opt/csw/lib -lz
#TESTURL=file:///upc/share/dmh/nc/netcdf-3/ncdap_test/testdata3
VALGRIND=valgrind --leak-check=full
#NCLIB=/tmp/install/lib/libnetcdf.a
CYG=1
#HDF=1
NCLIB=../liblib/.libs/libnetcdf.a
NCINCL=-I ../liblib
#OCLIB=liboc.a
#OCINCL=-I./oc
ifneq ($(CYG),1)
LFLAG=-L/upc/share/ed/local/${HOST}/lib
else
# !CYGWIN
ifneq ($(HDF),1)
HDF5LIB=/share/ed/local/${HOST}/lib/libhdf5_hl.a /share/ed/local/${HOST}/lib/libhdf5.a
endif
endif
CURLLIB=-lcurl
ZLIB=-lz
#HDF5LIB=-lhdf5_hl -lhdf5
HDF5LIB=/share/ed/local/${HOST}/lib/libhdf5_hl.a /share/ed/local/${HOST}/lib/libhdf5.a
OTHERLIBS=-lm
LIBS=${NCLIB} ${LFLAG} ${CURLLIB} ${HDF5LIB} ${ZLIB} ${OTHERLIBS}
INCL=-I. -I.. -I../include ${NCINCL} ${CURLINCL}
INCL=-I. -I.. -I../include ${NCINCL}
RPATH=-Wl,-rpath,${LFLAG}
# Might want to specify a particular C compiler with flags

View File

@ -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++) {

View File

@ -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

View File

@ -1,24 +1,29 @@
PARMS=""; ARGS=""; CON="" ; CE=""; OCON="" ; VAR=""
alias q0=;alias qq=;alias qv=;alias q=;alias qh=;alias qqh=;alias qall=;alias qv=;alias qo=;
TOP="/home/dmh/mach/major"
#TOP="/home/dmh/mach/major"
TOP="/cygdrive/f/svn/trunk"
PROG=./ncd
#PROG="$TOP/ncdump/ncdump"
#PROG=./ncd
PROG="$TOP/ncdump/ncdump"
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
F="http://hycom.coaps.fsu.edu/thredds/dodsC/atl_ops"
PARMS="[log]"
VAR=f64
#PARMS="[log]"
#PARMS="${PARMS}[netcdf3]"
PARMS="${PARMS}[fetch=disk]"
#PARMS="${PARMS}[fetch=disk]"
#PARMS="${PARMS}[cache]"
#PARMS="${PARMS}[prefetch]"
#PARMS="${PARMS}[nocache]"
@ -53,6 +58,7 @@ alias qq="gdb --args $PROG $ARGS '$U'"
alias qv="valgrind $VARGS PROG $ARGS '$U'"
alias q0="$PROG $ARGS '$U'"
alias qh="$PROG -h $ARGS '$U'"
alias qk="$PROG -k $ARGS '$U'"
alias qvar="$PROG -v $VAR $ARGS '$U'"
alias qqh="gdb --args $PROG -h $ARGS '$U'"
alias qall="$PROG -h $ARGS '${UALL}'"

View File

@ -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*);

View File

@ -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);
@ -143,11 +145,8 @@ NCD3_open(const char * path, int mode,
/* Use libsrc code for storing metadata */
snprintf(tmpname,sizeof(tmpname),"%d",drno->int_ncid);
/* Now, use the file to create the netcdf file */
if(sizeof(size_t) == sizeof(unsigned int))
ncstat = nc_create(tmpname,NC_DISKLESS,&drno->substrate);
else
ncstat = nc_create(tmpname,NC_DISKLESS|NC_64BIT_OFFSET,&drno->substrate);
/* Now, use the file to create the netcdf file; always 64 bit */
ncstat = nc_create(tmpname,NC_DISKLESS|NC_64BIT_OFFSET,&drno->substrate);
if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
/* Avoid fill */
@ -164,9 +163,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 +182,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 +285,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

View File

@ -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"

View File

@ -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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -6,10 +6,7 @@
#include "nclist.h"
static ncelem ncDATANULL = (ncelem)0;
/*static int ncinitialized=0;*/
int nclistnull(ncelem e) {return e == ncDATANULL;}
int nclistnull(ncelem e) {return e == NULL;}
#ifndef TRUE
#define TRUE 1
@ -79,8 +76,8 @@ nclistsetlength(NClist* l, unsigned int sz)
ncelem
nclistget(NClist* l, unsigned int index)
{
if(l == NULL || l->length == 0) return ncDATANULL;
if(index >= l->length) return ncDATANULL;
if(l == NULL || l->length == 0) return NULL;
if(index >= l->length) return NULL;
return l->content[index];
}
@ -120,7 +117,7 @@ nclistpush(NClist* l, ncelem elem)
ncelem
nclistpop(NClist* l)
{
if(l == NULL || l->length == 0) return ncDATANULL;
if(l == NULL || l->length == 0) return NULL;
l->length--;
return l->content[l->length];
}
@ -128,7 +125,7 @@ nclistpop(NClist* l)
ncelem
nclisttop(NClist* l)
{
if(l == NULL || l->length == 0) return ncDATANULL;
if(l == NULL || l->length == 0) return NULL;
return l->content[l->length - 1];
}
@ -137,8 +134,8 @@ nclistremove(NClist* l, unsigned int i)
{
unsigned int len;
ncelem elem;
if(l == NULL || (len=l->length) == 0) return ncDATANULL;
if(i >= len) return ncDATANULL;
if(l == NULL || (len=l->length) == 0) return NULL;
if(i >= len) return NULL;
elem = l->content[i];
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
l->length--;
@ -172,7 +169,7 @@ nclistelemremove(NClist* l, ncelem elem)
unsigned int len;
unsigned int i;
int found = 0;
if(l == NULL || (len=l->length) == 0) return ncDATANULL;
if(l == NULL || (len=l->length) == 0) return 0;
for(i=0;i<nclistlength(l);i++) {
ncelem candidate = l->content[i];
if(elem == candidate) {

View File

@ -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
View 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;
}

View File

@ -19,6 +19,7 @@ Components of a NetCDF Data Set
- \ref data_model
- \ref dimensions
- \ref variables
- \ref coordinate_variables
- \ref attributes
- \ref differences_atts_vars
@ -313,7 +314,7 @@ The mere use of netCDF is not sufficient to make data
"self-describing" and meaningful to both humans and machines. The
names of variables and dimensions should be meaningful and conform to
any relevant conventions. Dimensions should have corresponding
coordinate variables where sensible.
coordinate variables (See \ref coordinate_variables) where sensible.
Attributes play a vital role in providing ancillary information. It is
important to use all the relevant standard attributes using the
@ -671,6 +672,20 @@ short, whereas the unpacked values are intended to be of type float or
double. The attributes scale_factor and add_offset should both be of
the type intended for the unpacked data, e.g. float or double.
\section coordinates
Following the CF (Climate and Forecast) conventions for netCDF
metadata, we define an <em>auxiliary coordinate variable</em> as any netCDF
variable that contains coordinate data, but is not a coordinate
variable (See \ref coordinate_variables). Unlike coordinate
variables, there is no relationship between the name of an auxiliary
coordinate variable and the name(s) of its dimension(s).
The value of the coordinates attribute is a blank separated list of
names of auxiliary coordinate variables and (optionally) coordinate
variables. There is no restriction on the order in which the variable
names appear in the coordinates attribute string.
\section signedness
Deprecated attribute, originally designed to indicate whether byte
@ -1299,25 +1314,27 @@ for variables with dimensions, or
for scalar variables.
In the above CDL example there are six variables. As discussed below,
four of these are coordinate variables. The remaining variables
(sometimes called primary variables), temp and rh, contain what is
usually thought of as the data. Each of these variables has the
unlimited dimension time as its first dimension, so they are called
record variables. A variable that is not a record variable has a fixed
length (number of data values) given by the product of its dimension
lengths. The length of a record variable is also the product of its
dimension lengths, but in this case the product is variable because it
involves the length of the unlimited dimension, which can vary. The
length of the unlimited dimension is the number of records. 2.3.1
Coordinate Variables
four of these are coordinate variables (See coordinate_variables). The
remaining variables (sometimes called primary variables), temp and rh,
contain what is usually thought of as the data. Each of these
variables has the unlimited dimension time as its first dimension, so
they are called record variables. A variable that is not a record
variable has a fixed length (number of data values) given by the
product of its dimension lengths. The length of a record variable is
also the product of its dimension lengths, but in this case the
product is variable because it involves the length of the unlimited
dimension, which can vary. The length of the unlimited dimension is
the number of records.
\page coordinate_variables Coordinate Variables
It is legal for a variable to have the same name as a dimension. Such
variables have no special meaning to the netCDF library. However there
is a convention that such variables should be treated in a special way
by software using this library.
A variable with the same name as a dimension is called a coordinate
variable. It typically defines a physical coordinate corresponding to
A variable with the same name as a dimension is called a
<em>coordinate variable</em>. It typically defines a physical coordinate corresponding to
that dimension. The above CDL example includes the coordinate
variables lat, lon, level and time, defined as follows:

View File

@ -932,11 +932,66 @@ int ncstring_typ_tostring(const nctype_t *typ, safebuf_t *sfbf, const void *valp
size_t slen;
char *sout;
int res;
int iel;
const char *cp;
char *sp;
unsigned char uc;
slen = 3 + strlen(((char **)valp)[0]); /* need "'s around string */
cp = ((char **)valp)[0];
slen = 3 + 5 * strlen(cp); /* need "'s around string, and extra space to escape control characters */
sout = emalloc(slen);
res = snprintf(sout, slen, "\"%s\"", ((char **)valp)[0]);
assert(res > 0);
sp = sout;
*sp++ = '"' ;
while(*cp) {
switch (uc = *cp++ & 0377) {
case '\b':
*sp++ = '\\';
*sp++ = 'b' ;
break;
case '\f':
*sp++ = '\\';
*sp++ = 'f';
break;
case '\n':
*sp++ = '\\';
*sp++ = 'n';
break;
case '\r':
*sp++ = '\\';
*sp++ = 'r';
break;
case '\t':
*sp++ = '\\';
*sp++ = 't';
break;
case '\v':
*sp++ = '\\';
*sp++ = 'n';
break;
case '\\':
*sp++ = '\\';
*sp++ = '\\';
break;
case '\'':
*sp++ = '\\';
*sp++ = '\'';
break;
case '\"':
*sp++ = '\\';
*sp++ = '\"';
break;
default:
if (iscntrl(uc)) {
snprintf(sp,3,"\\%03o",uc);
sp += 4;
}
else
*sp++ = uc;
break;
}
}
*sp++ = '"' ;
*sp++ = '\0' ;
sbuf_cpy(sfbf, sout);
free(sout);
return sbuf_len(sfbf);

View File

@ -295,7 +295,7 @@ pr_att_string(
printf ("\\\\");
break;
case '\'':
printf ("\\'");
printf ("\\\'");
break;
case '\"':
printf ("\\\"");

View File

@ -7,5 +7,5 @@ variables:
data:
description = "first string", "second string", "third string", _,
"last string" ;
"last \n\"string\"" ;
}

View File

@ -30,7 +30,7 @@ main(int argc, char **argv)
int var_dims[VAR4_RANK];
const char *desc_data[DIM4_LEN] = {
"first string", "second string", "third string", "", "last string"
"first string", "second string", "third string", "", "last \n\"string\""
};
const char *missing_val[ATT4_LEN] = {""};
char *strings_in[DIM4_LEN];

View File

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 2.6.2. */
/* A Bison parser, made by GNU Bison 2.4.2. */
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -44,7 +45,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "2.6.2"
#define YYBISON_VERSION "2.4.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"

View File

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 2.6.2. */
/* A Bison parser, made by GNU Bison 2.4.2. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -355,13 +355,22 @@ ocread(OCdata* data, XXDR* xdrs, char* memory, size_t memsize, size_t start, siz
/* non-packed fixed length, but memory size < xdrsize */
case OC_Int16: case OC_UInt16: {
/* In order to avoid allocating a lot of space, we do this one int at a time */
/* Remember also that the short is not packed, so its xdr size is twice
its memory size */
xxdr_setpos(xdrs,data->xdroffset+xdrstart);
if(scalar) {
if(!xxdr_ushort(xdrs,(unsigned short*)memory)) {OCTHROW(OC_EDATADDS); goto xdrfail;}
} else {
unsigned short* sp = (unsigned short*)memory;
for(i=0;i<count;i++,sp++) {
if(!xxdr_ushort(xdrs,sp)) {OCTHROW(OC_EDATADDS); goto xdrfail;}
unsigned int tmp;
if(!xxdr_getbytes(xdrs,(char*)&tmp,XDRUNIT))
{OCTHROW(OC_EDATADDS); goto xdrfail;}
/* convert from network order if necessary */
if(!xxdr_network_order)
swapinline32(&tmp);
/* store as unsigned short */
*sp = (unsigned short)tmp;
}
}
} break;
@ -404,7 +413,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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -1,18 +1,12 @@
/* 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>
#include "oclist.h"
static ocelem ocDATANULL = (ocelem)0;
/*static int ocinitialized=0;*/
int oclistnull(ocelem e) {return e == ocDATANULL;}
int oclistnull(ocelem e) {return e == NULL;}
#ifndef TRUE
#define TRUE 1
@ -24,7 +18,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 +27,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 +57,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;
@ -84,8 +76,8 @@ oclistsetlength(OClist* l, unsigned int sz)
ocelem
oclistget(OClist* l, unsigned int index)
{
if(l == NULL || l->length == 0) return ocDATANULL;
if(index >= l->length) return ocDATANULL;
if(l == NULL || l->length == 0) return NULL;
if(index >= l->length) return NULL;
return l->content[index];
}
@ -102,11 +94,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;
@ -125,7 +117,7 @@ oclistpush(OClist* l, ocelem elem)
ocelem
oclistpop(OClist* l)
{
if(l == NULL || l->length == 0) return ocDATANULL;
if(l == NULL || l->length == 0) return NULL;
l->length--;
return l->content[l->length];
}
@ -133,7 +125,7 @@ oclistpop(OClist* l)
ocelem
oclisttop(OClist* l)
{
if(l == NULL || l->length == 0) return ocDATANULL;
if(l == NULL || l->length == 0) return NULL;
return l->content[l->length - 1];
}
@ -142,10 +134,10 @@ oclistremove(OClist* l, unsigned int i)
{
unsigned int len;
ocelem elem;
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
if(i >= len) return ocDATANULL;
if(l == NULL || (len=l->length) == 0) return NULL;
if(i >= len) return NULL;
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 +161,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 0;
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;
}

View File

@ -11,7 +11,7 @@
#define EXTERNC extern
#endif
typedef unsigned long ocelem;
typedef void* ocelem;
EXTERNC int oclistnull(ocelem);
@ -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*/

View File

@ -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];
}
}

View File

@ -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*/

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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,140 +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;
if(strncmp(protocol,"file",4)) {
port = strchr(p,':');
if(port!=NULL)
*port++ = '\0';
}
/* Locate end of the file */
constraint = strchr(file,'?');
if(constraint!=NULL)
suffixparams = strchr(constraint,'#');
else
suffixparams = strchr(file,'#');
assert(file != NULL);
p = 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
@ -267,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;
}
@ -282,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);
}
@ -315,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;
@ -327,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 {
@ -339,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.
*/
@ -353,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);
@ -367,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(":@"));
@ -399,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);
@ -428,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;
@ -526,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
@ -576,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 */
@ -714,7 +776,7 @@ ocuriencode(char* s, char* allowable)
}
}
}
*outptr = '\0';
*outptr = EOFCHAR;
return encoded;
}
@ -750,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 */
@ -763,7 +825,7 @@ ocuridecodeonly(char* s, char* only)
}
*outptr++ = c;
}
*outptr = '\0';
*outptr = EOFCHAR;
return decoded;
}

View File

@ -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);

View File

@ -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;
}