blob: c6f3a6d94f471894db05762aa4b76c1de0c67479 [file] [log] [blame]
/*
* Copyright 2001-2004 Brandon Long
* All Rights Reserved.
*
* ClearSilver Templating System
*
* This code is made available under the terms of the ClearSilver License.
* http://www.clearsilver.net/license.hdf
*
*/
/* Bring in gd library functions */
#include "gd.h"
/* Bring in standard I/O so we can output the PNG to a file */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <time.h>
#include <ctype.h>
#include "ClearSilver.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,"%25s %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];
ne_warn("%s: %dx%d", file, *width, *height);
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")) ||
(!strcasecmp(ch, ".thm")))
{
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>4 && !strcasecmp(fname+l-4, ".thm")) ||
(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 ((maxW && srcW > maxW) || (maxH && 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 );
}
#ifdef GD2_VERS
dest_im = gdImageCreateTrueColor(dstW,dstH);
#else
dest_im = gdImageCreate(dstW,dstH);
#endif
/* 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 {
dispfile = fopen(fname,"rb");
}
}
/* the data in "dispfile" is going to be printed now */
{
char buf[8192];
int count;
if (!fstat(fileno(dispfile), &s) && s.st_size)
{
cgiwrap_writef("Content-Length: %ld\n\n", s.st_size);
}
else
{
cgiwrap_writef("\n");
}
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);
}
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>4 && !strcasecmp(de->d_name+l-4, ".thm")) ||
(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, is_thm = 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;
else if (l>4 && !strcasecmp(file+l-4, ".thm"))
is_thm = 1;
snprintf (buf, sizeof(buf), "%s.%d", prefix, i);
err = hdf_set_value (cgi->hdf, prefix, file);
if (err != STATUS_OK) return nerr_pass(err);
snprintf (ipath, sizeof(ipath), "%s/%s", path, file);
if (is_jpeg || is_thm)
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);
}
if (is_thm)
{
strcpy(ipath, file);
strcpy(ipath+l-4, ".avi");
snprintf(buf, sizeof(buf), "%s.avi", prefix);
err = hdf_set_value (cgi->hdf, buf, ipath);
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);
}
static NEOERR *export_album_path(CGI *cgi, char *album, char *prefix)
{
NEOERR *err = STATUS_OK;
char *p, *l;
int n = 0;
char buf[256];
l = album;
p = strchr(album, '/');
while (p != NULL)
{
*p = '\0';
snprintf(buf, sizeof(buf), "%s.%d", prefix, n);
err = hdf_set_value(cgi->hdf, buf, l);
if (err) break;
snprintf(buf, sizeof(buf), "%s.%d.path", prefix, n++);
err = hdf_set_value(cgi->hdf, buf, album);
if (err) break;
*p = '/';
l = p+1;
p = strchr(l, '/');
}
if (err) return nerr_pass(err);
if (strlen(l))
{
snprintf(buf, sizeof(buf), "%s.%d", prefix, n);
err = hdf_set_value(cgi->hdf, buf, l);
if (err) return nerr_pass(err);
snprintf(buf, sizeof(buf), "%s.%d.path", prefix, n++);
err = hdf_set_value(cgi->hdf, buf, album);
if (err) return nerr_pass(err);
}
return STATUS_OK;
}
NEOERR *dowork_picture (CGI *cgi, char *album, char *picture)
{
NEOERR *err = STATUS_OK;
char *base, *name;
char path[_POSIX_PATH_MAX];
char buf[256];
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;
char *avi = NULL;
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_value (cgi->hdf, "Album", 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 = export_album_path(cgi, album, "Album.Path");
if (err) return nerr_pass(err);
err = hdf_set_value (cgi->hdf, "Picture", 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;
ne_warn("factor = %d, y = %d", factor, y);
}
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);
}
snprintf (buf, sizeof(buf), "Show.%d.avi", i);
avi = hdf_get_value (cgi->hdf, buf, NULL);
if (avi)
{
err = hdf_set_value(cgi->hdf, "Picture.avi", avi);
}
err = scale_images (cgi, "Show", thumb_width, thumb_height, 0);
}
uListDestroy(&files, ULIST_FREE);
return nerr_pass(err);
}
static int is_album(void *rock, char *filename)
{
char path[_POSIX_PATH_MAX];
char *prefix = (char *)rock;
if (filename[0] == '.') return 0;
snprintf(path, sizeof(path), "%s/%s", prefix, filename);
if (isdir(path)) return 1;
return 0;
}
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, y;
int thumb_width, thumb_height;
ULIST *files = NULL;
ULIST *albums = NULL;
char *name;
thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
err = ne_listdir_fmatch(album, &albums, is_album, album);
if (err) return nerr_pass(err);
err = uListSort(albums, alpha_sort);
if (err) return nerr_pass(err);
for (y = 0; y < uListLength(albums); y++)
{
err = uListGet(albums, y, (void *)&name);
if (err) break;
snprintf(path, sizeof(path), "%s/%s", album, name);
snprintf(buf, sizeof(buf), "Albums.%d", i);
err = hdf_set_value (cgi->hdf, buf, 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++;
}
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_value (cgi->hdf, "Album", 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 = export_album_path(cgi, album, "Album.Path");
if (err) 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 = 0, maxH = 0;
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); */
ne_warn("srcpath: %s", srcpath);
l = strlen(srcpath);
if ((l>4 && !strcasecmp(srcpath+l-4, ".jpg")) ||
(l>4 && !strcasecmp(srcpath+l-4, ".thm")) ||
(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");
else if (l>4 && !strcasecmp(srcpath+l-4, ".avi"))
{
ne_warn("found avi");
cgiwrap_writef("Content-Type: video/x-msvideo\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", buf);
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;
ne_warn("Starting IMD");
cgi_debug_init (argc,argv);
cgiwrap_init_std (argc, argv, envp);
nerr_init();
ne_warn("CGI init");
err = cgi_init(&cgi, NULL);
if (err != STATUS_OK)
{
nerr_log_error(err);
cgi_destroy(&cgi);
return -1;
}
imd_file = hdf_get_value(cgi->hdf, "CGI.PathTranslated", NULL);
ne_warn("Reading IMD file %s", imd_file);
err = hdf_read_file (cgi->hdf, imd_file);
if (err != STATUS_OK)
{
cgi_neo_error(cgi, err);
nerr_log_error(err);
cgi_destroy(&cgi);
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);
cgi_destroy(&cgi);
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
{
cgi_neo_error(cgi, err);
nerr_log_error(err);
cgi_destroy(&cgi);
return -1;
}
}
else
{
err = cgi_display(cgi, cs_file);
if (err != STATUS_OK)
{
cgi_neo_error(cgi, err);
nerr_log_error(err);
cgi_destroy(&cgi);
return -1;
}
}
}
cgi_destroy(&cgi);
return 0;
}