+
+#include "cgi/cgi.h"
+#include "cgi/cgiwrap.h"
+#include "util/neo_misc.h"
+
+/* from httpd util.c : made infamous with Roy owes Rob beer. */
+static char *months[] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+int find_month(char *mon) {
+ register int x;
+
+ for(x=0;x<12;x++)
+ if(!strcmp(months[x],mon))
+ return x;
+ return -1;
+}
+
+int later_than(struct tm *lms, char *ims) {
+ char *ip;
+ char mname[256];
+ int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, x;
+
+ /* Whatever format we're looking at, it will start
+ * with weekday. */
+ /* Skip to first space. */
+ if(!(ip = strchr(ims,' ')))
+ return 0;
+ else
+ while(isspace(*ip))
+ ++ip;
+
+ if(isalpha(*ip)) {
+ /* ctime */
+ sscanf(ip,"%s %d %d:%d:%d %d",mname,&day,&hour,&min,&sec,&year);
+ }
+ else if(ip[2] == '-') {
+ /* RFC 850 (normal HTTP) */
+ char t[256];
+ sscanf(ip,"%s %d:%d:%d",t,&hour,&min,&sec);
+ t[2] = '\0';
+ day = atoi(t);
+ t[6] = '\0';
+ strcpy(mname,&t[3]);
+ x = atoi(&t[7]);
+ /* Prevent
+ * wraparound
+ * from
+ * ambiguity
+ * */
+ if(x < 70)
+ x += 100;
+ year = 1900 + x;
+ }
+ else {
+ /* RFC 822 */
+ sscanf(ip,"%d %s %d %d:%d:%d",&day,mname,&year,&hour,&min,&sec);
+ }
+ month = find_month(mname);
+
+ if((x = (1900+lms->tm_year) - year))
+ return x < 0;
+ if((x = lms->tm_mon - month))
+ return x < 0;
+ if((x = lms->tm_mday - day))
+ return x < 0;
+ if((x = lms->tm_hour - hour))
+ return x < 0;
+ if((x = lms->tm_min - min))
+ return x < 0;
+ if((x = lms->tm_sec - sec))
+ return x < 0;
+
+ return 1;
+}
+
+
+
+int gif_size (char *file, int *width, int *height)
+{
+ UINT8 data[256];
+ int fd;
+ int blen;
+
+ *width = 0; *height = 0;
+ fd = open (file, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ blen = read(fd, data, sizeof(data));
+ close(fd);
+
+ if (blen < 10) return -1;
+ if (strncmp(data, "GIF87a", 6) && strncmp(data, "GIF89a", 6))
+ return -1;
+
+ *width = data[6] + data[7]*256;
+ *height = data[8] + data[9]*256;
+
+ return 0;
+}
+
+int jpeg_size (char *file, int *width, int *height)
+{
+ UINT8 data[64*1024];
+ int blen;
+ int fd;
+ int pos;
+ int length;
+ UINT8 tag, marker;
+
+
+ *width = 0; *height = 0;
+ fd = open (file, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ blen = read(fd, data, sizeof(data));
+ close(fd);
+ pos = 2;
+ while (pos+8 < blen)
+ {
+ tag = data[pos+0];
+ if (tag != 0xff) return -1;
+ marker = data[pos+1];
+ length = data[pos+2] * 256 + data[pos+3] + 2;
+ if (marker >= 0xc0 && marker <= 0xcf && marker != 0xc4 &&
+ marker != 0xc8 && marker != 0xcc)
+ {
+ *height = data[pos+5] * 256 + data[pos+6];
+ *width = data[pos+7] * 256 + data[pos+8];
+ return 0;
+ }
+ pos += length;
+ }
+ return -1;
+}
+
+int isdir(char *dir) {
+ struct stat statinfo;
+ if ( stat(dir, &statinfo) != 0) {
+ return 0;
+ }
+
+ return S_ISDIR(statinfo.st_mode);
+}
+
+int create_directories(char *fullpath) {
+ char s[4000];
+ char *last_slash;
+ int last_slash_pos;
+
+ if ((fullpath == NULL) || (strlen(fullpath) > 4000)) {
+ return 1;
+ }
+
+ last_slash = strrchr(fullpath,'/');
+ last_slash_pos = (last_slash - fullpath);
+ /* fprintf(stderr,"dira(%d): %s\n", last_slash_pos,fullpath); */
+
+ if (last_slash_pos > 2) {
+ strncpy(s,fullpath,last_slash_pos);
+ s[last_slash_pos] = 0;
+ /* fprintf(stderr,"dir: %s\n", s); */
+
+ if (!isdir(s)) {
+ char s2[4000];
+ sprintf(s2,"mkdir -p %s", s);
+ return system(s2);
+ }
+
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+NEOERR *rotate_image(char *path, char *file, int degree, char *rpath)
+{
+ char cmd[256];
+ char nfile[_POSIX_PATH_MAX];
+ char ofile[_POSIX_PATH_MAX];
+ char *ch, *opt;
+ int is_jpeg = 0;
+ struct stat s;
+ int r;
+
+ snprintf (ofile, sizeof(ofile), "%s/%s", path, file);
+ snprintf (rpath, _POSIX_PATH_MAX, "%s/%s", path, file);
+ ch = strrchr(rpath, '.');
+ if ((!strcasecmp(ch, ".jpg")) ||
+ (!strcasecmp(ch, ".jpeg")))
+ {
+ is_jpeg = 1;
+ }
+ else if (strcasecmp(ch, ".gif"))
+ {
+ return nerr_raise(NERR_ASSERT, "Only support gif/jpeg for rotation, ext %s",
+ ch);
+ }
+ *ch = '\0';
+ if (degree == 90)
+ {
+ strcat(rpath, "_r");
+ opt = "-cw";
+ }
+ else if (degree == -90)
+ {
+ strcat(rpath, "_l");
+ opt = "-ccw";
+ }
+ else if (degree == 180)
+ {
+ strcat(rpath, "_u");
+ opt = "-rotate180";
+ }
+ else
+ {
+ return nerr_raise(NERR_ASSERT, "currently only support 90/-90/180 rotations");
+ }
+ if (is_jpeg)
+ {
+ strcat(rpath, ".jpg");
+ snprintf(cmd, sizeof(cmd), "djpeg -pnm %s | pnmflip %s | cjpeg -quality 85 > %s", ofile, opt, rpath);
+ }
+ else
+ {
+ strcat(rpath, ".gif");
+ snprintf(cmd, sizeof(cmd), "giftopnm %s | pnmflip %s | ppmtogif > %s", ofile, opt, rpath);
+ }
+ /* already exists? */
+ if (!stat(rpath, &s))
+ {
+ return STATUS_OK;
+ }
+ r = system(cmd);
+ if (r) return nerr_raise_errno (NERR_SYSTEM, "%s returned %d", cmd, r);
+ /* always save off the old file */
+ snprintf (nfile, sizeof(nfile), "%s/%s.orig", path, file);
+ if (stat(nfile, &s))
+ {
+ if (link(ofile, nfile))
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to link %s -> %s", ofile, nfile);
+ unlink(ofile);
+ }
+ return STATUS_OK;
+}
+
+NEOERR *scale_and_display_image(char *fname,int maxW,int maxH,char *cachepath,
+ int quality)
+{
+ NEOERR *err = STATUS_OK;
+ /* Declare the image */
+ gdImagePtr src_im = 0;
+ /* Declare input file */
+ FILE *infile=0, *cachefile=0;
+ int srcX,srcY,srcW,srcH;
+ FILE *dispfile=0;
+ struct stat s;
+
+ /* if we can open the cachepath, then just print it */
+ if (!stat(cachepath, &s) && s.st_size)
+ cachefile = fopen(cachepath,"rb");
+ if (cachefile) {
+ /* we should probably stat the files and make sure the thumbnail
+ is current */
+ /* fprintf(stderr,"using cachefile: %s\n",cachepath); */
+ dispfile = cachefile;
+ } else {
+ char cmd[1024];
+ int factor=1;
+ int l;
+ int is_jpeg = 0, is_gif = 0;
+
+ l = strlen(fname);
+ if ((l>4 && !strcasecmp(fname+l-4, ".jpg")) ||
+ (l>5 && !strcasecmp(fname+l-5, ".jpeg")))
+ is_jpeg = 1;
+ else if (l>4 && !strcasecmp(fname+l-4, ".gif"))
+ is_gif = 1;
+
+ if (is_jpeg)
+ {
+ if (!quality)
+ {
+ if (!jpeg_size (fname, &srcW, &srcH))
+ {
+ if ((srcW > maxW) || (srcH > maxH))
+ {
+ factor = 2;
+ if (srcW / factor > maxW)
+ {
+ factor = 4;
+ if (srcW / factor > maxW)
+ factor = 8;
+ }
+ }
+ }
+
+ /* ne_warn("factor %d\n", factor); */
+ snprintf (cmd, sizeof(cmd), "/usr/bin/djpeg -fast -scale 1/%d '%s' | /usr/bin/cjpeg -quality 60 -progressive -dct fast -outfile '%s'", factor, fname, cachepath);
+
+ create_directories(cachepath);
+ system(cmd);
+ if (!stat(cachepath, &s) && s.st_size)
+ cachefile = fopen(cachepath,"rb");
+ else
+ ne_warn("external command failed to create file\n");
+ }
+ if (cachefile) {
+ dispfile = cachefile;
+
+ } else /* no cachefile */ {
+
+
+ /* fprintf(stderr,"reading image\n"); */
+ /* Read the image in */
+ infile = fopen(fname,"rb");
+ src_im = gdImageCreateFromJpeg(infile);
+ srcX=0; srcY=0; srcW=src_im->sx; srcH=src_im->sy;
+
+
+ /* figure out if we need to scale it */
+
+ if ((srcW > maxW) || (srcH > maxH)) {
+ /* scale paramaters */
+ int dstX,dstY,dstW,dstH;
+ /* Declare output file */
+ FILE *jpegout;
+ gdImagePtr dest_im;
+ float srcAspect,dstAspect;
+
+ /* create the destination image */
+
+ dstX=0; dstY=0;
+
+
+ srcAspect = ((float)srcW/(float)srcH);
+ dstAspect = ((float)maxW/(float)maxH);
+
+ if (srcAspect == dstAspect) {
+ /* they are the same aspect ratio */
+ dstW = maxW;
+ dstH = maxH;
+ } else if ( srcAspect > dstAspect ) {
+ /* if the src image has wider aspect ratio than the max */
+ dstW = maxW;
+ dstH = (int) ( ((float)dstW/(float)srcW) * srcH );
+ } else {
+ /* if the src image has taller aspect ratio than the max */
+ dstH = maxW;
+ dstW = (int) ( ((float)dstH/(float)srcH) * srcW );
+ }
+
+ dest_im = gdImageCreate(dstW,dstH);
+
+ /* fprintf(stderr,"scaling to (%d,%d)\n",dstW,dstH); */
+
+ /* Scale it to the destination image */
+
+ gdImageCopyResized(dest_im,src_im,dstX,dstY,srcX,srcY,dstW,dstH,srcW,srcH);
+
+ /* fprintf(stderr,"scaling finished\n"); */
+
+ /* write the output image */
+ create_directories(cachepath);
+ jpegout = fopen(cachepath,"wb+");
+ if (!jpegout) {
+ jpegout = fopen("/tmp/foobar.jpg","wb+");
+ }
+ if (jpegout) {
+ gdImageJpeg(dest_im,jpegout,-1);
+ fflush(jpegout);
+
+ /* now print that data out the stream */
+ dispfile = jpegout;
+ } else {
+ return nerr_raise_errno(NERR_IO, "Unable to create output file: %s", cachepath);
+ }
+
+
+ gdImageDestroy(dest_im);
+
+ } else {
+ /* just print the input file because it's small enough */
+ dispfile = infile;
+ }
+
+ }
+ }
+ else if (is_gif)
+ {
+ float scale = 1.0;
+ if (!gif_size (fname, &srcW, &srcH))
+ {
+ if ((srcW > maxW) || (srcH > maxH))
+ {
+ scale = 0.5;
+ if (srcW * scale > maxW)
+ {
+ scale = 0.25;
+ if (srcW * scale > maxW)
+ factor = 0.125;
+ }
+ }
+ }
+
+ if (scale < 1.0)
+ {
+ snprintf (cmd, sizeof(cmd), "/usr/bin/giftopnm '%s' | /usr/bin/pnmscale %5.3f | ppmquant 256 | ppmtogif > '%s'", fname, scale, cachepath);
+
+ create_directories(cachepath);
+ system(cmd);
+ dispfile = fopen(cachepath,"rb");
+ if (dispfile == NULL)
+ return nerr_raise_errno(NERR_IO, "Unable to open file: %s", cachepath);
+
+ }
+ else
+ {
+ dispfile = fopen(fname, "rb");
+ if (dispfile == NULL)
+ return nerr_raise_errno(NERR_IO, "Unable to open file: %s", fname);
+ }
+ }
+ else {
+ ne_warn("How'd I get here?");
+ return nerr_raise(NERR_ASSERT, "I shouldn't get here...");
+ }
+ }
+
+ /* the data in "dispfile" is going to be printed now */
+ {
+
+ char buf[8192];
+ int count;
+
+ fseek(dispfile,0,SEEK_SET);
+
+ do {
+ count = fread(buf,1,sizeof(buf),dispfile);
+ if (count > 0) {
+ err = cgiwrap_write(buf,count);
+ }
+ } while (count > 0);
+
+ }
+
+ if (dispfile) fclose(dispfile);
+ if (src_im) gdImageDestroy(src_im);
+
+ return nerr_pass(err);
+}
+
+char *url_escape (char *buf)
+{
+ int nl = 0;
+ int l = 0;
+ char *s;
+
+ while (buf[l])
+ {
+ if (buf[l] == '/' || buf[l] == '+' || buf[l] == '=' || buf[l] == '&' ||
+ buf[l] == '"' ||
+ buf[l] < 32 || buf[l] > 122)
+ {
+ nl += 2;
+ }
+ nl++;
+ l++;
+ }
+
+ s = (char *) malloc (sizeof(char) * (nl + 1));
+ if (s == NULL) return NULL;
+
+ nl = 0; l = 0;
+ while (buf[l])
+ {
+ if (buf[l] == ' ')
+ {
+ s[nl++] = '+';
+ l++;
+ }
+ else
+ if (buf[l] == '/' || buf[l] == '+' || buf[l] == '=' || buf[l] == '&' ||
+ buf[l] == '"' ||
+ buf[l] < 32 || buf[l] > 122)
+ {
+ s[nl++] = '%';
+ s[nl++] = "0123456789ABCDEF"[buf[l] / 16];
+ s[nl++] = "0123456789ABCDEF"[buf[l] % 16];
+ l++;
+ }
+ else
+ {
+ s[nl++] = buf[l++];
+ }
+ }
+ s[nl] = '\0';
+
+ return s;
+}
+
+NEOERR *load_images (char *path, ULIST **rfiles, char *partial, int descend)
+{
+ NEOERR *err = STATUS_OK;
+ DIR *dp;
+ struct dirent *de;
+ int is_jpeg, is_gif, l;
+ char fpath[_POSIX_PATH_MAX];
+ char ppath[_POSIX_PATH_MAX];
+ ULIST *files = NULL;
+
+ if ((dp = opendir (path)) == NULL)
+ {
+ return nerr_raise(NERR_IO, "Unable to opendir %s: [%d] %s", path, errno,
+ strerror(errno));
+ }
+
+ if (rfiles == NULL || *rfiles == NULL)
+ {
+ err = uListInit(&files, 50, 0);
+ if (err) return nerr_pass(err);
+ *rfiles = files;
+ }
+ else
+ {
+ files = *rfiles;
+ }
+
+ while ((de = readdir (dp)) != NULL)
+ {
+ if (de->d_name[0] != '.')
+ {
+ snprintf(fpath, sizeof(fpath), "%s/%s", path, de->d_name);
+ if (partial)
+ {
+ snprintf(ppath, sizeof(ppath), "%s/%s", partial, de->d_name);
+ }
+ else
+ {
+ strncpy(ppath, de->d_name, sizeof(ppath));
+ }
+ if (descend && isdir(fpath))
+ {
+ err = load_images(fpath, rfiles, ppath, descend);
+ if (err) break;
+ }
+ else
+ {
+ l = strlen(de->d_name);
+ is_jpeg = 0; is_gif = 0;
+
+ if ((l>4 && !strcasecmp(de->d_name+l-4, ".jpg")) ||
+ (l>5 && !strcasecmp(de->d_name+l-5, ".jpeg")))
+ is_jpeg = 1;
+ else if (l>4 && !strcasecmp(de->d_name+l-4, ".gif"))
+ is_gif = 1;
+
+ if (is_gif || is_jpeg)
+ {
+ err = uListAppend(files, strdup(ppath));
+ if (err) break;
+ }
+ }
+ }
+ }
+ closedir(dp);
+ if (err)
+ {
+ uListDestroy(&files, ULIST_FREE);
+ }
+ else
+ {
+ *rfiles = files;
+ }
+ return nerr_pass(err);
+}
+
+NEOERR *export_image(CGI *cgi, char *prefix, char *path, char *file)
+{
+ NEOERR *err;
+ char buf[256];
+ char num[20];
+ int i = 0;
+ int r, l;
+ int width, height;
+ char ipath[_POSIX_PATH_MAX];
+ int is_jpeg = 0, is_gif = 0;
+
+ l = strlen(file);
+ if ((l>4 && !strcasecmp(file+l-4, ".jpg")) ||
+ (l>5 && !strcasecmp(file+l-5, ".jpeg")))
+ is_jpeg = 1;
+ else if (l>4 && !strcasecmp(file+l-4, ".gif"))
+ is_gif = 1;
+
+ snprintf (buf, sizeof(buf), "%s.%d", prefix, i);
+ err = hdf_set_buf (cgi->hdf, prefix, url_escape(file));
+ if (err != STATUS_OK) return nerr_pass(err);
+ snprintf (ipath, sizeof(ipath), "%s/%s", path, file);
+ if (is_jpeg)
+ r = jpeg_size(ipath, &width, &height);
+ else
+ r = gif_size(ipath, &width, &height);
+ if (!r)
+ {
+ snprintf (buf, sizeof(buf), "%s.width", prefix);
+ snprintf (num, sizeof(num), "%d", width);
+ err = hdf_set_value (cgi->hdf, buf, num);
+ if (err != STATUS_OK) return nerr_pass(err);
+ snprintf (buf, sizeof(buf), "%s.height", prefix);
+ snprintf (num, sizeof(num), "%d", height);
+ err = hdf_set_value (cgi->hdf, buf, num);
+ if (err != STATUS_OK) return nerr_pass(err);
+ }
+ return STATUS_OK;
+}
+
+NEOERR *scale_images (CGI *cgi, char *prefix, int width, int height, int force)
+{
+ NEOERR *err;
+ char num[20];
+ HDF *obj;
+ int i, x;
+ int factor;
+
+ obj = hdf_get_obj (cgi->hdf, prefix);
+ if (obj) obj = hdf_obj_child (obj);
+ while (obj)
+ {
+ factor = 1;
+ i = hdf_get_int_value(obj, "height", -1);
+ if (i != -1)
+ {
+ x = i;
+ while (x > height)
+ {
+ /* factor = factor * 2;*/
+ factor++;
+ x = i / factor;
+ }
+ snprintf (num, sizeof(num), "%d", x);
+ err = hdf_set_value (obj, "height", num);
+ if (err != STATUS_OK) return nerr_pass (err);
+
+ i = hdf_get_int_value(obj, "width", -1);
+ if (i != -1)
+ {
+ i = i / factor;
+ snprintf (num, sizeof(num), "%d", i);
+ err = hdf_set_value (obj, "width", num);
+ if (err != STATUS_OK) return nerr_pass (err);
+ }
+ }
+ else
+ {
+ snprintf (num, sizeof(num), "%d", height);
+ err = hdf_set_value (obj, "height", num);
+ if (err != STATUS_OK) return nerr_pass (err);
+ snprintf (num, sizeof(num), "%d", width);
+ err = hdf_set_value (obj, "width", num);
+ if (err != STATUS_OK) return nerr_pass (err);
+ }
+ obj = hdf_obj_next(obj);
+ }
+ return STATUS_OK;
+}
+
+int alpha_sort(const void *a, const void *b)
+{
+ char **sa = (char **)a;
+ char **sb = (char **)b;
+
+ /* ne_warn("%s %s: %d", *sa, *sb, strcmp(*sa, *sb)); */
+
+ return strcmp(*sa, *sb);
+}
+
+NEOERR *dowork_picture (CGI *cgi, char *album, char *picture)
+{
+ NEOERR *err = STATUS_OK;
+ char *base, *name;
+ char path[_POSIX_PATH_MAX];
+ char buf[256];
+ char *enc_picture;
+ int i, x, factor, y;
+ int thumb_width, thumb_height;
+ int pic_width, pic_height;
+ ULIST *files = NULL;
+ char t_album[_POSIX_PATH_MAX];
+ char t_pic[_POSIX_PATH_MAX];
+ char nfile[_POSIX_PATH_MAX];
+ char *ch;
+ int rotate;
+
+ ch = strrchr(picture, '/');
+ if (ch != NULL)
+ {
+ *ch = '\0';
+ snprintf(t_album, sizeof(t_album), "%s/%s", album, picture);
+ *ch = '/';
+ strncpy(t_pic, ch+1, sizeof(t_pic));
+ picture = t_pic;
+ album = t_album;
+ }
+
+ base = hdf_get_value (cgi->hdf, "BASEDIR", NULL);
+ if (base == NULL)
+ {
+ cgi_error (cgi, "No BASEDIR in imd file");
+ return nerr_raise(CGIFinished, "Finished");
+ }
+
+ thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
+ thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
+ pic_width = hdf_get_int_value (cgi->hdf, "PictureWidth", 120);
+ pic_height = hdf_get_int_value (cgi->hdf, "PictureWidth", 90);
+
+ err = hdf_set_value (cgi->hdf, "Context", "picture");
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ snprintf (path, sizeof(path), "%s/%s", base, album);
+ rotate = hdf_get_int_value(cgi->hdf, "Query.rotate", 0);
+ if (rotate)
+ {
+ err = rotate_image(path, picture, rotate, nfile);
+ if (err) return nerr_pass(err);
+ picture = strrchr(nfile, '/') + 1;
+ }
+
+ err = hdf_set_buf (cgi->hdf, "Album", url_escape(album));
+ if (err != STATUS_OK) return nerr_pass(err);
+ err = hdf_set_value (cgi->hdf, "Album.Raw", album);
+ if (err != STATUS_OK) return nerr_pass(err);
+ enc_picture = url_escape(picture);
+ err = hdf_set_buf (cgi->hdf, "Picture", enc_picture);
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ err = load_images(path, &files, NULL, 0);
+ if (err != STATUS_OK) return nerr_pass(err);
+ err = uListSort(files, alpha_sort);
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ i = -1;
+ for (x = 0; x < uListLength(files); x++)
+ {
+ err = uListGet(files, x, (void *)&name);
+ if (err) break;
+ if (!strcmp(name, picture))
+ {
+ i = x;
+ break;
+ }
+ }
+ if (i != -1)
+ {
+ for (x = 2; x > 0; x--)
+ {
+ if (i - x < 0) continue;
+ err = uListGet(files, i-x, (void *)&name);
+ if (err) break;
+ snprintf(buf, sizeof(buf), "Show.%d", i-x);
+ err = export_image(cgi, buf, path, name);
+ if (err) break;
+ }
+ for (x = 0; x < 3; x++)
+ {
+ if (i + x > uListLength(files)) break;
+ err = uListGet(files, i+x, (void *)&name);
+ if (err) break;
+ snprintf(buf, sizeof(buf), "Show.%d", i+x);
+ err = export_image(cgi, buf, path, name);
+ if (err) break;
+ }
+ snprintf (buf, sizeof(buf), "Show.%d.width", i);
+ x = hdf_get_int_value (cgi->hdf, buf, -1);
+ if (x != -1)
+ {
+ factor = 1;
+ y = x;
+ while (y > pic_width)
+ {
+ /* factor = factor * 2; */
+ factor++;
+ y = x / factor;
+ }
+ snprintf (buf, sizeof(buf), "%d", y);
+ hdf_set_value (cgi->hdf, "Picture.width", buf);
+ snprintf (buf, sizeof(buf), "Show.%d.height", i);
+ x = hdf_get_int_value (cgi->hdf, buf, -1);
+ y = x / factor;
+ snprintf (buf, sizeof(buf), "%d", y);
+ hdf_set_value (cgi->hdf, "Picture.height", buf);
+ }
+ else
+ {
+ snprintf (buf, sizeof(buf), "%d", pic_width);
+ hdf_set_value (cgi->hdf, "Picture.width", buf);
+ snprintf (buf, sizeof(buf), "%d", pic_height);
+ hdf_set_value (cgi->hdf, "Picture.height", buf);
+ }
+
+ err = scale_images (cgi, "Show", thumb_width, thumb_height, 0);
+ }
+ uListDestroy(&files, ULIST_FREE);
+
+ return nerr_pass(err);
+}
+
+NEOERR *dowork_album_overview (CGI *cgi, char *album)
+{
+ NEOERR *err = STATUS_OK;
+ DIR *dp;
+ struct dirent *de;
+ char path[_POSIX_PATH_MAX];
+ char buf[256];
+ int i = 0, x;
+ int thumb_width, thumb_height;
+ ULIST *files = NULL;
+ char *name;
+
+ thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
+ thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
+
+ if ((dp = opendir (album)) == NULL)
+ {
+ return nerr_raise(NERR_IO, "Unable to opendir %s: [%d] %s", album, errno,
+ strerror(errno));
+ }
+
+ while ((de = readdir (dp)) != NULL)
+ {
+ if (de->d_name[0] != '.')
+ {
+ snprintf(path, sizeof(path), "%s/%s", album, de->d_name);
+ if (isdir(path))
+ {
+ snprintf(buf, sizeof(buf), "Albums.%d", i);
+ err = hdf_set_buf (cgi->hdf, buf, url_escape(de->d_name));
+ if (err != STATUS_OK) break;
+ err = load_images(path, &files, NULL, 1);
+ if (err != STATUS_OK) break;
+ err = uListSort(files, alpha_sort);
+ if (err != STATUS_OK) break;
+ snprintf(buf, sizeof(buf), "Albums.%d.Count", i);
+ err = hdf_set_int_value(cgi->hdf, buf, uListLength(files));
+ if (err != STATUS_OK) break;
+ for (x = 0; (x < 4) && (x < uListLength(files)); x++)
+ {
+ err = uListGet(files, x, (void *)&name);
+ if (err) break;
+ snprintf(buf, sizeof(buf), "Albums.%d.Images.%d", i, x);
+ err = export_image(cgi, buf, path, name);
+ if (err) break;
+ }
+ uListDestroy(&files, ULIST_FREE);
+ if (err != STATUS_OK) break;
+ snprintf(buf, sizeof(buf), "Albums.%d.Images", i);
+ err = scale_images (cgi, buf, thumb_width, thumb_height, 0);
+ if (err != STATUS_OK) break;
+ i++;
+ }
+ }
+ }
+ closedir(dp);
+ return nerr_pass(err);
+}
+
+NEOERR *dowork_album (CGI *cgi, char *album)
+{
+ NEOERR *err;
+ char *base;
+ char buf[256];
+ char path[_POSIX_PATH_MAX];
+ int thumb_width, thumb_height;
+ int per_page, start, next, prev, last;
+ ULIST *files = NULL;
+ char *name;
+ int x;
+
+ base = hdf_get_value (cgi->hdf, "BASEDIR", NULL);
+ if (base == NULL)
+ {
+ cgi_error (cgi, "No BASEDIR in imd file");
+ return nerr_raise(CGIFinished, "Finished");
+ }
+ thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
+ thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
+ per_page = hdf_get_int_value (cgi->hdf, "PerPage", 50);
+ start = hdf_get_int_value (cgi->hdf, "Query.start", 0);
+
+ err = hdf_set_buf (cgi->hdf, "Album", url_escape(album));
+ if (err != STATUS_OK) return nerr_pass(err);
+ err = hdf_set_value (cgi->hdf, "Album.Raw", album);
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ err = hdf_set_value (cgi->hdf, "Context", "album");
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ snprintf (path, sizeof(path), "%s/%s", base, album);
+ err = dowork_album_overview(cgi, path);
+ if (err != STATUS_OK) return nerr_pass(err);
+
+ err = load_images(path, &files, NULL, 0);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = uListSort(files, alpha_sort);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = hdf_set_int_value(cgi->hdf, "Album.Count", uListLength(files));
+ if (err != STATUS_OK) return nerr_pass (err);
+ if (start > uListLength(files)) start = 0;
+ next = start + per_page;
+ if (next > uListLength(files)) next = uListLength(files);
+ prev = start - per_page;
+ if (prev < 0) prev = 0;
+ last = uListLength(files) - per_page;
+ if (last < 0) last = 0;
+ err = hdf_set_int_value(cgi->hdf, "Album.Start", start);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = hdf_set_int_value(cgi->hdf, "Album.Next", next);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = hdf_set_int_value(cgi->hdf, "Album.Prev", prev);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = hdf_set_int_value(cgi->hdf, "Album.Last", last);
+ if (err != STATUS_OK) return nerr_pass (err);
+ for (x = start; x < next; x++)
+ {
+ err = uListGet(files, x, (void *)&name);
+ if (err) break;
+ snprintf(buf, sizeof(buf), "Images.%d", x);
+ err = export_image(cgi, buf, path, name);
+ if (err) break;
+ }
+ uListDestroy(&files, ULIST_FREE);
+ if (err != STATUS_OK) return nerr_pass (err);
+ err = scale_images (cgi, "Images", thumb_width, thumb_height, 0);
+ if (err != STATUS_OK) return nerr_pass (err);
+ return STATUS_OK;
+}
+
+NEOERR *dowork_image (CGI *cgi, char *image)
+{
+ NEOERR *err = STATUS_OK;
+ int maxW = 1024, maxH = 1024;
+ char *basepath = "";
+ char *cache_basepath = "/tmp/.imgcache/";
+ char srcpath[_POSIX_PATH_MAX] = "";
+ char cachepath[_POSIX_PATH_MAX] = "";
+ char buf[256];
+ char *if_mod;
+ int i, l, quality;
+ struct stat s;
+ struct tm *t;
+
+ if ((i = hdf_get_int_value(cgi->hdf, "Query.width", 0)) != 0) {
+ maxW = i;
+ }
+
+ if ((i = hdf_get_int_value(cgi->hdf, "Query.height", 0)) != 0) {
+ maxH = i;
+ }
+ quality = hdf_get_int_value(cgi->hdf, "Query.quality", 0);
+
+ if_mod = hdf_get_value(cgi->hdf, "HTTP.IfModifiedSince", NULL);
+
+ basepath = hdf_get_value(cgi->hdf, "BASEDIR", NULL);
+ if (basepath == NULL)
+ {
+ cgi_error (cgi, "No BASEDIR in imd file");
+ return nerr_raise(CGIFinished, "Finished");
+ }
+
+ snprintf (srcpath, sizeof(srcpath), "%s/%s", basepath, image);
+ snprintf (cachepath, sizeof(cachepath), "%s/%dx%d/%s", cache_basepath,
+ maxW, maxH,image);
+
+ if (stat(srcpath, &s))
+ {
+ cgiwrap_writef("Status: 404\nContent-Type: text/html\n\n");
+ cgiwrap_writef("File %s not found.", srcpath);
+ return nerr_raise_errno(NERR_IO, "Unable to stat file %s", srcpath);
+ }
+
+ t = gmtime(&(s.st_mtime));
+ if (if_mod && later_than(t, if_mod))
+ {
+ cgiwrap_writef("Status: 304\nContent-Type: text/html\n\n");
+ cgiwrap_writef("Use Local Copy");
+ return STATUS_OK;
+ }
+
+ /* fprintf(stderr,"cachepath: %s\n",cachepath); */
+
+ l = strlen(srcpath);
+ if ((l>4 && !strcasecmp(srcpath+l-4, ".jpg")) ||
+ (l>5 && !strcasecmp(srcpath+l-5, ".jpeg")))
+ cgiwrap_writef("Content-Type: image/jpeg\n");
+ else if (l>4 && !strcasecmp(srcpath+l-4, ".gif"))
+ cgiwrap_writef("Content-Type: image/gif\n");
+ t = gmtime(&(s.st_mtime));
+ strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", t);
+ cgiwrap_writef("Last-modified: %s\n\n", buf);
+
+ fflush(stdout);
+
+ err = scale_and_display_image(srcpath,maxW,maxH,cachepath,quality);
+ return nerr_pass(err);
+}
+
+int main(int argc, char **argv, char **envp)
+{
+ NEOERR *err;
+ CGI *cgi;
+ char *image;
+ char *album;
+ char *imd_file;
+ char *cs_file;
+ char *picture;
+
+ cgi_debug_init (argc,argv);
+ cgiwrap_init_std (argc, argv, envp);
+
+ nerr_init();
+
+ err = cgi_init(&cgi, NULL);
+ if (err != STATUS_OK)
+ {
+ cgi_neo_error(cgi, err);
+ nerr_log_error(err);
+ return -1;
+ }
+ imd_file = hdf_get_value(cgi->hdf, "CGI.PathTranslated", NULL);
+ err = hdf_read_file (cgi->hdf, imd_file);
+ if (err != STATUS_OK)
+ {
+ cgi_neo_error(cgi, err);
+ nerr_log_error(err);
+ return -1;
+ }
+
+ cs_file = hdf_get_value(cgi->hdf, "Template", NULL);
+ image = hdf_get_value(cgi->hdf, "Query.image", NULL);
+ album = hdf_get_value(cgi->hdf, "Query.album", "");
+ picture = hdf_get_value(cgi->hdf, "Query.picture", NULL);
+ if (image)
+ {
+ err = dowork_image(cgi, image);
+ if (err)
+ {
+ nerr_log_error(err);
+ return -1;
+ }
+ }
+ else
+ {
+ if (!picture)
+ {
+ err = dowork_album (cgi, album);
+ }
+ else
+ {
+ err = dowork_picture (cgi, album, picture);
+ }
+ if (err != STATUS_OK)
+ {
+ if (nerr_handle(&err, CGIFinished))
+ {
+ /* pass */
+ }
+ }
+ else
+ {
+ err = cgi_display(cgi, cs_file);
+ if (err != STATUS_OK)
+ {
+ cgi_neo_error(cgi, err);
+ nerr_log_error(err);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
diff -Nbru clearsilver-0.4/imd/imd.cs clearsilver-0.5/imd/imd.cs
--- clearsilver-0.4/imd/imd.cs Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/imd/imd.cs Mon Feb 11 12:16:23 2002
@@ -0,0 +1,195 @@
+
+
+
+
+
+ - of
+-
+
+
+
+
+
+
+
+
+
+ |
+ ( images)
+ |
+
+
+ |
+
+ |
+
+
+
+
+
+
+
+
+
+ #0 ?>
+
First
+
+ First
+
+
+ #0 ?>
+
Prev
+
+ Prev
+
+
+ - of
+
+
+
Next
+
+ Next
+
+
+
+
Last
+
+ Last
+
+
+
+
+
+
+ #0 ?>
+
First
+
+ First
+
+
+ #0 ?>
+
Prev
+
+ Prev
+
+
+ - of
+
+
+
Next
+
+ Next
+
+
+
+
Last
+
+ Last
+
+
+
+
+
+ --
+
+
+
+
+  |
+ src="1.gif"> |
+  |
+
+
+ width=18 src="3.gif"> |
+ height= src="?image=/&width=&height=&quality=1"> |
+ width=18 src="4.gif"> |
+
+
+  |
+ src="6.gif"> |
+  |
+
+
+
+
+
+
+ Rotate:
+ Right -
+ Left -
+ Flip
+
+
+
+
diff -Nbru clearsilver-0.4/imd/imdm.py clearsilver-0.5/imd/imdm.py
--- clearsilver-0.4/imd/imdm.py Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/imd/imdm.py Sat Dec 30 01:57:16 2000
@@ -0,0 +1,209 @@
+#!/usr/local/bin/python
+#
+# imdm
+#
+# IMage Display Master
+#
+# This uses the affiliated C-cgi "imd" to build a caching image display
+# server with only passive Apache cgis.
+#
+import sys,os,string
+import cgi
+
+# this function should find the first four images inside a
+# nested subdirectory
+
+albumstartfile = "/~jeske/Images/jeskealbum.imd"
+imagestartfile = "/~jeske/Images/jeskealbum.imc"
+
+THUMB_WIDTH = 120
+THUMB_HEIGHT = 90
+
+# ------------------------------------------------------------------------------------
+#
+# utility functions
+
+def albumoverview(basedir,sub_dir,count = 4,skip = 0):
+ images = []
+
+ fulldir = os.path.join(basedir,sub_dir)
+ for a_entry in os.listdir(fulldir):
+ fullpath = os.path.join(fulldir,a_entry)
+ if os.path.isfile(fullpath):
+ if string.lower(string.split(a_entry,".")[-1]) in ["jpeg","jpg"]:
+ images.append(os.path.join(sub_dir,a_entry))
+ elif os.path.isdir(fullpath):
+ images + albumoverview(basedir,os.path.join(sub_dir,a_entry),1)
+ if len(images) >= (count + skip):
+ return images[skip:]
+
+ return images[skip:]
+
+
+def makethumbnailimgtag(filename,width=THUMB_WIDTH,height=THUMB_HEIGHT):
+ global imagestartfile
+ return '
' % (imagestartfile,filename,width,height)
+
+def makealbumurl(dir):
+ global albumstartfile
+ return "%s?album=%s" % (albumstartfile,dir)
+
+def makepictureurl(dir,picture):
+ global albumstartfile
+ return "%s?album=%s&picture=%s" % (albumstartfile,dir,picture)
+
+# ------------------------------------------------------------------------------------
+#
+# picturedisplay
+
+def picturedisplay(basedir,album,picture):
+ sys.stdout.write("top " % albumstartfile)
+
+ sys.stdout.write("-- %s" % (makealbumurl(album),album))
+
+ imagename = os.path.join(album,picture)
+
+ sys.stdout.write("
")
+
+ sys.stdout.write("| \n")
+ sys.stdout.write(makethumbnailimgtag(imagename,width=600,height=500))
+ sys.stdout.write(" |
\n")
+
+ images = albumoverview(basedir,album,count=500)
+ image_index = None
+ for x in range(len(images)):
+ if images[x] == imagename:
+ image_index = x
+ break
+
+ if not image_index is None:
+ sys.stdout.write("")
+
+ # pre-images
+ for i in range(1,3):
+ pic_index = image_index - i
+
+ picture_path = string.join(string.split(images[pic_index],'/')[1:],'/')
+ sys.stdout.write("| %s | " % (makepictureurl(album,picture_path),makethumbnailimgtag(images[pic_index])))
+
+ sys.stdout.write("
")
+
+ # post-images
+ for i in range(1,3):
+ pic_index = image_index + i
+ if pic_index >= len(images):
+ pic_index = pic_index - len(images)
+
+ picture_path = string.join(string.split(images[pic_index],'/')[1:],'/')
+ sys.stdout.write("%s | " % (makepictureurl(album,picture_path), makethumbnailimgtag(images[pic_index])))
+ sys.stdout.write("
\n")
+
+ # navigation
+
+
+# ------------------------------------------------------------------------------------
+#
+# albumdisplay
+
+
+
+def albumdisplay(basedir,album,columns=7,rows=5):
+ next_page = 0
+
+
+ sys.stdout.write("" % album)
+
+ imgcount = columns * rows
+ images = albumoverview(basedir,album,count=(imgcount + 1),skip=0)
+
+ if len(images) > imgcount:
+ images = images[:-1]
+ next_page = 1
+
+ while images:
+ sys.stdout.write("")
+ for a_col in range(columns):
+ if len(images):
+ picture_path = string.join(string.split(images[0],'/')[1:],'/')
+ sys.stdout.write("| %s | " % (makepictureurl(album,picture_path),makethumbnailimgtag(images[0])))
+ images = images[1:]
+ sys.stdout.write("
")
+
+ if next_page:
+ sys.stdout.write("more...")
+
+
+# ------------------------------------------------------------------------------------
+#
+# topalbumoverview
+
+def topalbumoverview(dir):
+ for a_dir in os.listdir(dir):
+ if os.path.isdir(os.path.join(dir,a_dir)):
+ sys.stdout.write("")
+ sys.stdout.write("")
+
+ sys.stdout.write("| %s |
" % (makealbumurl(a_dir),a_dir))
+
+ sys.stdout.write("")
+
+ for a_file in albumoverview(dir,a_dir):
+ picture_path = string.join(string.split(a_file,'/')[1:],'/')
+ sys.stdout.write("| %s | \n" % (makepictureurl(a_dir,picture_path),makethumbnailimgtag(a_file)))
+ sys.stdout.write("
|
\n\n")
+
+# ------------------------------------------------------------------------------------
+#
+# readvars() -- simple file format reader
+
+def readvars(filename):
+ vars = {}
+ data = open(filename,"rb").read()
+ lines = string.split(data,"\n")
+ for a_line in lines:
+ stripped_line = string.strip(a_line)
+ if not stripped_line or stripped_line[0] == "#":
+ continue
+ try:
+ key,value = string.split(a_line,"=")
+ vars[key] = value
+ except:
+ pass
+ return vars
+
+# ------------------------------------------------------------------------------------
+#
+# main()
+
+
+def main():
+ global cgiform
+ cgiform = cgi.FieldStorage()
+
+ sys.stdout.write("Content-Type: text/html\n\n")
+ sys.stdout.write("
HTML Image Viewer!
")
+
+ myvars = readvars(os.environ['PATH_TRANSLATED'])
+
+ sys.stderr.write(repr(myvars))
+
+ global albumstartfile, imagestartfile
+ albumstartfile = os.environ['PATH_INFO']
+ imagestartfile = myvars['IMGSTARTFILE']
+ BASEDIR = myvars['BASEDIR']
+
+ album = cgiform.getvalue('album',None)
+ picture = cgiform.getvalue('picture',None)
+
+ if album is None:
+ topalbumoverview(BASEDIR)
+ elif picture is None:
+ albumdisplay(BASEDIR,album)
+ else:
+ picturedisplay(BASEDIR,album,picture)
+
+if __name__ == "__main__":
+ main()
+
+
+
diff -Nbru clearsilver-0.4/imd/test.in clearsilver-0.5/imd/test.in
--- clearsilver-0.4/imd/test.in Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/imd/test.in Sat Dec 30 01:57:16 2000
@@ -0,0 +1,2 @@
+PATH_TRANSLATED=/home/blong/public_html/Images/test.imd
+QUERY_STRING=
diff -Nbru clearsilver-0.4/python/Makefile clearsilver-0.5/python/Makefile
--- clearsilver-0.4/python/Makefile Mon Aug 6 15:16:45 2001
+++ clearsilver-0.5/python/Makefile Fri Mar 22 11:26:41 2002
@@ -13,6 +13,7 @@
ifeq ($(PYTHON_INC),)
PYTHON_INC = -I/usr/include/python1.5
endif
+PYTHON_INC += -I/usr/include/python1.5
CFLAGS += -I$(NEOTONIC_ROOT) $(PYTHON_INC)
DLIBS += -lneo_cgi -lneo_cs -lneo_utl
diff -Nbru clearsilver-0.4/python/neo_cgi.c clearsilver-0.5/python/neo_cgi.c
--- clearsilver-0.4/python/neo_cgi.c Fri Aug 31 15:19:48 2001
+++ clearsilver-0.5/python/neo_cgi.c Sat Apr 13 17:49:50 2002
@@ -18,6 +18,8 @@
#include "cgi/cgiwrap.h"
#include "cgi/date.h"
#include "cgi/html.h"
+
+#define NEO_CGI_MODULE
#include "p_neo_util.h"
static PyObject *CGIFinishedException;
@@ -283,7 +285,7 @@
char *name, *domain = NULL, *path = NULL;
NEOERR *err;
- if (!PyArg_ParseTuple(args, "s|ss:cookieClear(name, domain, path)", &name, domain, path))
+ if (!PyArg_ParseTuple(args, "s|ss:cookieClear(name, domain, path)", &name, &domain, &path))
return NULL;
err = cgi_cookie_clear (cgi, name, domain, path);
@@ -307,7 +309,7 @@
Py_INCREF(Py_None);
return Py_None;
}
- return PyFile_FromFile (fp, "name", "w+", NULL);
+ return PyFile_FromFile (fp, name, "w+", NULL);
}
static PyMethodDef CGIMethods[] =
@@ -331,20 +333,37 @@
static PyObject * p_cgi_url_escape (PyObject *self, PyObject *args)
{
- char *s, *esc;
+ char *s, *esc, *o = NULL;
NEOERR *err;
PyObject *rv;
- if (!PyArg_ParseTuple(args, "s:urlEscape(str)", &s))
+ if (!PyArg_ParseTuple(args, "s|s:urlEscape(str, other=None)", &s, &o))
return NULL;
- err = cgi_url_escape (s, &esc);
+ err = cgi_url_escape_more (s, &esc, o);
if (err) return p_neo_error (err);
rv = Py_BuildValue ("s", esc);
free (esc);
return rv;
}
+static PyObject * p_cgi_url_unescape (PyObject *self, PyObject *args)
+{
+ char *s;
+ PyObject *rv;
+ char *r;
+
+ if (!PyArg_ParseTuple(args, "s:urlUnescape(str)", &s))
+ return NULL;
+
+ r = strdup(s);
+ if (r == NULL) return PyErr_NoMemory();
+ cgi_url_unescape (r);
+ rv = Py_BuildValue ("s", r);
+ free (r);
+ return rv;
+}
+
static PyObject * p_html_escape (PyObject *self, PyObject *args)
{
char *s, *esc;
@@ -523,15 +542,6 @@
PyErr_SetString(PyExc_TypeError,
"object.read() returned non-string");
}
- if (n < 0 && result != NULL) {
- int len = PyString_Size(result);
- if (len == 0) {
- Py_DECREF(result);
- result = NULL;
- PyErr_SetString(PyExc_EOFError,
- "EOF on object.read()");
- }
- }
return result;
}
}
@@ -547,7 +557,7 @@
if (buf == NULL)
{
PyErr_Clear();
- return 0;
+ return -1;
}
len = PyString_Size(buf);
@@ -609,7 +619,7 @@
items = PyObject_GetAttrString(wrap->p_env, "items");
if (items == NULL)
{
- /* ne_warn ("p_iterenv: Unable to get items method"); */
+ ne_warn ("p_iterenv: Unable to get items method");
PyErr_Clear();
return -1;
}
@@ -617,14 +627,21 @@
Py_DECREF(items);
if (env_list == NULL)
{
- /* ne_warn ("p_iterenv: Unable to call items method"); */
+ ne_warn ("p_iterenv: Unable to call items method");
PyErr_Clear();
return -1;
}
+ if (x >= PyList_Size(env_list))
+ {
+ *rk = NULL;
+ *rv = NULL;
+ Py_DECREF(env_list);
+ return 0;
+ }
result = PyList_GetItem (env_list, x);
if (result == NULL)
{
- /* ne_warn ("p_iterenv: Unable to get env %d", x); */
+ ne_warn ("p_iterenv: Unable to get env %d", x);
Py_DECREF(env_list);
PyErr_Clear();
return -1;
@@ -633,7 +650,7 @@
v = PyTuple_GetItem (result, 1);
if (k == NULL || v == NULL)
{
- /* ne_warn ("p_iterenv: Unable to get k,v %s,%s", k, v); */
+ ne_warn ("p_iterenv: Unable to get k,v %s,%s", k, v);
Py_DECREF(env_list);
PyErr_Clear();
return -1;
@@ -793,9 +810,6 @@
static PyObject * p_update (PyObject *self, PyObject *args)
{
- PyObject *dict;
- int i = 0;
-
if (_PyImport_FindExtension("neo_util","neo_util") == NULL)
initneo_util();
@@ -810,6 +824,7 @@
{
{"CGI", p_cgi_init, METH_VARARGS, NULL},
{"urlEscape", p_cgi_url_escape, METH_VARARGS, NULL},
+ {"urlUnescape", p_cgi_url_unescape, METH_VARARGS, NULL},
{"htmlEscape", p_html_escape, METH_VARARGS, NULL},
{"text2html", p_text_html, METH_VARARGS, NULL},
{"cgiWrap", cgiwrap, METH_VARARGS, cgiwrap_doc},
@@ -822,6 +837,8 @@
void initneo_cgi(void)
{
PyObject *m, *d;
+ static void *NEO_PYTHON_API[P_NEO_CGI_POINTERS];
+ PyObject *c_api_object;
initneo_util();
_PyImport_FixupExtension("neo_util", "neo_util");
@@ -834,4 +851,18 @@
d = PyModule_GetDict(m);
CGIFinishedException = PyErr_NewException("neo_cgi.CGIFinished", NULL, NULL);
PyDict_SetItemString(d, "CGIFinished", CGIFinishedException);
+
+ /* Initialize the C API Pointer array */
+ NEO_PYTHON_API[P_HDF_TO_OBJECT_NUM] = (void *)p_hdf_to_object;
+ NEO_PYTHON_API[P_OBJECT_TO_HDF_NUM] = (void *)p_object_to_hdf;
+ NEO_PYTHON_API[P_NEO_ERROR_NUM] = (void *)p_neo_error;
+
+ /* create a CObject containing the API pointer array's address */
+ c_api_object = PyCObject_FromVoidPtr((void *)NEO_PYTHON_API, NULL);
+ if (c_api_object != NULL) {
+ /* create a name for this object in the module's namespace */
+ PyDict_SetItemString(d, "_C_API", c_api_object);
+ Py_DECREF(c_api_object);
+ PyDict_SetItemString(d, "_C_API_NUM", PyInt_FromLong(P_NEO_CGI_POINTERS));
+ }
}
diff -Nbru clearsilver-0.4/python/neo_cs.c clearsilver-0.5/python/neo_cs.c
--- clearsilver-0.4/python/neo_cs.c Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/python/neo_cs.c Sat Apr 13 17:49:50 2002
@@ -14,6 +14,8 @@
#include "util/neo_str.h"
#include "util/neo_hdf.h"
#include "cs/cs.h"
+
+#define NEO_CGI_MODULE
#include "p_neo_util.h"
diff -Nbru clearsilver-0.4/python/neo_util.c clearsilver-0.5/python/neo_util.c
--- clearsilver-0.4/python/neo_util.c Tue Oct 23 00:01:35 2001
+++ clearsilver-0.5/python/neo_util.c Sat Apr 13 17:49:50 2002
@@ -14,15 +14,27 @@
#include "util/neo_str.h"
#include "util/neo_hdf.h"
+#define NEO_CGI_MODULE
+#include "p_neo_util.h"
+
static PyObject *NeoError;
+static PyObject *NeoParseError;
PyObject * p_neo_error (NEOERR *err)
{
STRING str;
string_init (&str);
+ if (nerr_match(err, NERR_PARSE))
+ {
nerr_error_string (err, &str);
+ PyErr_SetString (NeoParseError, str.buf);
+ }
+ else
+ {
+ nerr_error_traceback (err, &str);
PyErr_SetString (NeoError, str.buf);
+ }
string_clear (&str);
return NULL;
}
@@ -392,6 +404,25 @@
return rv;
}
+static PyObject * p_hdf_set_symlink (PyObject *self, PyObject *args)
+{
+ HDFObject *ho = (HDFObject *)self;
+ PyObject *rv;
+ char *src;
+ char *dest;
+ NEOERR *err;
+
+ if (!PyArg_ParseTuple(args, "ss:copy(src, dest)", &src, &dest))
+ return NULL;
+
+ err = hdf_set_symlink (ho->data, src, dest);
+ if (err) return p_neo_error(err);
+
+ rv = Py_None;
+ Py_INCREF(rv);
+ return rv;
+}
+
static PyMethodDef HDFMethods[] =
{
{"getIntValue", p_hdf_get_int_value, METH_VARARGS, NULL},
@@ -410,12 +441,56 @@
{"removeTree", p_hdf_remove_tree, METH_VARARGS, NULL},
{"dump", p_hdf_dump, METH_VARARGS, NULL},
{"copy", p_hdf_copy, METH_VARARGS, NULL},
+ {"setSymLink", p_hdf_set_symlink, METH_VARARGS, NULL},
{NULL, NULL}
};
+static PyObject * p_escape (PyObject *self, PyObject *args)
+{
+ PyObject *rv;
+ char *s;
+ char *escape;
+ char *esc_char;
+ int buflen;
+ char *ret = NULL;
+ NEOERR *err;
+
+ if (!PyArg_ParseTuple(args, "s#ss:escape(str, char, escape)", &s, &buflen, &esc_char, &escape))
+ return NULL;
+
+ err = neos_escape(s, buflen, esc_char[0], escape, &ret);
+ if (err) return p_neo_error(err);
+
+ rv = Py_BuildValue("s", ret);
+ free(ret);
+ return rv;
+}
+
+static PyObject * p_unescape (PyObject *self, PyObject *args)
+{
+ PyObject *rv;
+ char *s;
+ char *copy;
+ char *esc_char;
+ int buflen;
+
+ if (!PyArg_ParseTuple(args, "s#s:unescape(str, char)", &s, &buflen, &esc_char))
+ return NULL;
+
+ copy = strdup(s);
+ if (copy == NULL) return PyErr_NoMemory();
+ neos_unescape(copy, buflen, esc_char[0]);
+
+ rv = Py_BuildValue("s", copy);
+ free(copy);
+ return rv;
+}
+
static PyMethodDef UtilMethods[] =
{
{"HDF", p_hdf_init, METH_VARARGS, NULL},
+ {"escape", p_escape, METH_VARARGS, NULL},
+ {"unescape", p_unescape, METH_VARARGS, NULL},
{NULL, NULL}
};
@@ -430,6 +505,8 @@
m = Py_InitModule("neo_util", UtilMethods);
d = PyModule_GetDict(m);
- NeoError = PyErr_NewException("neo_util.error", NULL, NULL);
- PyDict_SetItemString(d, "error", NeoError);
+ NeoError = PyErr_NewException("neo_util.Error", NULL, NULL);
+ NeoParseError = PyErr_NewException("neo_util.ParseError", NULL, NULL);
+ PyDict_SetItemString(d, "Error", NeoError);
+ PyDict_SetItemString(d, "ParseError", NeoParseError);
}
diff -Nbru clearsilver-0.4/python/p_neo_util.h clearsilver-0.5/python/p_neo_util.h
--- clearsilver-0.4/python/p_neo_util.h Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/python/p_neo_util.h Sat Apr 13 17:49:51 2002
@@ -11,10 +11,66 @@
#ifndef __P_NEO_UTIL_H_
#define __P_NEO_UTIL_H_ 1
-PyObject * p_neo_error (NEOERR *err);
-PyObject * p_hdf_to_object (HDF *data, int dealloc);
-HDF * p_object_to_hdf (PyObject *ho);
+#include
+
+__BEGIN_DECLS
+
+/* external HDF object interface. */
+
+#define P_HDF_TO_OBJECT_NUM 0
+#define P_HDF_TO_OBJECT_RETURN PyObject *
+#define P_HDF_TO_OBJECT_PROTO (HDF *data, int dealloc)
+
+#define P_OBJECT_TO_HDF_NUM 1
+#define P_OBJECT_TO_HDF_RETURN HDF *
+#define P_OBJECT_TO_HDF_PROTO (PyObject *ho)
+
+#define P_NEO_ERROR_NUM 2
+#define P_NEO_ERROR_RETURN PyObject *
+#define P_NEO_ERROR_PROTO (NEOERR *err)
+
+#define P_NEO_CGI_POINTERS 3
+
+#ifdef NEO_CGI_MODULE
+P_HDF_TO_OBJECT_RETURN p_hdf_to_object P_HDF_TO_OBJECT_PROTO;
+P_OBJECT_TO_HDF_RETURN p_object_to_hdf P_OBJECT_TO_HDF_PROTO;
+P_NEO_ERROR_RETURN p_neo_error P_NEO_ERROR_PROTO;
+
+/* other functions */
+
void initneo_util(void);
void initneo_cs(void);
+
+#else
+static void **NEO_PYTHON_API;
+
+#define p_hdf_to_object \
+ (*(P_HDF_TO_OBJECT_RETURN (*)P_HDF_TO_OBJECT_PROTO) NEO_PYTHON_API[P_HDF_TO_OBJECT_NUM])
+
+#define p_object_to_hdf \
+ (*(P_OBJECT_TO_HDF_RETURN (*)P_OBJECT_TO_HDF_PROTO) NEO_PYTHON_API[P_OBJECT_TO_HDF_NUM])
+
+#define p_neo_error \
+ (*(P_NEO_ERROR_RETURN (*)P_NEO_ERROR_PROTO) NEO_PYTHON_API[P_NEO_ERROR_NUM])
+
+#define import_neo_cgi() \
+{ \
+ PyObject *module = PyImport_ImportModule("neo_cgi"); \
+ if (module != NULL) { \
+ PyObject *module_dict = PyModule_GetDict(module); \
+ PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \
+ PyObject *c_api_num_o = PyDict_GetItemString(module_dict, "_C_API_NUM"); \
+ if (PyInt_AsLong(c_api_num_o) < P_NEO_CGI_POINTERS) { \
+ PyErr_Format(PyExc_ImportError, "neo_cgi module doesn't match header compiled against, use of this module may cause a core dump: %ld < %ld", PyInt_AsLong(c_api_num_o), P_NEO_CGI_POINTERS); \
+ } \
+ if (PyCObject_Check(c_api_object)) { \
+ NEO_PYTHON_API = (void **)PyCObject_AsVoidPtr(c_api_object); \
+ } \
+ } \
+}
+
+#endif
+
+__END_DECLS
#endif /* __P_NEO_UTIL_H_ */
diff -Nbru clearsilver-0.4/rules.mk clearsilver-0.5/rules.mk
--- clearsilver-0.4/rules.mk Mon Aug 6 15:16:45 2001
+++ clearsilver-0.5/rules.mk Sat Apr 13 11:59:01 2002
@@ -14,18 +14,20 @@
## 2.7.7 instead
DB2_INC = -I$(HOME)/src/db-2.7.7/dist
DB2_LIB = -L$(HOME)/src/db-2.7.7/dist -ldb
-PYTHON_INC = -I/neo/opt/include/python2.1
+PYTHON_INC = -I/neo/opt/include/python2.1 -I/neo/opt/include/python2.2
## Programs
MKDIR = mkdir -p
RM = rm -f
CC = gcc
+CPP = g++
CFLAGS = -g -O2 -Wall -c -I$(NEOTONIC_ROOT) $(DB2_INC) -I/neo/opt/include
OUTPUT_OPTION = -o $@
LD = $(CC) -o
LDFLAGS = -L$(LIB_DIR)
-LDSHARED = $(CC) -shared -fPic
+LDSHARED = $(CC) -shared -fPi
+CPPLDSHARED = $(CPP) -shared -fPic
AR = $(MKDIR) $(LIB_DIR); ar -cr
DEP_LIBS = $(DLIBS:-l%=$(LIB_DIR)lib%.a)
@@ -40,7 +42,7 @@
.PHONY: depend
depend: Makefile.depends
-Makefile.depends:
+Makefile.depends: $(NEOTONIC_ROOT)/rules.mk Makefile
@echo "*******************************************"
@echo "** Building Dependencies "
@rm -f Makefile.depends
diff -Nbru clearsilver-0.4/util/Makefile clearsilver-0.5/util/Makefile
--- clearsilver-0.4/util/Makefile Mon Jun 25 04:24:40 2001
+++ clearsilver-0.5/util/Makefile Thu Feb 28 16:53:41 2002
@@ -7,8 +7,9 @@
include $(NEOTONIC_ROOT)rules.mk
UTL_LIB = $(LIB_DIR)libneo_utl.a
-UTL_SRC = neo_err.c neo_misc.c neo_test.c ulist.c neo_hdf.c neo_str.c \
- ulocks.c skiplist.c dict.c wdb.c neo_date.c rcfs.c
+UTL_SRC = neo_err.c neo_files.c neo_misc.c neo_test.c ulist.c neo_hdf.c \
+ neo_str.c ulocks.c skiplist.c dict.c wdb.c neo_date.c rcfs.c \
+ wildmat.c
UTL_OBJ = $(UTL_SRC:%.c=%.o)
TARGETS = $(UTL_LIB)
diff -Nbru clearsilver-0.4/util/neo_date.h clearsilver-0.5/util/neo_date.h
--- clearsilver-0.4/util/neo_date.h Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/neo_date.h Thu Apr 18 14:42:33 2002
@@ -11,10 +11,14 @@
#ifndef _NEO_DATE_H_
#define _NEO_DATE_H_ 1
+__BEGIN_DECLS
+
/* UTC time_t -> struct tm in local timezone */
void neo_time_expand (const time_t tt, char *timezone, struct tm *ttm);
/* local timezone struct tm -> time_t UTC */
time_t neo_time_compact (struct tm *ttm, char *timezone);
+
+__END_DECLS
#endif /* _NEO_DATE_H_ */
diff -Nbru clearsilver-0.4/util/neo_err.c clearsilver-0.5/util/neo_err.c
--- clearsilver-0.4/util/neo_err.c Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/neo_err.c Tue Mar 12 23:46:03 2002
@@ -226,6 +226,50 @@
{
NEOERR *more;
char buf[1024];
+ char *err_name;
+
+ if (err == STATUS_OK)
+ return;
+
+ if (err == INTERNAL_ERR)
+ {
+ string_append (str, "Internal error");
+ return;
+ }
+
+ more = err;
+ while (more && more != INTERNAL_ERR)
+ {
+ err = more;
+ more = err->next;
+ if (err->error != NERR_PASS)
+ {
+ NEOERR *r;
+ if (err->error == 0)
+ {
+ err_name = buf;
+ snprintf (buf, sizeof (buf), "Unknown Error");
+ }
+ else
+ {
+ r = uListGet (Errors, err->error - 1, (void *)&err_name);
+ if (r != STATUS_OK)
+ {
+ err_name = buf;
+ snprintf (buf, sizeof (buf), "Error %d", err->error);
+ }
+ }
+
+ string_appendf(str, "%s: %s", err_name, err->desc);
+ return;
+ }
+ }
+}
+
+void nerr_error_traceback (NEOERR *err, STRING *str)
+{
+ NEOERR *more;
+ char buf[1024];
char buf2[1024];
char *err_name;
@@ -289,33 +333,55 @@
int nerr_handle (NEOERR **err, int type)
{
- if (*err == STATUS_OK && (NEOERR *)type == STATUS_OK)
+ NEOERR *walk = *err;
+
+ while (walk != STATUS_OK && walk != INTERNAL_ERR)
+ {
+
+ if (walk->error == type)
+ {
+ _err_free(*err);
+ *err = STATUS_OK;
return 1;
- if (*err == STATUS_OK)
- return 0;
+ }
+ walk = walk->next;
+ }
- if (*err == INTERNAL_ERR && (NEOERR *)type == INTERNAL_ERR)
+ if (walk == STATUS_OK && (NEOERR *)type == STATUS_OK)
return 1;
- if (*err == INTERNAL_ERR)
+ if (walk == STATUS_OK)
return 0;
- if (((*err)->error == NERR_PASS) && (type != NERR_PASS))
- {
- int r = nerr_handle (&((*err)->next), type);
- if (r)
+ if (walk == INTERNAL_ERR && (NEOERR *)type == INTERNAL_ERR)
{
- _err_free (*err);
*err = STATUS_OK;
return 1;
}
- }
+ if (walk == INTERNAL_ERR)
+ return 0;
+
+ return 0;
+}
- if ((*err)->error == type)
+int nerr_match (NEOERR *err, int type)
+{
+ while (err != STATUS_OK && err != INTERNAL_ERR)
{
- _err_free (*err);
- *err = STATUS_OK;
+
+ if (err->error == type)
return 1;
+ err = err->next;
}
+
+ if (err == STATUS_OK && (NEOERR *)type == STATUS_OK)
+ return 1;
+ if (err == STATUS_OK)
+ return 0;
+
+ if (err == INTERNAL_ERR && (NEOERR *)type == INTERNAL_ERR)
+ return 1;
+ if (err == INTERNAL_ERR)
+ return 0;
return 0;
}
diff -Nbru clearsilver-0.4/util/neo_err.h clearsilver-0.5/util/neo_err.h
--- clearsilver-0.4/util/neo_err.h Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/neo_err.h Tue Mar 12 23:42:32 2002
@@ -111,6 +111,7 @@
#include "neo_str.h"
void nerr_error_string (NEOERR *err, STRING *str);
+void nerr_error_traceback (NEOERR *err, STRING *str);
/* function: nerr_ignore
* description: you should only call this if you actually handle the
@@ -123,6 +124,7 @@
NEOERR *nerr_init (void);
int nerr_handle (NEOERR **err, NERR_TYPE type);
+int nerr_match (NEOERR *err, NERR_TYPE type);
__END_DECLS
diff -Nbru clearsilver-0.4/util/neo_files.c clearsilver-0.5/util/neo_files.c
--- clearsilver-0.4/util/neo_files.c Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/neo_files.c Thu Feb 28 16:53:41 2002
@@ -0,0 +1,237 @@
+/*
+ * Neotonic ClearSilver Templating System
+ *
+ * This code is made available under the terms of the
+ * Neotonic ClearSilver License.
+ * http://www.neotonic.com/clearsilver/license.hdf
+ *
+ * Copyright (C) 2001 by Brandon Long
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "neo_err.h"
+#include "neo_misc.h"
+#include "neo_files.h"
+#include "wildmat.h"
+
+NEOERR *ne_mkdirs (char *path, mode_t mode)
+{
+ char mypath[_POSIX_PATH_MAX];
+ int x;
+ int r;
+
+ strncpy (mypath, path, sizeof(mypath));
+ x = strlen(mypath);
+ if ((x < sizeof(mypath)) && (mypath[x-1] != '/'))
+ {
+ mypath[x] = '/';
+ mypath[x+1] = '\0';
+ }
+
+ for (x = 1; mypath[x]; x++)
+ {
+ if (mypath[x] == '/')
+ {
+ mypath[x] = '\0';
+ r = mkdir (mypath, mode);
+ if (r == -1 && errno != EEXIST)
+ {
+ return nerr_raise_errno(NERR_SYSTEM, "ne_mkdirs: mkdir(%s, %x) failed", mypath, mode);
+ }
+ mypath[x] = '/';
+ }
+ }
+ return STATUS_OK;
+}
+
+NEOERR *ne_load_file (char *path, char **str)
+{
+ struct stat s;
+ int fd;
+ int len;
+
+ *str = NULL;
+
+ if (stat(path, &s) == -1)
+ {
+ if (errno == ENOENT)
+ return nerr_raise (NERR_NOT_FOUND, "File %s not found", path);
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path);
+ }
+
+ fd = open (path, O_RDONLY);
+ if (fd == -1)
+ {
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to open file %s", path);
+ }
+ len = s.st_size;
+ *str = (char *) malloc (len + 1);
+
+ if (*str == NULL)
+ {
+ close(fd);
+ return nerr_raise (NERR_NOMEM,
+ "Unable to allocate memory (%d) to load file %s", s.st_size, path);
+ }
+ if (read (fd, *str, len) == -1)
+ {
+ close(fd);
+ free(*str);
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to read file %s", path);
+ }
+ (*str)[len] = '\0';
+ close(fd);
+
+ return STATUS_OK;
+}
+
+NEOERR *ne_save_file (char *path, char *str)
+{
+ NEOERR *err;
+ int fd;
+ int w, l;
+
+ fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (fd == -1)
+ {
+ return nerr_raise_errno (NERR_IO, "Unable to create file %s", path);
+ }
+ l = strlen(str);
+ w = write (fd, str, l);
+ if (w != l)
+ {
+ err = nerr_raise_errno (NERR_IO, "Unable to write file %s", path);
+ close (fd);
+ return err;
+ }
+ close (fd);
+
+ return STATUS_OK;
+}
+
+NEOERR *ne_remove_dir (char *path)
+{
+ NEOERR *err;
+ DIR *dp;
+ struct stat s;
+ struct dirent *de;
+ char npath[_POSIX_PATH_MAX];
+
+ if (stat(path, &s) == -1)
+ {
+ if (errno == ENOENT) return STATUS_OK;
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path);
+ }
+ if (!S_ISDIR(s.st_mode))
+ {
+ return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path);
+ }
+ dp = opendir(path);
+ if (dp == NULL)
+ return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path);
+ while ((de = readdir (dp)) != NULL)
+ {
+ if (strcmp(de->d_name, ".") && strcmp(de->d_name, ".."))
+ {
+ snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name);
+ if (stat(npath, &s) == -1)
+ {
+ if (errno == ENOENT) continue;
+ closedir(dp);
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath);
+ }
+ if (S_ISDIR(s.st_mode))
+ {
+ err = ne_remove_dir(npath);
+ if (err) break;
+ }
+ else
+ {
+ if (unlink(npath) == -1)
+ {
+ if (errno == ENOENT) continue;
+ closedir(dp);
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s",
+ npath);
+ }
+ }
+ }
+ }
+ closedir(dp);
+ if (rmdir(path) == -1)
+ {
+ return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path);
+ }
+ return STATUS_OK;
+}
+
+NEOERR *ne_listdir(char *path, ULIST **files)
+{
+ return nerr_pass(ne_listdir_fmatch(path, files, NULL, NULL));
+}
+
+static int _glob_match(void *rock, char *filename)
+{
+ return wildmat(filename, rock);
+}
+
+NEOERR *ne_listdir_match(char *path, ULIST **files, char *match)
+{
+ return nerr_pass(ne_listdir_fmatch(path, files, _glob_match, match));
+}
+
+NEOERR *ne_listdir_fmatch(char *path, ULIST **files, MATCH_FUNC fmatch, void *rock)
+{
+ DIR *dp;
+ struct dirent *de;
+ ULIST *myfiles = NULL;
+ NEOERR *err = STATUS_OK;
+
+ if (files == NULL)
+ return nerr_raise(NERR_ASSERT, "Invalid call to ne_listdir_fmatch");
+
+ if (*files == NULL)
+ {
+ err = uListInit(&myfiles, 10, 0);
+ if (err) return nerr_pass(err);
+ }
+ else
+ {
+ myfiles = *files;
+ }
+
+ if ((dp = opendir (path)) == NULL)
+ {
+ return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path);
+ }
+ while ((de = readdir (dp)) != NULL)
+ {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+
+ if (fmatch != NULL && !fmatch(rock, de->d_name))
+ continue;
+
+ err = uListAppend(myfiles, strdup(de->d_name));
+ if (err) break;
+ }
+ closedir(dp);
+ if (err && *files == NULL)
+ {
+ uListDestroy(&myfiles, ULIST_FREE);
+ }
+ else if (*files == NULL)
+ {
+ *files = myfiles;
+ }
+ return nerr_pass(err);
+}
diff -Nbru clearsilver-0.4/util/neo_files.h clearsilver-0.5/util/neo_files.h
--- clearsilver-0.4/util/neo_files.h Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/neo_files.h Thu Feb 28 16:53:41 2002
@@ -0,0 +1,32 @@
+/*
+ * Neotonic ClearSilver Templating System
+ *
+ * This code is made available under the terms of the
+ * Neotonic ClearSilver License.
+ * http://www.neotonic.com/clearsilver/license.hdf
+ *
+ * Copyright (C) 2001 by Brandon Long
+ */
+
+#ifndef __NEO_FILES_H_
+#define __NEO_FILES_H_ 1
+
+__BEGIN_DECLS
+
+#include
+#include
+#include "util/ulist.h"
+
+typedef int (* MATCH_FUNC)(void *rock, char *filename);
+
+NEOERR *ne_mkdirs (char *path, mode_t mode);
+NEOERR *ne_load_file (char *path, char **str);
+NEOERR *ne_save_file (char *path, char *str);
+NEOERR *ne_remove_dir (char *path);
+NEOERR *ne_listdir(char *path, ULIST **files);
+NEOERR *ne_listdir_match(char *path, ULIST **files, char *match);
+NEOERR *ne_listdir_fmatch(char *path, ULIST **files, MATCH_FUNC fmatch, void *rock);
+
+__END_DECLS
+
+#endif /* __NEO_FILES_H_ */
diff -Nbru clearsilver-0.4/util/neo_hdf.c clearsilver-0.5/util/neo_hdf.c
--- clearsilver-0.4/util/neo_hdf.c Wed Oct 10 17:26:13 2001
+++ clearsilver-0.5/util/neo_hdf.c Thu Apr 18 12:24:53 2002
@@ -19,6 +19,7 @@
#include "neo_err.h"
#include "neo_hdf.h"
#include "neo_str.h"
+#include "ulist.h"
static NEOERR *_alloc_hdf (HDF **hdf, char *name, size_t nlen, char *value,
int dup, int wf, HDF *top)
@@ -131,6 +132,11 @@
*node = NULL;
if (hdf == NULL) return -1;
+ if (name == NULL || name[0] == '\0')
+ {
+ *node = hdf;
+ return 0;
+ }
if (hdf->link)
{
@@ -448,6 +454,66 @@
return nerr_raise (NERR_NOT_FOUND, "Unable to find %s", src);
}
+/* grody bubble sort from Wheeler, but sorting a singly linked list
+ * is annoying */
+void hdf_sort_obj_bubble(HDF *h, int (*compareFunc)(HDF *, HDF *))
+{
+ HDF *p, *c = hdf_obj_child(h);
+ HDF *prev;
+ int swapped;
+
+ do {
+ swapped = 0;
+ for (p = c, prev = c; p && p->next; prev = p, p = p->next) {
+ if (compareFunc(p, p->next) > 0) {
+ HDF *tmp = p->next;
+ prev->next = tmp;
+ p->next = tmp->next;
+ tmp->next = p;
+ p = tmp;
+ swapped = 1;
+ }
+ }
+ } while (swapped);
+}
+
+/* Ok, this version avoids the bubble sort by walking the level once to
+ * load them all into a ULIST, qsort'ing the list, and then dumping them
+ * back out... */
+NEOERR *hdf_sort_obj (HDF *h, int (*compareFunc)(const void *, const void *))
+{
+ NEOERR *err = STATUS_OK;
+ ULIST *level = NULL;
+ HDF *p, *c;
+ int x;
+
+ if (h == NULL) return STATUS_OK;
+ c = h->child;
+ if (c == NULL) return STATUS_OK;
+
+ do {
+ err = uListInit(&level, 40, 0);
+ if (err) return nerr_pass(err);
+ for (p = c; p; p = p->next) {
+ err = uListAppend(level, p);
+ if (err) break;
+ }
+ err = uListSort(level, compareFunc);
+ if (err) break;
+ uListGet(level, 0, (void **)&c);
+ h->child = c;
+ for (x = 1; x < uListLength(level); x++)
+ {
+ uListGet(level, x, (void **)&p);
+ c->next = p;
+ p->next = NULL;
+ c = p;
+ }
+ } while (0);
+ uListDestroy(&level, 0);
+ return nerr_pass(err);
+}
+
NEOERR* hdf_remove_tree (HDF *hdf, char *name)
{
HDF *hp = hdf;
@@ -464,6 +530,9 @@
return STATUS_OK;
}
+ lp = hdf;
+ ln = NULL;
+
n = name;
s = strchr (n, '.');
x = (s == NULL) ? strlen(n) : s - n;
@@ -932,19 +1001,37 @@
return nerr_pass (_hdf_read_string (hdf, &str, &line));
}
+static int count_newlines (char *s)
+{
+ int i = 0;
+ char *n = s;
+
+ n = strchr(s, '\n');
+ while (n != NULL)
+ {
+ i++;
+ n = strchr(n+1, '\n');
+ }
+ return i;
+}
+
static NEOERR* hdf_read_file_fp (HDF *hdf, FILE *fp, char *path, int *line)
{
NEOERR *err;
+ STRING str;
HDF *lower;
char buf[4096];
char *s;
char *name, *value;
int l;
- while (fgets(buf, sizeof(buf), fp) != NULL)
+ string_init(&str);
+ err = string_readline(&str, fp);
+ if (err) return nerr_pass(err);
+ while (str.len != 0)
{
(*line)++;
- s = buf;
+ s = str.buf;
SKIPWS(s);
if (!strncmp(s, "#include ", 9))
{
@@ -1048,7 +1135,7 @@
path, *line, name);
while (fgets(m+msize, mmax-msize, fp) != NULL)
{
- if (!strncmp(value, m+msize, l) && isspace(m[msize+l]))
+ if (!strncmp(value, m+msize, l) && (m[msize+l] == '\r' || m[msize+l] == '\n'))
{
m[msize] = '\0';
break;
@@ -1070,7 +1157,8 @@
free (m);
return nerr_pass_ctx(err, "In file %s:%d", path, *line);
}
-
+ /* count the newlines so we know what line we're on... +1 for EOM */
+ (*line) = (*line) + count_newlines(m) + 1;
}
else
{
@@ -1078,6 +1166,9 @@
path, *line, buf);
}
}
+ str.len = 0;
+ err = string_readline(&str, fp);
+ if (err) return nerr_pass(err);
}
return STATUS_OK;
}
@@ -1123,6 +1214,8 @@
int line = 0;
char fpath[_POSIX_PATH_MAX];
+ if (path == NULL)
+ return nerr_raise(NERR_ASSERT, "Can't read NULL file");
if (path[0] != '/')
{
err = hdf_search_path (hdf, path, fpath);
diff -Nbru clearsilver-0.4/util/neo_hdf.h clearsilver-0.5/util/neo_hdf.h
--- clearsilver-0.4/util/neo_hdf.h Fri Sep 14 16:45:46 2001
+++ clearsilver-0.5/util/neo_hdf.h Mon Apr 15 17:37:10 2002
@@ -50,6 +50,19 @@
NEOERR *hdf_set_symlink (HDF *hdf, char *src, char *dest);
+/*
+ * Function: hdf_sort_obj - sort the children of an HDF node
+ * Description: hdf_sort_obj will sort the children of an HDF node,
+ * based on the given comparison function. The current
+ * implementation uses a bubble sort, so be warned.
+ * Input: h - HDF node
+ * compareFunc - function which returns 1,0,-1 depending on some
+ * criteria. Given two children of h
+ * Output: None (h children will be sorted)
+ * Return: None
+ */
+NEOERR *hdf_sort_obj(HDF *h, int (*compareFunc)(const void *, const void *));
+
NEOERR* hdf_read_file (HDF *hdf, char *path);
NEOERR* hdf_write_file (HDF *hdf, char *path);
diff -Nbru clearsilver-0.4/util/neo_misc.c clearsilver-0.5/util/neo_misc.c
--- clearsilver-0.4/util/neo_misc.c Wed Jan 2 16:36:42 2002
+++ clearsilver-0.5/util/neo_misc.c Thu Feb 28 16:53:41 2002
@@ -10,18 +10,12 @@
#include
#include
-#include
#include
#include
#include
#include
-#include
#include
#include
-#include
-#include
-#include
-#include
#include "neo_err.h"
#include "neo_misc.h"
@@ -140,36 +134,6 @@
return f;
}
-NEOERR *ne_mkdirs (char *path, mode_t mode)
-{
- char mypath[_POSIX_PATH_MAX];
- int x;
- int r;
-
- strncpy (mypath, path, sizeof(mypath));
- x = strlen(mypath);
- if ((x < sizeof(mypath)) && (mypath[x-1] != '/'))
- {
- mypath[x] = '/';
- mypath[x+1] = '\0';
- }
-
- for (x = 1; mypath[x]; x++)
- {
- if (mypath[x] == '/')
- {
- mypath[x] = '\0';
- r = mkdir (mypath, mode);
- if (r == -1 && errno != EEXIST)
- {
- return nerr_raise_errno(NERR_SYSTEM, "ne_mkdirs: mkdir(%s, %x) failed", mypath, mode);
- }
- mypath[x] = '/';
- }
- }
- return STATUS_OK;
-}
-
static const UINT32 CRCTable[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
@@ -230,124 +194,3 @@
return crc;
}
-
-NEOERR *ne_load_file (char *path, char **str)
-{
- struct stat s;
- int fd;
- int len;
-
- *str = NULL;
-
- if (stat(path, &s) == -1)
- {
- if (errno == ENOENT)
- return nerr_raise (NERR_NOT_FOUND, "File %s not found", path);
- return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path);
- }
-
- fd = open (path, O_RDONLY);
- if (fd == -1)
- {
- return nerr_raise_errno (NERR_SYSTEM, "Unable to open file %s", path);
- }
- len = s.st_size;
- *str = (char *) malloc (len + 1);
-
- if (*str == NULL)
- {
- close(fd);
- return nerr_raise (NERR_NOMEM,
- "Unable to allocate memory (%d) to load file %s", s.st_size, path);
- }
- if (read (fd, *str, len) == -1)
- {
- close(fd);
- free(*str);
- return nerr_raise_errno (NERR_SYSTEM, "Unable to read file %s", path);
- }
- (*str)[len] = '\0';
- close(fd);
-
- return STATUS_OK;
-}
-
-NEOERR *ne_save_file (char *path, char *str)
-{
- NEOERR *err;
- int fd;
- int w, l;
-
- fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (fd == -1)
- {
- return nerr_raise_errno (NERR_IO, "Unable to create file %s", path);
- }
- l = strlen(str);
- w = write (fd, str, l);
- if (w != l)
- {
- err = nerr_raise_errno (NERR_IO, "Unable to write file %s", path);
- close (fd);
- return err;
- }
- close (fd);
-
- return STATUS_OK;
-}
-
-NEOERR *ne_remove_dir (char *path)
-{
- NEOERR *err;
- DIR *dp;
- struct stat s;
- struct dirent *de;
- char npath[_POSIX_PATH_MAX];
-
- if (stat(path, &s) == -1)
- {
- if (errno == ENOENT) return STATUS_OK;
- return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path);
- }
- if (!S_ISDIR(s.st_mode))
- {
- return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path);
- }
- dp = opendir(path);
- if (dp == NULL)
- return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path);
- while ((de = readdir (dp)) != NULL)
- {
- if (strcmp(de->d_name, ".") && strcmp(de->d_name, ".."))
- {
- snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name);
- if (stat(npath, &s) == -1)
- {
- if (errno == ENOENT) continue;
- closedir(dp);
- return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath);
- }
- if (S_ISDIR(s.st_mode))
- {
- err = ne_remove_dir(npath);
- if (err) break;
- }
- else
- {
- if (unlink(npath) == -1)
- {
- if (errno == ENOENT) continue;
- closedir(dp);
- return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s",
- npath);
- }
- }
- }
- }
- closedir(dp);
- if (rmdir(path) == -1)
- {
- return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path);
- }
- return STATUS_OK;
-}
diff -Nbru clearsilver-0.4/util/neo_misc.h clearsilver-0.5/util/neo_misc.h
--- clearsilver-0.4/util/neo_misc.h Mon Dec 17 23:17:05 2001
+++ clearsilver-0.5/util/neo_misc.h Thu Feb 28 16:53:41 2002
@@ -43,11 +43,7 @@
UINT8 *ne_stream_str (UINT8 *dest, char *s, int l);
UINT8 *ne_unstream_str (char *s, int l, UINT8 *src);
double ne_timef (void);
-NEOERR *ne_mkdirs (char *path, mode_t mode);
-NEOERR *ne_load_file (char *path, char **str);
-NEOERR *ne_save_file (char *path, char *str);
UINT32 ne_crc (UINT8 *data, UINT32 bytes);
-NEOERR *ne_remove_dir (char *path);
__END_DECLS
diff -Nbru clearsilver-0.4/util/neo_str.c clearsilver-0.5/util/neo_str.c
--- clearsilver-0.4/util/neo_str.c Mon Dec 17 23:17:05 2001
+++ clearsilver-0.5/util/neo_str.c Thu Apr 11 18:10:59 2002
@@ -121,7 +121,7 @@
err = string_check_length (str, l+1);
if (err != STATUS_OK) return nerr_pass (err);
- strncpy(str->buf + str->len, buf, l);
+ memcpy(str->buf + str->len, buf, l);
str->len += l;
str->buf[str->len] = '\0';
@@ -296,4 +296,122 @@
if (errcode == 0)
return TRUE;
return FALSE;
+}
+
+NEOERR *string_readline (STRING *str, FILE *fp)
+{
+ NEOERR *err;
+
+ /* minimum size for a readline is 256 above current position */
+ err = string_check_length (str, str->len + 256);
+ if (err != STATUS_OK) return nerr_pass (err);
+
+ while (fgets(str->buf + str->len, str->max - str->len, fp) != NULL)
+ {
+ str->len = strlen(str->buf);
+ if (str->buf[str->len-1] == '\n') break;
+ err = string_check_length (str, str->len + 256);
+ if (err != STATUS_OK) return nerr_pass (err);
+ }
+ return STATUS_OK;
+}
+
+NEOERR* neos_escape(UINT8 *buf, int buflen, char esc_char, char *escape, char **esc)
+{
+ int nl = 0;
+ int l = 0;
+ int x = 0;
+ char *s;
+ int match = 0;
+
+ while (l < buflen)
+ {
+ if (buf[l] == esc_char)
+ {
+ nl += 2;
+ }
+ else
+ {
+ x = 0;
+ while (escape[x])
+ {
+ if (escape[x] == buf[l])
+ {
+ nl +=2;
+ break;
+ }
+ x++;
+ }
+ }
+ nl++;
+ l++;
+ }
+
+ s = (char *) malloc (sizeof(char) * (nl + 1));
+ if (s == NULL)
+ return nerr_raise (NERR_NOMEM, "Unable to allocate memory to escape %s",
+ buf);
+
+ nl = 0; l = 0;
+ while (l < buflen)
+ {
+ match = 0;
+ if (buf[l] == esc_char)
+ {
+ match = 1;
+ }
+ else
+ {
+ x = 0;
+ while (escape[x])
+ {
+ if (escape[x] == buf[l])
+ {
+ match = 1;
+ break;
+ }
+ x++;
+ }
+ }
+ if (match)
+ {
+ s[nl++] = esc_char;
+ s[nl++] = "0123456789ABCDEF"[buf[l] / 16];
+ s[nl++] = "0123456789ABCDEF"[buf[l] % 16];
+ l++;
+ }
+ else
+ {
+ s[nl++] = buf[l++];
+ }
+ }
+ s[nl] = '\0';
+
+ *esc = s;
+ return STATUS_OK;
+}
+
+UINT8 *neos_unescape (UINT8 *s, int buflen, char esc_char)
+{
+ int i = 0, o = 0;
+
+ if (s == NULL) return s;
+ while (i < buflen)
+ {
+ if (s[i] == esc_char && (i+2 < buflen) &&
+ isxdigit(s[i+1]) && isxdigit(s[i+2]))
+ {
+ UINT8 num;
+ num = (s[i+1] >= 'A') ? ((s[i+1] & 0xdf) - 'A') + 10 : (s[i+1] - '0');
+ num *= 16;
+ num += (s[i+2] >= 'A') ? ((s[i+2] & 0xdf) - 'A') + 10 : (s[i+2] - '0');
+ s[o++] = num;
+ i+=3;
+ }
+ else {
+ s[o++] = s[i++];
+ }
+ }
+ if (i && o) s[o] = '\0';
+ return s;
}
diff -Nbru clearsilver-0.4/util/neo_str.h clearsilver-0.5/util/neo_str.h
--- clearsilver-0.4/util/neo_str.h Mon Dec 17 23:17:05 2001
+++ clearsilver-0.5/util/neo_str.h Thu Apr 11 18:10:59 2002
@@ -15,6 +15,7 @@
__BEGIN_DECLS
#include
+#include
#include "util/neo_misc.h"
/* This modifies the string its called with by replacing all the white
@@ -30,7 +31,7 @@
typedef struct _string
{
- char *buf;
+ UINT8 *buf;
int len;
int max;
} STRING;
@@ -49,6 +50,7 @@
NEOERR *string_append_char (STRING *str, char c);
NEOERR *string_appendf (STRING *str, char *fmt, ...);
NEOERR *string_appendvf (STRING *str, char *fmt, va_list ap);
+NEOERR *string_readline (STRING *str, FILE *fp);
void string_clear (STRING *str);
/* typedef struct _ulist ULIST; */
@@ -57,6 +59,9 @@
BOOL reg_search (char *re, char *str);
+
+NEOERR* neos_escape(UINT8 *buf, int buflen, char esc_char, char *escape, char **esc);
+UINT8 *neos_unescape (UINT8 *s, int buflen, char esc_char);
__END_DECLS
diff -Nbru clearsilver-0.4/util/rcfs.c clearsilver-0.5/util/rcfs.c
--- clearsilver-0.4/util/rcfs.c Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/rcfs.c Thu Feb 28 16:53:41 2002
@@ -24,6 +24,7 @@
#include "util/neo_err.h"
#include "util/neo_misc.h"
+#include "util/neo_files.h"
#include "util/neo_hdf.h"
#include "util/ulocks.h"
#include "rcfs.h"
diff -Nbru clearsilver-0.4/util/skiplist.c clearsilver-0.5/util/skiplist.c
--- clearsilver-0.4/util/skiplist.c Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/skiplist.c Thu Apr 11 14:17:46 2002
@@ -37,7 +37,7 @@
#define SIZEOFITEM(max) (sizeof(struct skipItem) + \
((max+1) * sizeof(skipItem)))
-struct skipList {
+struct skipList_struct {
INT32 topLevel; /* current max level in any item */
INT32 levelHint; /* hint at level to start search */
skipItem header; /* header item (has all levels) */
@@ -361,7 +361,7 @@
UINT32 i;
*skip = NULL;
- if(! (list = calloc(1, sizeof(struct skipList))))
+ if(! (list = calloc(1, sizeof(struct skipList_struct))))
return nerr_raise(NERR_NOMEM, "Unable to allocate memore for skiplist");
if (maxLevel == 0)
diff -Nbru clearsilver-0.4/util/skiplist.h clearsilver-0.5/util/skiplist.h
--- clearsilver-0.4/util/skiplist.h Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/skiplist.h Thu Apr 11 14:17:46 2002
@@ -17,6 +17,10 @@
#ifndef _SKIPLIST_H_
#define _SKIPLIST_H_
+#include
+
+__BEGIN_DECLS
+
/*
* Larger values of means fewer levels and faster lookups,
* but more variability in those lookup times (range limited from 2 to 4).
@@ -27,11 +31,15 @@
*
* I've capped at 20, which would be good for a minimum of
* 1 million items on lists with == 2.
+ *
+ *
+ * Example
+ * skipNewList(&(my_wdb->ondisk), 0, 4, 2, 0, NULL, NULL);
*/
#define SKIP_MAXLEVEL 20
/* SKIP LIST TYPEDEFS */
-typedef struct skipList *skipList;
+typedef struct skipList_struct *skipList;
typedef void (*skipFreeValue)(void *value, void *ctx);
NEOERR *skipNewList(skipList *skip, int threaded, int root, int maxLevel,
@@ -146,4 +154,12 @@
* MT-Level: Safe if thread-safe.
*/
+__END_DECLS
+
#endif /* _SKIPLIST_H_ */
+
+
+
+
+
+
diff -Nbru clearsilver-0.4/util/test/Makefile clearsilver-0.5/util/test/Makefile
--- clearsilver-0.4/util/test/Makefile Fri Dec 22 00:31:27 2000
+++ clearsilver-0.5/util/test/Makefile Thu Apr 18 12:24:55 2002
@@ -10,16 +10,30 @@
HDFTEST_SRC = hdftest.c
HDFTEST_OBJ = $(HDFTEST_SRC:%.c=%.o)
+LISTDIRTEST_EXE = listdir_test
+LISTDIRTEST_SRC = listdir_test.c
+LISTDIRTEST_OBJ = $(LISTDIRTEST_SRC:%.c=%.o)
+
+HDFCOPYTEST_EXE = hdf_copy_test
+HDFCOPYTEST_SRC = hdf_copy_test.c
+HDFCOPYTEST_OBJ = $(HDFCOPYTEST_SRC:%.c=%.o)
+
CFLAGS += -I$(NEOTONIC_ROOT)/util
-LIBS += -L$(LIB_DIR) -lneo_utl # -lefence
+LIBS += -L$(LIB_DIR) -lneo_utl
-TARGETS = $(HDFTEST_EXE)
+TARGETS = $(HDFTEST_EXE) $(LISTDIRTEST_EXE) $(HDFCOPYTEST_EXE)
all: $(TARGETS)
$(HDFTEST_EXE): $(HDFTEST_OBJ) $(NTR_LIB)
$(LD) $@ $(HDFTEST_OBJ) $(LIBS)
+
+$(LISTDIRTEST_EXE): $(LISTDIRTEST_OBJ) $(NTR_LIB)
+ $(LD) $@ $(LISTDIRTEST_OBJ) $(LIBS)
+
+$(HDFCOPYTEST_EXE): $(HDFCOPYTEST_OBJ) $(NTR_LIB)
+ $(LD) $@ $(HDFCOPYTEST_OBJ) $(LIBS) -lefence
clean:
$(RM) *.o
diff -Nbru clearsilver-0.4/util/test/hdf_copy_test.c clearsilver-0.5/util/test/hdf_copy_test.c
--- clearsilver-0.4/util/test/hdf_copy_test.c Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/test/hdf_copy_test.c Thu Apr 18 12:24:55 2002
@@ -0,0 +1,37 @@
+
+#include
+#include
+
+int main(void) {
+ HDF *hdf_1;
+ HDF *hdf_2;
+ HDF *cur_node,*last_node;
+
+ hdf_init(&hdf_1);
+
+ hdf_read_file(hdf_1,"hdf_copy_test.hdf");
+
+ cur_node = hdf_get_obj(hdf_1,"Chart");
+ last_node = cur_node;
+
+ cur_node = hdf_get_obj(cur_node,"next_stage");
+ while (hdf_get_obj(cur_node,"next_stage") && strcmp(hdf_get_value(cur_node,"Bucket.FieldId",""),"QUEUE")) {
+ last_node = cur_node;
+ cur_node = hdf_get_obj(cur_node,"next_stage");
+ }
+
+ if (hdf_get_obj(cur_node,"next_stage")) {
+ hdf_copy(hdf_1,"TempHolderPlace",hdf_get_obj(cur_node,"next_stage"));
+ }
+ ne_warn("Delete tree from node: %s", hdf_obj_name(last_node));
+ hdf_remove_tree(last_node,"next_stage");
+
+ hdf_dump(hdf_1,NULL);
+ fprintf(stderr,"-----------------\n");
+
+
+ hdf_copy(last_node,"next_stage",hdf_get_obj(hdf_1,"TempHolderPlace"));
+ hdf_dump(hdf_1,NULL);
+
+ return 0;
+}
diff -Nbru clearsilver-0.4/util/test/hdf_copy_test.hdf clearsilver-0.5/util/test/hdf_copy_test.hdf
--- clearsilver-0.4/util/test/hdf_copy_test.hdf Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/test/hdf_copy_test.hdf Thu Apr 18 11:46:44 2002
@@ -0,0 +1,50 @@
+
+# --------------------------------------------------
+# this is an example definition of a chart pipeline
+#
+
+
+DataSource = outfile.sdb
+DataSource {
+# TODO: specify time range for the dataset....
+}
+
+DomainData {
+# TODO: include data values for agents, queues, etc.
+}
+
+Filters {
+# TODO: configure filters to limit data
+}
+
+Chart {
+ next_stage {
+ id = 1
+ Type = Mux
+ Bucket = Discrete
+ Bucket.FieldId = QUEUE
+ Bucket.Dimension = Y
+
+ next_stage {
+ id = 2
+ Type = Mux
+ Bucket = Time
+ Bucket.FieldId = TIME
+ Bucket.Dimension = Y
+
+ next_stage {
+ id = 3
+ Type = Mux
+ Bucket = Discrete
+ Bucket.FieldId = AGENT
+ Bucket.Dimension = X
+
+ next_stage {
+ id = 4
+ Type = Accumulator
+ }
+ }
+ }
+
+ }
+}
diff -Nbru clearsilver-0.4/util/test/hdftest.c clearsilver-0.5/util/test/hdftest.c
--- clearsilver-0.4/util/test/hdftest.c Fri Dec 22 00:31:27 2000
+++ clearsilver-0.5/util/test/hdftest.c Mon Apr 15 17:37:11 2002
@@ -21,6 +21,15 @@
return 0;
}
+static int sortByName(const void *a, const void *b) {
+ HDF **ha = (HDF **)a;
+ HDF **hb = (HDF **)b;
+
+ /* fprintf(stderr, "%s <=> %s\n", hdf_obj_name(*ha), hdf_obj_name(*hb)); */
+ return strcasecmp(hdf_obj_name(*ha), hdf_obj_name(*hb));
+}
+
+
int main(int argc, char *argv[])
{
NEOERR *err;
@@ -28,6 +37,7 @@
int x;
char name[256];
char value[256];
+ double tstart = 0;
err = hdf_init(&hdf);
if (err != STATUS_OK)
@@ -75,7 +85,7 @@
hdf_dump(hdf, NULL);
- err = hdf_get_int_value (hdf, "Beware.The.Ides", &x, 0);
+ x = hdf_get_int_value (hdf, "Beware.The.Ides", 0);
if (err != STATUS_OK)
{
nerr_log_error(err);
@@ -87,7 +97,7 @@
return -1;
}
- for (x = 0; x < 100; x++)
+ for (x = 0; x < 10000; x++)
{
rand_name(name, sizeof(name));
neot_rand_word(value, sizeof(value));
@@ -107,7 +117,11 @@
return -1;
}
- hdf_dump(hdf, NULL);
+ tstart = ne_timef();
+ hdf_sort_obj(hdf, sortByName);
+ ne_warn("sort took %5.5fs", ne_timef() - tstart);
+
+ /* hdf_dump(hdf, NULL); */
hdf_destroy(&hdf);
diff -Nbru clearsilver-0.4/util/test/listdir_test.c clearsilver-0.5/util/test/listdir_test.c
--- clearsilver-0.4/util/test/listdir_test.c Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/test/listdir_test.c Thu Feb 28 16:53:42 2002
@@ -0,0 +1,52 @@
+
+#include
+#include "util/neo_err.h"
+#include "util/neo_misc.h"
+#include "util/neo_files.h"
+
+int main(int argc, char **argv)
+{
+ char *path;
+ ULIST *files = NULL;
+ char *filename;
+ NEOERR *err;
+ int x;
+
+ if (argc > 1)
+ path = argv[1];
+ else
+ path = ".";
+
+ ne_warn("Testing ne_listdir()");
+ err = ne_listdir(path, &files);
+ if (err)
+ {
+ nerr_log_error(err);
+ return -1;
+ }
+
+ for (x = 0; x < uListLength(files); x++)
+ {
+ err = uListGet(files, x, &filename);
+ printf("%s\n", filename);
+ }
+
+ uListDestroy(&files, ULIST_FREE);
+
+ ne_warn("Testing ne_listdir_match() with *.c");
+ err = ne_listdir_match(path, &files, "*.c");
+ if (err)
+ {
+ nerr_log_error(err);
+ return -1;
+ }
+
+ for (x = 0; x < uListLength(files); x++)
+ {
+ err = uListGet(files, x, &filename);
+ printf("%s\n", filename);
+ }
+
+ uListDestroy(&files, ULIST_FREE);
+ return 0;
+}
diff -Nbru clearsilver-0.4/util/ulist.c clearsilver-0.5/util/ulist.c
--- clearsilver-0.4/util/ulist.c Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/ulist.c Thu Mar 28 10:35:43 2002
@@ -216,6 +216,29 @@
return STATUS_OK;
}
+void *uListSearch (ULIST *ul, const void *key, int
+ (*compareFunc)(const void *, const void*)) {
+ return bsearch(key, ul->items, ul->num, sizeof(void *), compareFunc);
+}
+
+void *uListIn (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*)) {
+ int i;
+
+ for (i = 0; i < ul->num; ++i) {
+ if (!compareFunc(key, &ul->items[i])) {
+ return &ul->items[i];
+ }
+ }
+ return NULL;
+}
+
+int uListIndex (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*)) {
+ void **p = uListIn(ul, key, compareFunc);
+ return p ? (p - ul->items) : -1;
+}
+
+
+
NEOERR *uListDestroy (ULIST **ul, int flags)
{
if (flags & ULIST_FREE)
@@ -254,5 +277,6 @@
int uListLength (ULIST *ul)
{
+ if (ul == NULL) return 0;
return ul->num;
}
diff -Nbru clearsilver-0.4/util/ulist.h clearsilver-0.5/util/ulist.h
--- clearsilver-0.4/util/ulist.h Mon Aug 6 14:28:17 2001
+++ clearsilver-0.5/util/ulist.h Thu Mar 28 10:35:43 2002
@@ -36,6 +36,9 @@
NEOERR * uListSet (ULIST *ul, int x, void *data);
NEOERR * uListReverse (ULIST *ul);
NEOERR * uListSort (ULIST *ul, int (*compareFunc)(const void*, const void*));
+void *uListSearch (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*));
+void *uListIn (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*));
+int uListIndex (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*));
NEOERR * uListDestroy (ULIST **ul, int flags);
NEOERR * uListDestroyFunc (ULIST **ul, void (*destroyFunc)(void *));
diff -Nbru clearsilver-0.4/util/ulocks.c clearsilver-0.5/util/ulocks.c
--- clearsilver-0.4/util/ulocks.c Wed Jan 2 16:36:31 2002
+++ clearsilver-0.5/util/ulocks.c Thu Feb 28 16:53:41 2002
@@ -17,6 +17,7 @@
#include "neo_err.h"
#include "neo_misc.h"
+#include "neo_files.h"
#include "ulocks.h"
NEOERR *fCreate(int *plock, char *file)
diff -Nbru clearsilver-0.4/util/wildmat.c clearsilver-0.5/util/wildmat.c
--- clearsilver-0.4/util/wildmat.c Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/wildmat.c Thu Feb 28 16:53:41 2002
@@ -0,0 +1,205 @@
+/* $Revision: 1.1 $
+ **
+ ** Do shell-style pattern matching for ?, \, [], and * characters.
+ ** Might not be robust in face of malformed patterns; e.g., "foo[a-"
+ ** could cause a segmentation violation. It is 8bit clean.
+ **
+ ** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+ ** Rich $alz is now .
+ ** April, 1991: Replaced mutually-recursive calls with in-line code
+ ** for the star character.
+ **
+ ** Special thanks to Lars Mathiesen for the ABORT code.
+ ** This can greatly speed up failing wildcard patterns. For example:
+ ** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
+ ** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
+ ** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
+ ** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
+ ** the ABORT code, it takes 22310 calls to fail. Ugh. The following
+ ** explanation is from Lars:
+ ** The precondition that must be fulfilled is that DoMatch will consume
+ ** at least one character in text. This is true if *p is neither '*' nor
+ ** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic
+ ** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With
+ ** FALSE, each star-loop has to run to the end of the text; with ABORT
+ ** only the last one does.
+ **
+ ** Once the control of one instance of DoMatch enters the star-loop, that
+ ** instance will return either TRUE or ABORT, and any calling instance
+ ** will therefore return immediately after (without calling recursively
+ ** again). In effect, only one star-loop is ever active. It would be
+ ** possible to modify the code to maintain this context explicitly,
+ ** eliminating all recursive calls at the cost of some complication and
+ ** loss of clarity (and the ABORT stuff seems to be unclear enough by
+ ** itself). I think it would be unwise to try to get this into a
+ ** released version unless you have a good test data base to try it
+ ** out on.
+ */
+
+#include
+#include "neo_misc.h"
+
+#define ABORT -1
+
+
+ /* What character marks an inverted character class? */
+#define NEGATE_CLASS '^'
+ /* Is "*" a common pattern? */
+#define OPTIMIZE_JUST_STAR
+ /* Do tar(1) matching rules, which ignore a trailing slash? */
+#undef MATCH_TAR_PATTERN
+
+
+/*
+ ** Match text and p, return TRUE, FALSE, or ABORT.
+ */
+ static int
+DoMatch(register char *text, register char *p)
+{
+ register int last;
+ register int matched;
+ register int reverse;
+
+ for ( ; *p; text++, p++) {
+ if (*text == '\0' && *p != '*')
+ return ABORT;
+ switch (*p) {
+ case '\\':
+ /* Literal match with following character. */
+ p++;
+ /* FALLTHROUGH */
+ default:
+ if (*text != *p)
+ return FALSE;
+ continue;
+ case '?':
+ /* Match anything. */
+ continue;
+ case '*':
+ while (*++p == '*')
+ /* Consecutive stars act just like one. */
+ continue;
+ if (*p == '\0')
+ /* Trailing star matches everything. */
+ return TRUE;
+ while (*text)
+ if ((matched = DoMatch(text++, p)) != FALSE)
+ return matched;
+ return ABORT;
+ case '[':
+ reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
+ if (reverse)
+ /* Inverted character class. */
+ p++;
+ matched = FALSE;
+ if (p[1] == ']' || p[1] == '-')
+ if (*++p == *text)
+ matched = TRUE;
+ for (last = *p; *++p && *p != ']'; last = *p)
+ /* This next line requires a good C compiler. */
+ if (*p == '-' && p[1] != ']'
+ ? *text <= *++p && *text >= last : *text == *p)
+ matched = TRUE;
+ if (matched == reverse)
+ return FALSE;
+ continue;
+ }
+ }
+
+#ifdef MATCH_TAR_PATTERN
+ if (*text == '/')
+ return TRUE;
+#endif /* MATCH_TAR_ATTERN */
+ return *text == '\0';
+}
+
+
+/*
+ ** Match text and p, return TRUE, FALSE, or ABORT.
+ */
+static int
+DoMatchCaseInsensitive(register char *text, register char *p)
+{
+ register int last;
+ register int matched;
+ register int reverse;
+
+ for ( ; *p; text++, p++) {
+ if (*text == '\0' && *p != '*')
+ return ABORT;
+ switch (*p) {
+ case '\\':
+ /* Literal match with following character. */
+ p++;
+ /* FALLTHROUGH */
+ default:
+ if (toupper(*text) != toupper(*p))
+ return FALSE;
+ continue;
+ case '?':
+ /* Match anything. */
+ continue;
+ case '*':
+ while (*++p == '*')
+ /* Consecutive stars act just like one. */
+ continue;
+ if (*p == '\0')
+ /* Trailing star matches everything. */
+ return TRUE;
+ while (*text)
+ if ((matched = DoMatchCaseInsensitive(text++, p)) != FALSE)
+ return matched;
+ return ABORT;
+ case '[':
+ reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
+ if (reverse)
+ /* Inverted character class. */
+ p++;
+ matched = FALSE;
+ if (p[1] == ']' || p[1] == '-')
+ if (toupper(*++p) == toupper(*text))
+ matched = TRUE;
+ for (last = toupper(*p); *++p && *p != ']'; last = toupper(*p))
+ /* This next line requires a good C compiler. */
+ if (*p == '-' && p[1] != ']'
+ ? toupper(*text) <= toupper(*++p) && toupper(*text) >= last : toupper(*text) == toupper(*p))
+ matched = TRUE;
+ if (matched == reverse)
+ return FALSE;
+ continue;
+ }
+ }
+
+#ifdef MATCH_TAR_PATTERN
+ if (*text == '/')
+ return TRUE;
+#endif /* MATCH_TAR_ATTERN */
+ return *text == '\0';
+}
+
+
+/*
+ ** User-level routine. Returns TRUE or FALSE.
+ */
+int
+wildmat(char *text, char *p)
+{
+#ifdef OPTIMIZE_JUST_STAR
+ if (p[0] == '*' && p[1] == '\0')
+ return TRUE;
+#endif /* OPTIMIZE_JUST_STAR */
+ return DoMatch(text, p) == TRUE;
+}
+
+/*
+ ** User-level routine. Returns TRUE or FALSE.
+ */
+int
+wildmatcase(char *text, char *p)
+{
+#ifdef OPTIMIZE_JUST_STAR
+ if (p[0] == '*' && p[1] == '\0')
+ return TRUE;
+#endif /* OPTIMIZE_JUST_STAR */
+ return DoMatchCaseInsensitive(text, p) == TRUE;
+}
diff -Nbru clearsilver-0.4/util/wildmat.h clearsilver-0.5/util/wildmat.h
--- clearsilver-0.4/util/wildmat.h Wed Dec 31 16:00:00 1969
+++ clearsilver-0.5/util/wildmat.h Thu Feb 28 16:53:41 2002
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1986-1991 Rich Salz
+ *
+ */
+
+#ifndef __WILDMAT_H_
+#define __WILDMAT_H_ 1
+
+__BEGIN_DECLS
+
+int wildmat(char *text, char *p);
+int wildmatcase(char *text, char *p);
+
+__END_DECLS
+
+#endif /* __WILDMAT_H_ */