1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
4 *
5 * ClearSilver Templating System
6 *
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
9 *
10 */
11
12 /* Bring in gd library functions */
13 #include "gd.h"
14
15 /* Bring in standard I/O so we can output the PNG to a file */
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <stdlib.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <sys/fcntl.h>
24 #include <time.h>
25 #include <ctype.h>
26
27 #include "ClearSilver.h"
28
29 /* from httpd util.c : made infamous with Roy owes Rob beer. */
30 static char *months[] = {
31 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
32 };
33
find_month(char * mon)34 int find_month(char *mon) {
35 register int x;
36
37 for(x=0;x<12;x++)
38 if(!strcmp(months[x],mon))
39 return x;
40 return -1;
41 }
42
later_than(struct tm * lms,char * ims)43 int later_than(struct tm *lms, char *ims) {
44 char *ip;
45 char mname[256];
46 int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, x;
47
48 /* Whatever format we're looking at, it will start
49 * with weekday. */
50 /* Skip to first space. */
51 if(!(ip = strchr(ims,' ')))
52 return 0;
53 else
54 while(isspace(*ip))
55 ++ip;
56
57 if(isalpha(*ip)) {
58 /* ctime */
59 sscanf(ip,"%25s %d %d:%d:%d %d",mname,&day,&hour,&min,&sec,&year);
60 }
61 else if(ip[2] == '-') {
62 /* RFC 850 (normal HTTP) */
63 char t[256];
64 sscanf(ip,"%s %d:%d:%d",t,&hour,&min,&sec);
65 t[2] = '\0';
66 day = atoi(t);
67 t[6] = '\0';
68 strcpy(mname,&t[3]);
69 x = atoi(&t[7]);
70 /* Prevent wraparound from ambiguity */
71 if(x < 70)
72 x += 100;
73 year = 1900 + x;
74 }
75 else {
76 /* RFC 822 */
77 sscanf(ip,"%d %s %d %d:%d:%d",&day,mname,&year,&hour,&min,&sec);
78 }
79 month = find_month(mname);
80
81 if((x = (1900+lms->tm_year) - year))
82 return x < 0;
83 if((x = lms->tm_mon - month))
84 return x < 0;
85 if((x = lms->tm_mday - day))
86 return x < 0;
87 if((x = lms->tm_hour - hour))
88 return x < 0;
89 if((x = lms->tm_min - min))
90 return x < 0;
91 if((x = lms->tm_sec - sec))
92 return x < 0;
93
94 return 1;
95 }
96
97
98
gif_size(char * file,int * width,int * height)99 int gif_size (char *file, int *width, int *height)
100 {
101 UINT8 data[256];
102 int fd;
103 int blen;
104
105 *width = 0; *height = 0;
106 fd = open (file, O_RDONLY);
107 if (fd == -1)
108 return -1;
109
110 blen = read(fd, data, sizeof(data));
111 close(fd);
112
113 if (blen < 10) return -1;
114 if (strncmp(data, "GIF87a", 6) && strncmp(data, "GIF89a", 6))
115 return -1;
116
117 *width = data[6] + data[7]*256;
118 *height = data[8] + data[9]*256;
119
120 return 0;
121 }
122
jpeg_size(char * file,int * width,int * height)123 int jpeg_size (char *file, int *width, int *height)
124 {
125 UINT8 data[64*1024];
126 int blen;
127 int fd;
128 int pos;
129 int length;
130 UINT8 tag, marker;
131
132
133 *width = 0; *height = 0;
134 fd = open (file, O_RDONLY);
135 if (fd == -1)
136 return -1;
137
138 blen = read(fd, data, sizeof(data));
139 close(fd);
140 pos = 2;
141 while (pos+8 < blen)
142 {
143 tag = data[pos+0];
144 if (tag != 0xff) return -1;
145 marker = data[pos+1];
146 length = data[pos+2] * 256 + data[pos+3] + 2;
147 if (marker >= 0xc0 && marker <= 0xcf && marker != 0xc4 &&
148 marker != 0xc8 && marker != 0xcc)
149 {
150 *height = data[pos+5] * 256 + data[pos+6];
151 *width = data[pos+7] * 256 + data[pos+8];
152 ne_warn("%s: %dx%d", file, *width, *height);
153 return 0;
154 }
155 pos += length;
156 }
157 return -1;
158 }
159
isdir(char * dir)160 int isdir(char *dir) {
161 struct stat statinfo;
162 if ( stat(dir, &statinfo) != 0) {
163 return 0;
164 }
165
166 return S_ISDIR(statinfo.st_mode);
167 }
168
create_directories(char * fullpath)169 int create_directories(char *fullpath) {
170 char s[4000];
171 char *last_slash;
172 int last_slash_pos;
173
174 if ((fullpath == NULL) || (strlen(fullpath) > 4000)) {
175 return 1;
176 }
177
178 last_slash = strrchr(fullpath,'/');
179 last_slash_pos = (last_slash - fullpath);
180 /* fprintf(stderr,"dira(%d): %s\n", last_slash_pos,fullpath); */
181
182 if (last_slash_pos > 2) {
183 strncpy(s,fullpath,last_slash_pos);
184 s[last_slash_pos] = 0;
185 /* fprintf(stderr,"dir: %s\n", s); */
186
187 if (!isdir(s)) {
188 char s2[4000];
189 sprintf(s2,"mkdir -p %s", s);
190 return system(s2);
191 }
192
193 } else {
194 return 1;
195 }
196
197 return 0;
198 }
199
rotate_image(char * path,char * file,int degree,char * rpath)200 NEOERR *rotate_image(char *path, char *file, int degree, char *rpath)
201 {
202 char cmd[256];
203 char nfile[_POSIX_PATH_MAX];
204 char ofile[_POSIX_PATH_MAX];
205 char *ch, *opt;
206 int is_jpeg = 0;
207 struct stat s;
208 int r;
209
210 snprintf (ofile, sizeof(ofile), "%s/%s", path, file);
211 snprintf (rpath, _POSIX_PATH_MAX, "%s/%s", path, file);
212 ch = strrchr(rpath, '.');
213 if ((!strcasecmp(ch, ".jpg")) ||
214 (!strcasecmp(ch, ".jpeg")) ||
215 (!strcasecmp(ch, ".thm")))
216 {
217 is_jpeg = 1;
218 }
219 else if (strcasecmp(ch, ".gif"))
220 {
221 return nerr_raise(NERR_ASSERT, "Only support gif/jpeg for rotation, ext %s",
222 ch);
223 }
224 *ch = '\0';
225 if (degree == 90)
226 {
227 strcat(rpath, "_r");
228 opt = "-cw";
229 }
230 else if (degree == -90)
231 {
232 strcat(rpath, "_l");
233 opt = "-ccw";
234 }
235 else if (degree == 180)
236 {
237 strcat(rpath, "_u");
238 opt = "-rotate180";
239 }
240 else
241 {
242 return nerr_raise(NERR_ASSERT, "currently only support 90/-90/180 rotations");
243 }
244 if (is_jpeg)
245 {
246 strcat(rpath, ".jpg");
247 snprintf(cmd, sizeof(cmd), "djpeg -pnm %s | pnmflip %s | cjpeg -quality 85 > %s", ofile, opt, rpath);
248 }
249 else
250 {
251 strcat(rpath, ".gif");
252 snprintf(cmd, sizeof(cmd), "giftopnm %s | pnmflip %s | ppmtogif > %s", ofile, opt, rpath);
253 }
254 /* already exists? */
255 if (!stat(rpath, &s))
256 {
257 return STATUS_OK;
258 }
259 r = system(cmd);
260 if (r) return nerr_raise_errno (NERR_SYSTEM, "%s returned %d", cmd, r);
261 /* always save off the old file */
262 snprintf (nfile, sizeof(nfile), "%s/%s.orig", path, file);
263 if (stat(nfile, &s))
264 {
265 if (link(ofile, nfile))
266 return nerr_raise_errno (NERR_SYSTEM, "Unable to link %s -> %s", ofile, nfile);
267 unlink(ofile);
268 }
269 return STATUS_OK;
270 }
271
scale_and_display_image(char * fname,int maxW,int maxH,char * cachepath,int quality)272 NEOERR *scale_and_display_image(char *fname,int maxW,int maxH,char *cachepath,
273 int quality)
274 {
275 NEOERR *err = STATUS_OK;
276 /* Declare the image */
277 gdImagePtr src_im = 0;
278 /* Declare input file */
279 FILE *infile=0, *cachefile=0;
280 int srcX,srcY,srcW,srcH;
281 FILE *dispfile=0;
282 struct stat s;
283
284 /* if we can open the cachepath, then just print it */
285 if (!stat(cachepath, &s) && s.st_size)
286 cachefile = fopen(cachepath,"rb");
287 if (cachefile) {
288 /* we should probably stat the files and make sure the thumbnail
289 is current */
290 /* fprintf(stderr,"using cachefile: %s\n",cachepath); */
291 dispfile = cachefile;
292 } else {
293 char cmd[1024];
294 int factor=1;
295 int l;
296 int is_jpeg = 0, is_gif = 0;
297
298 l = strlen(fname);
299 if ((l>4 && !strcasecmp(fname+l-4, ".jpg")) ||
300 (l>4 && !strcasecmp(fname+l-4, ".thm")) ||
301 (l>5 && !strcasecmp(fname+l-5, ".jpeg")))
302 is_jpeg = 1;
303 else if (l>4 && !strcasecmp(fname+l-4, ".gif"))
304 is_gif = 1;
305
306
307 if (is_jpeg)
308 {
309 if (!quality)
310 {
311 if (!jpeg_size (fname, &srcW, &srcH))
312 {
313 if ((srcW > maxW) || (srcH > maxH))
314 {
315 factor = 2;
316 if (srcW / factor > maxW)
317 {
318 factor = 4;
319 if (srcW / factor > maxW)
320 factor = 8;
321 }
322 }
323 }
324
325 /* ne_warn("factor %d\n", factor); */
326 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);
327
328 create_directories(cachepath);
329 system(cmd);
330 if (!stat(cachepath, &s) && s.st_size)
331 cachefile = fopen(cachepath,"rb");
332 else
333 ne_warn("external command failed to create file\n");
334 }
335 if (cachefile) {
336 dispfile = cachefile;
337
338 } else /* no cachefile */ {
339
340
341 /* fprintf(stderr,"reading image\n"); */
342 /* Read the image in */
343 infile = fopen(fname,"rb");
344 src_im = gdImageCreateFromJpeg(infile);
345 srcX=0; srcY=0; srcW=src_im->sx; srcH=src_im->sy;
346
347
348 /* figure out if we need to scale it */
349
350 if ((maxW && srcW > maxW) || (maxH && srcH > maxH)) {
351 /* scale paramaters */
352 int dstX,dstY,dstW,dstH;
353 /* Declare output file */
354 FILE *jpegout;
355 gdImagePtr dest_im;
356 float srcAspect,dstAspect;
357
358 /* create the destination image */
359
360 dstX=0; dstY=0;
361
362
363 srcAspect = ((float)srcW/(float)srcH);
364 dstAspect = ((float)maxW/(float)maxH);
365
366 if (srcAspect == dstAspect) {
367 /* they are the same aspect ratio */
368 dstW = maxW;
369 dstH = maxH;
370 } else if ( srcAspect > dstAspect ) {
371 /* if the src image has wider aspect ratio than the max */
372 dstW = maxW;
373 dstH = (int) ( ((float)dstW/(float)srcW) * srcH );
374 } else {
375 /* if the src image has taller aspect ratio than the max */
376 dstH = maxW;
377 dstW = (int) ( ((float)dstH/(float)srcH) * srcW );
378 }
379
380 #ifdef GD2_VERS
381 dest_im = gdImageCreateTrueColor(dstW,dstH);
382 #else
383 dest_im = gdImageCreate(dstW,dstH);
384 #endif
385
386 /* fprintf(stderr,"scaling to (%d,%d)\n",dstW,dstH); */
387
388 /* Scale it to the destination image */
389
390 gdImageCopyResized(dest_im,src_im,dstX,dstY,srcX,srcY,dstW,dstH,srcW,srcH);
391
392 /* fprintf(stderr,"scaling finished\n"); */
393
394 /* write the output image */
395 create_directories(cachepath);
396 jpegout = fopen(cachepath,"wb+");
397 if (!jpegout) {
398 jpegout = fopen("/tmp/foobar.jpg","wb+");
399 }
400 if (jpegout) {
401 gdImageJpeg(dest_im,jpegout,-1);
402 fflush(jpegout);
403
404 /* now print that data out the stream */
405 dispfile = jpegout;
406 } else {
407 return nerr_raise_errno(NERR_IO, "Unable to create output file: %s", cachepath);
408 }
409
410
411 gdImageDestroy(dest_im);
412
413 } else {
414 /* just print the input file because it's small enough */
415 dispfile = infile;
416 }
417
418 }
419 }
420 else if (is_gif)
421 {
422 float scale = 1.0;
423 if (!gif_size (fname, &srcW, &srcH))
424 {
425 if ((srcW > maxW) || (srcH > maxH))
426 {
427 scale = 0.5;
428 if (srcW * scale > maxW)
429 {
430 scale = 0.25;
431 if (srcW * scale > maxW)
432 factor = 0.125;
433 }
434 }
435 }
436
437 if (scale < 1.0)
438 {
439 snprintf (cmd, sizeof(cmd), "/usr/bin/giftopnm '%s' | /usr/bin/pnmscale %5.3f | ppmquant 256 | ppmtogif > '%s'", fname, scale, cachepath);
440
441 create_directories(cachepath);
442 system(cmd);
443 dispfile = fopen(cachepath,"rb");
444 if (dispfile == NULL)
445 return nerr_raise_errno(NERR_IO, "Unable to open file: %s", cachepath);
446
447 }
448 else
449 {
450 dispfile = fopen(fname, "rb");
451 if (dispfile == NULL)
452 return nerr_raise_errno(NERR_IO, "Unable to open file: %s", fname);
453 }
454 }
455 else {
456 dispfile = fopen(fname,"rb");
457 }
458 }
459
460 /* the data in "dispfile" is going to be printed now */
461 {
462
463 char buf[8192];
464 int count;
465
466 if (!fstat(fileno(dispfile), &s) && s.st_size)
467 {
468 cgiwrap_writef("Content-Length: %ld\n\n", s.st_size);
469 }
470 else
471 {
472 cgiwrap_writef("\n");
473 }
474
475 fseek(dispfile,0,SEEK_SET);
476
477 do {
478 count = fread(buf,1,sizeof(buf),dispfile);
479 if (count > 0) {
480 err = cgiwrap_write(buf,count);
481 }
482 } while (count > 0);
483
484 }
485
486 if (dispfile) fclose(dispfile);
487 if (src_im) gdImageDestroy(src_im);
488
489 return nerr_pass(err);
490 }
491
load_images(char * path,ULIST ** rfiles,char * partial,int descend)492 NEOERR *load_images (char *path, ULIST **rfiles, char *partial, int descend)
493 {
494 NEOERR *err = STATUS_OK;
495 DIR *dp;
496 struct dirent *de;
497 int is_jpeg, is_gif, l;
498 char fpath[_POSIX_PATH_MAX];
499 char ppath[_POSIX_PATH_MAX];
500 ULIST *files = NULL;
501
502 if ((dp = opendir (path)) == NULL)
503 {
504 return nerr_raise(NERR_IO, "Unable to opendir %s: [%d] %s", path, errno,
505 strerror(errno));
506 }
507
508 if (rfiles == NULL || *rfiles == NULL)
509 {
510 err = uListInit(&files, 50, 0);
511 if (err) return nerr_pass(err);
512 *rfiles = files;
513 }
514 else
515 {
516 files = *rfiles;
517 }
518
519 while ((de = readdir (dp)) != NULL)
520 {
521 if (de->d_name[0] != '.')
522 {
523 snprintf(fpath, sizeof(fpath), "%s/%s", path, de->d_name);
524 if (partial)
525 {
526 snprintf(ppath, sizeof(ppath), "%s/%s", partial, de->d_name);
527 }
528 else
529 {
530 strncpy(ppath, de->d_name, sizeof(ppath));
531 }
532 if (descend && isdir(fpath))
533 {
534 err = load_images(fpath, rfiles, ppath, descend);
535 if (err) break;
536 }
537 else
538 {
539 l = strlen(de->d_name);
540 is_jpeg = 0; is_gif = 0;
541
542 if ((l>4 && !strcasecmp(de->d_name+l-4, ".jpg")) ||
543 (l>4 && !strcasecmp(de->d_name+l-4, ".thm")) ||
544 (l>5 && !strcasecmp(de->d_name+l-5, ".jpeg")))
545 is_jpeg = 1;
546 else if (l>4 && !strcasecmp(de->d_name+l-4, ".gif"))
547 is_gif = 1;
548
549 if (is_gif || is_jpeg)
550 {
551 err = uListAppend(files, strdup(ppath));
552 if (err) break;
553 }
554 }
555 }
556 }
557 closedir(dp);
558 if (err)
559 {
560 uListDestroy(&files, ULIST_FREE);
561 }
562 else
563 {
564 *rfiles = files;
565 }
566 return nerr_pass(err);
567 }
568
export_image(CGI * cgi,char * prefix,char * path,char * file)569 NEOERR *export_image(CGI *cgi, char *prefix, char *path, char *file)
570 {
571 NEOERR *err;
572 char buf[256];
573 char num[20];
574 int i = 0;
575 int r, l;
576 int width, height;
577 char ipath[_POSIX_PATH_MAX];
578 int is_jpeg = 0, is_gif = 0, is_thm = 0;
579
580 l = strlen(file);
581 if ((l>4 && !strcasecmp(file+l-4, ".jpg")) ||
582 (l>5 && !strcasecmp(file+l-5, ".jpeg")))
583 is_jpeg = 1;
584 else if (l>4 && !strcasecmp(file+l-4, ".gif"))
585 is_gif = 1;
586 else if (l>4 && !strcasecmp(file+l-4, ".thm"))
587 is_thm = 1;
588
589 snprintf (buf, sizeof(buf), "%s.%d", prefix, i);
590 err = hdf_set_value (cgi->hdf, prefix, file);
591 if (err != STATUS_OK) return nerr_pass(err);
592 snprintf (ipath, sizeof(ipath), "%s/%s", path, file);
593 if (is_jpeg || is_thm)
594 r = jpeg_size(ipath, &width, &height);
595 else
596 r = gif_size(ipath, &width, &height);
597 if (!r)
598 {
599 snprintf (buf, sizeof(buf), "%s.width", prefix);
600 snprintf (num, sizeof(num), "%d", width);
601 err = hdf_set_value (cgi->hdf, buf, num);
602 if (err != STATUS_OK) return nerr_pass(err);
603 snprintf (buf, sizeof(buf), "%s.height", prefix);
604 snprintf (num, sizeof(num), "%d", height);
605 err = hdf_set_value (cgi->hdf, buf, num);
606 if (err != STATUS_OK) return nerr_pass(err);
607 }
608 if (is_thm)
609 {
610 strcpy(ipath, file);
611 strcpy(ipath+l-4, ".avi");
612 snprintf(buf, sizeof(buf), "%s.avi", prefix);
613 err = hdf_set_value (cgi->hdf, buf, ipath);
614 if (err != STATUS_OK) return nerr_pass(err);
615 }
616 return STATUS_OK;
617 }
618
scale_images(CGI * cgi,char * prefix,int width,int height,int force)619 NEOERR *scale_images (CGI *cgi, char *prefix, int width, int height, int force)
620 {
621 NEOERR *err;
622 char num[20];
623 HDF *obj;
624 int i, x;
625 int factor;
626
627 obj = hdf_get_obj (cgi->hdf, prefix);
628 if (obj) obj = hdf_obj_child (obj);
629 while (obj)
630 {
631 factor = 1;
632 i = hdf_get_int_value(obj, "height", -1);
633 if (i != -1)
634 {
635 x = i;
636 while (x > height)
637 {
638 /* factor = factor * 2;*/
639 factor++;
640 x = i / factor;
641 }
642 snprintf (num, sizeof(num), "%d", x);
643 err = hdf_set_value (obj, "height", num);
644 if (err != STATUS_OK) return nerr_pass (err);
645
646 i = hdf_get_int_value(obj, "width", -1);
647 if (i != -1)
648 {
649 i = i / factor;
650 snprintf (num, sizeof(num), "%d", i);
651 err = hdf_set_value (obj, "width", num);
652 if (err != STATUS_OK) return nerr_pass (err);
653 }
654 }
655 else
656 {
657 snprintf (num, sizeof(num), "%d", height);
658 err = hdf_set_value (obj, "height", num);
659 if (err != STATUS_OK) return nerr_pass (err);
660 snprintf (num, sizeof(num), "%d", width);
661 err = hdf_set_value (obj, "width", num);
662 if (err != STATUS_OK) return nerr_pass (err);
663 }
664 obj = hdf_obj_next(obj);
665 }
666 return STATUS_OK;
667 }
668
alpha_sort(const void * a,const void * b)669 int alpha_sort(const void *a, const void *b)
670 {
671 char **sa = (char **)a;
672 char **sb = (char **)b;
673
674 /* ne_warn("%s %s: %d", *sa, *sb, strcmp(*sa, *sb)); */
675
676 return strcmp(*sa, *sb);
677 }
678
export_album_path(CGI * cgi,char * album,char * prefix)679 static NEOERR *export_album_path(CGI *cgi, char *album, char *prefix)
680 {
681 NEOERR *err = STATUS_OK;
682 char *p, *l;
683 int n = 0;
684 char buf[256];
685
686 l = album;
687 p = strchr(album, '/');
688
689 while (p != NULL)
690 {
691 *p = '\0';
692 snprintf(buf, sizeof(buf), "%s.%d", prefix, n);
693 err = hdf_set_value(cgi->hdf, buf, l);
694 if (err) break;
695 snprintf(buf, sizeof(buf), "%s.%d.path", prefix, n++);
696 err = hdf_set_value(cgi->hdf, buf, album);
697 if (err) break;
698 *p = '/';
699 l = p+1;
700 p = strchr(l, '/');
701 }
702 if (err) return nerr_pass(err);
703 if (strlen(l))
704 {
705 snprintf(buf, sizeof(buf), "%s.%d", prefix, n);
706 err = hdf_set_value(cgi->hdf, buf, l);
707 if (err) return nerr_pass(err);
708 snprintf(buf, sizeof(buf), "%s.%d.path", prefix, n++);
709 err = hdf_set_value(cgi->hdf, buf, album);
710 if (err) return nerr_pass(err);
711 }
712
713 return STATUS_OK;
714 }
715
716
dowork_picture(CGI * cgi,char * album,char * picture)717 NEOERR *dowork_picture (CGI *cgi, char *album, char *picture)
718 {
719 NEOERR *err = STATUS_OK;
720 char *base, *name;
721 char path[_POSIX_PATH_MAX];
722 char buf[256];
723 int i, x, factor, y;
724 int thumb_width, thumb_height;
725 int pic_width, pic_height;
726 ULIST *files = NULL;
727 char t_album[_POSIX_PATH_MAX];
728 char t_pic[_POSIX_PATH_MAX];
729 char nfile[_POSIX_PATH_MAX];
730 char *ch;
731 char *avi = NULL;
732 int rotate;
733
734 ch = strrchr(picture, '/');
735 if (ch != NULL)
736 {
737 *ch = '\0';
738 snprintf(t_album, sizeof(t_album), "%s/%s", album, picture);
739 *ch = '/';
740 strncpy(t_pic, ch+1, sizeof(t_pic));
741 picture = t_pic;
742 album = t_album;
743 }
744
745 base = hdf_get_value (cgi->hdf, "BASEDIR", NULL);
746 if (base == NULL)
747 {
748 cgi_error (cgi, "No BASEDIR in imd file");
749 return nerr_raise(CGIFinished, "Finished");
750 }
751
752 thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
753 thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
754 pic_width = hdf_get_int_value (cgi->hdf, "PictureWidth", 120);
755 pic_height = hdf_get_int_value (cgi->hdf, "PictureWidth", 90);
756
757 err = hdf_set_value (cgi->hdf, "Context", "picture");
758 if (err != STATUS_OK) return nerr_pass(err);
759
760 snprintf (path, sizeof(path), "%s/%s", base, album);
761 rotate = hdf_get_int_value(cgi->hdf, "Query.rotate", 0);
762 if (rotate)
763 {
764 err = rotate_image(path, picture, rotate, nfile);
765 if (err) return nerr_pass(err);
766 picture = strrchr(nfile, '/') + 1;
767 }
768
769 err = hdf_set_value (cgi->hdf, "Album", album);
770 if (err != STATUS_OK) return nerr_pass(err);
771 err = hdf_set_value (cgi->hdf, "Album.Raw", album);
772 if (err != STATUS_OK) return nerr_pass(err);
773 err = export_album_path(cgi, album, "Album.Path");
774 if (err) return nerr_pass(err);
775 err = hdf_set_value (cgi->hdf, "Picture", picture);
776 if (err != STATUS_OK) return nerr_pass(err);
777
778 err = load_images(path, &files, NULL, 0);
779 if (err != STATUS_OK) return nerr_pass(err);
780 err = uListSort(files, alpha_sort);
781 if (err != STATUS_OK) return nerr_pass(err);
782
783 i = -1;
784 for (x = 0; x < uListLength(files); x++)
785 {
786 err = uListGet(files, x, (void *)&name);
787 if (err) break;
788 if (!strcmp(name, picture))
789 {
790 i = x;
791 break;
792 }
793 }
794 if (i != -1)
795 {
796 for (x = 2; x > 0; x--)
797 {
798 if (i - x < 0) continue;
799 err = uListGet(files, i-x, (void *)&name);
800 if (err) break;
801 snprintf(buf, sizeof(buf), "Show.%d", i-x);
802 err = export_image(cgi, buf, path, name);
803 if (err) break;
804 }
805 for (x = 0; x < 3; x++)
806 {
807 if (i + x > uListLength(files)) break;
808 err = uListGet(files, i+x, (void *)&name);
809 if (err) break;
810 snprintf(buf, sizeof(buf), "Show.%d", i+x);
811 err = export_image(cgi, buf, path, name);
812 if (err) break;
813 }
814 snprintf (buf, sizeof(buf), "Show.%d.width", i);
815 x = hdf_get_int_value (cgi->hdf, buf, -1);
816 if (x != -1)
817 {
818 factor = 1;
819 y = x;
820 while (y > pic_width)
821 {
822 factor = factor * 2;
823 /* factor++; */
824 y = x / factor;
825 ne_warn("factor = %d, y = %d", factor, y);
826 }
827 snprintf (buf, sizeof(buf), "%d", y);
828 hdf_set_value (cgi->hdf, "Picture.width", buf);
829 snprintf (buf, sizeof(buf), "Show.%d.height", i);
830 x = hdf_get_int_value (cgi->hdf, buf, -1);
831 y = x / factor;
832 snprintf (buf, sizeof(buf), "%d", y);
833 hdf_set_value (cgi->hdf, "Picture.height", buf);
834 }
835 else
836 {
837 snprintf (buf, sizeof(buf), "%d", pic_width);
838 hdf_set_value (cgi->hdf, "Picture.width", buf);
839 snprintf (buf, sizeof(buf), "%d", pic_height);
840 hdf_set_value (cgi->hdf, "Picture.height", buf);
841 }
842 snprintf (buf, sizeof(buf), "Show.%d.avi", i);
843 avi = hdf_get_value (cgi->hdf, buf, NULL);
844 if (avi)
845 {
846 err = hdf_set_value(cgi->hdf, "Picture.avi", avi);
847 }
848
849 err = scale_images (cgi, "Show", thumb_width, thumb_height, 0);
850 }
851 uListDestroy(&files, ULIST_FREE);
852
853 return nerr_pass(err);
854 }
855
is_album(void * rock,char * filename)856 static int is_album(void *rock, char *filename)
857 {
858 char path[_POSIX_PATH_MAX];
859 char *prefix = (char *)rock;
860
861 if (filename[0] == '.') return 0;
862 snprintf(path, sizeof(path), "%s/%s", prefix, filename);
863 if (isdir(path)) return 1;
864 return 0;
865 }
866
dowork_album_overview(CGI * cgi,char * album)867 NEOERR *dowork_album_overview (CGI *cgi, char *album)
868 {
869 NEOERR *err = STATUS_OK;
870 DIR *dp;
871 struct dirent *de;
872 char path[_POSIX_PATH_MAX];
873 char buf[256];
874 int i = 0, x, y;
875 int thumb_width, thumb_height;
876 ULIST *files = NULL;
877 ULIST *albums = NULL;
878 char *name;
879
880 thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
881 thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
882
883 err = ne_listdir_fmatch(album, &albums, is_album, album);
884 if (err) return nerr_pass(err);
885
886
887 err = uListSort(albums, alpha_sort);
888 if (err) return nerr_pass(err);
889 for (y = 0; y < uListLength(albums); y++)
890 {
891 err = uListGet(albums, y, (void *)&name);
892 if (err) break;
893
894 snprintf(path, sizeof(path), "%s/%s", album, name);
895 snprintf(buf, sizeof(buf), "Albums.%d", i);
896 err = hdf_set_value (cgi->hdf, buf, name);
897 if (err != STATUS_OK) break;
898 err = load_images(path, &files, NULL, 1);
899 if (err != STATUS_OK) break;
900 err = uListSort(files, alpha_sort);
901 if (err != STATUS_OK) break;
902 snprintf(buf, sizeof(buf), "Albums.%d.Count", i);
903 err = hdf_set_int_value(cgi->hdf, buf, uListLength(files));
904 if (err != STATUS_OK) break;
905 for (x = 0; (x < 4) && (x < uListLength(files)); x++)
906 {
907 err = uListGet(files, x, (void *)&name);
908 if (err) break;
909 snprintf(buf, sizeof(buf), "Albums.%d.Images.%d", i, x);
910 err = export_image(cgi, buf, path, name);
911 if (err) break;
912 }
913 uListDestroy(&files, ULIST_FREE);
914 if (err != STATUS_OK) break;
915 snprintf(buf, sizeof(buf), "Albums.%d.Images", i);
916 err = scale_images (cgi, buf, thumb_width, thumb_height, 0);
917 if (err != STATUS_OK) break;
918 i++;
919 }
920 return nerr_pass(err);
921 }
922
dowork_album(CGI * cgi,char * album)923 NEOERR *dowork_album (CGI *cgi, char *album)
924 {
925 NEOERR *err;
926 char *base;
927 char buf[256];
928 char path[_POSIX_PATH_MAX];
929 int thumb_width, thumb_height;
930 int per_page, start, next, prev, last;
931 ULIST *files = NULL;
932 char *name;
933 int x;
934
935 base = hdf_get_value (cgi->hdf, "BASEDIR", NULL);
936 if (base == NULL)
937 {
938 cgi_error (cgi, "No BASEDIR in imd file");
939 return nerr_raise(CGIFinished, "Finished");
940 }
941 thumb_width = hdf_get_int_value (cgi->hdf, "ThumbWidth", 120);
942 thumb_height = hdf_get_int_value (cgi->hdf, "ThumbWidth", 90);
943 per_page = hdf_get_int_value (cgi->hdf, "PerPage", 50);
944 start = hdf_get_int_value (cgi->hdf, "Query.start", 0);
945
946 err = hdf_set_value (cgi->hdf, "Album", album);
947 if (err != STATUS_OK) return nerr_pass(err);
948 err = hdf_set_value (cgi->hdf, "Album.Raw", album);
949 if (err != STATUS_OK) return nerr_pass(err);
950 err = export_album_path(cgi, album, "Album.Path");
951 if (err) return nerr_pass(err);
952
953
954 err = hdf_set_value (cgi->hdf, "Context", "album");
955 if (err != STATUS_OK) return nerr_pass(err);
956
957
958 snprintf (path, sizeof(path), "%s/%s", base, album);
959 err = dowork_album_overview(cgi, path);
960 if (err != STATUS_OK) return nerr_pass(err);
961
962 err = load_images(path, &files, NULL, 0);
963 if (err != STATUS_OK) return nerr_pass (err);
964 err = uListSort(files, alpha_sort);
965 if (err != STATUS_OK) return nerr_pass (err);
966 err = hdf_set_int_value(cgi->hdf, "Album.Count", uListLength(files));
967 if (err != STATUS_OK) return nerr_pass (err);
968 if (start > uListLength(files)) start = 0;
969 next = start + per_page;
970 if (next > uListLength(files)) next = uListLength(files);
971 prev = start - per_page;
972 if (prev < 0) prev = 0;
973 last = uListLength(files) - per_page;
974 if (last < 0) last = 0;
975 err = hdf_set_int_value(cgi->hdf, "Album.Start", start);
976 if (err != STATUS_OK) return nerr_pass (err);
977 err = hdf_set_int_value(cgi->hdf, "Album.Next", next);
978 if (err != STATUS_OK) return nerr_pass (err);
979 err = hdf_set_int_value(cgi->hdf, "Album.Prev", prev);
980 if (err != STATUS_OK) return nerr_pass (err);
981 err = hdf_set_int_value(cgi->hdf, "Album.Last", last);
982 if (err != STATUS_OK) return nerr_pass (err);
983 for (x = start; x < next; x++)
984 {
985 err = uListGet(files, x, (void *)&name);
986 if (err) break;
987 snprintf(buf, sizeof(buf), "Images.%d", x);
988 err = export_image(cgi, buf, path, name);
989 if (err) break;
990 }
991 uListDestroy(&files, ULIST_FREE);
992 if (err != STATUS_OK) return nerr_pass (err);
993 err = scale_images (cgi, "Images", thumb_width, thumb_height, 0);
994 if (err != STATUS_OK) return nerr_pass (err);
995 return STATUS_OK;
996 }
997
dowork_image(CGI * cgi,char * image)998 NEOERR *dowork_image (CGI *cgi, char *image)
999 {
1000 NEOERR *err = STATUS_OK;
1001 int maxW = 0, maxH = 0;
1002 char *basepath = "";
1003 char *cache_basepath = "/tmp/.imgcache/";
1004 char srcpath[_POSIX_PATH_MAX] = "";
1005 char cachepath[_POSIX_PATH_MAX] = "";
1006 char buf[256];
1007 char *if_mod;
1008 int i, l, quality;
1009 struct stat s;
1010 struct tm *t;
1011
1012 if ((i = hdf_get_int_value(cgi->hdf, "Query.width", 0)) != 0) {
1013 maxW = i;
1014 }
1015
1016 if ((i = hdf_get_int_value(cgi->hdf, "Query.height", 0)) != 0) {
1017 maxH = i;
1018 }
1019 quality = hdf_get_int_value(cgi->hdf, "Query.quality", 0);
1020
1021 if_mod = hdf_get_value(cgi->hdf, "HTTP.IfModifiedSince", NULL);
1022
1023 basepath = hdf_get_value(cgi->hdf, "BASEDIR", NULL);
1024 if (basepath == NULL)
1025 {
1026 cgi_error (cgi, "No BASEDIR in imd file");
1027 return nerr_raise(CGIFinished, "Finished");
1028 }
1029
1030 snprintf (srcpath, sizeof(srcpath), "%s/%s", basepath, image);
1031 snprintf (cachepath, sizeof(cachepath), "%s/%dx%d/%s", cache_basepath,
1032 maxW, maxH,image);
1033
1034 if (stat(srcpath, &s))
1035 {
1036 cgiwrap_writef("Status: 404\nContent-Type: text/html\n\n");
1037 cgiwrap_writef("File %s not found.", srcpath);
1038 return nerr_raise_errno(NERR_IO, "Unable to stat file %s", srcpath);
1039 }
1040
1041 t = gmtime(&(s.st_mtime));
1042 if (if_mod && later_than(t, if_mod))
1043 {
1044 cgiwrap_writef("Status: 304\nContent-Type: text/html\n\n");
1045 cgiwrap_writef("Use Local Copy");
1046 return STATUS_OK;
1047 }
1048
1049 /* fprintf(stderr,"cachepath: %s\n",cachepath); */
1050
1051 ne_warn("srcpath: %s", srcpath);
1052 l = strlen(srcpath);
1053 if ((l>4 && !strcasecmp(srcpath+l-4, ".jpg")) ||
1054 (l>4 && !strcasecmp(srcpath+l-4, ".thm")) ||
1055 (l>5 && !strcasecmp(srcpath+l-5, ".jpeg")))
1056 cgiwrap_writef("Content-Type: image/jpeg\n");
1057 else if (l>4 && !strcasecmp(srcpath+l-4, ".gif"))
1058 cgiwrap_writef("Content-Type: image/gif\n");
1059 else if (l>4 && !strcasecmp(srcpath+l-4, ".avi"))
1060 {
1061 ne_warn("found avi");
1062 cgiwrap_writef("Content-Type: video/x-msvideo\n");
1063 }
1064 t = gmtime(&(s.st_mtime));
1065 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", t);
1066 cgiwrap_writef("Last-modified: %s\n", buf);
1067
1068 err = scale_and_display_image(srcpath,maxW,maxH,cachepath,quality);
1069 return nerr_pass(err);
1070 }
1071
main(int argc,char ** argv,char ** envp)1072 int main(int argc, char **argv, char **envp)
1073 {
1074 NEOERR *err;
1075 CGI *cgi;
1076 char *image;
1077 char *album;
1078 char *imd_file;
1079 char *cs_file;
1080 char *picture;
1081
1082 ne_warn("Starting IMD");
1083 cgi_debug_init (argc,argv);
1084 cgiwrap_init_std (argc, argv, envp);
1085
1086 nerr_init();
1087
1088 ne_warn("CGI init");
1089 err = cgi_init(&cgi, NULL);
1090 if (err != STATUS_OK)
1091 {
1092 nerr_log_error(err);
1093 cgi_destroy(&cgi);
1094 return -1;
1095 }
1096 imd_file = hdf_get_value(cgi->hdf, "CGI.PathTranslated", NULL);
1097 ne_warn("Reading IMD file %s", imd_file);
1098 err = hdf_read_file (cgi->hdf, imd_file);
1099 if (err != STATUS_OK)
1100 {
1101 cgi_neo_error(cgi, err);
1102 nerr_log_error(err);
1103 cgi_destroy(&cgi);
1104 return -1;
1105 }
1106
1107 cs_file = hdf_get_value(cgi->hdf, "Template", NULL);
1108 image = hdf_get_value(cgi->hdf, "Query.image", NULL);
1109 album = hdf_get_value(cgi->hdf, "Query.album", "");
1110 picture = hdf_get_value(cgi->hdf, "Query.picture", NULL);
1111 if (image)
1112 {
1113 err = dowork_image(cgi, image);
1114 if (err)
1115 {
1116 nerr_log_error(err);
1117 cgi_destroy(&cgi);
1118 return -1;
1119 }
1120 }
1121 else
1122 {
1123 if (!picture)
1124 {
1125 err = dowork_album (cgi, album);
1126 }
1127 else
1128 {
1129 err = dowork_picture (cgi, album, picture);
1130 }
1131 if (err != STATUS_OK)
1132 {
1133 if (nerr_handle(&err, CGIFinished))
1134 {
1135 /* pass */
1136 }
1137 else
1138 {
1139 cgi_neo_error(cgi, err);
1140 nerr_log_error(err);
1141 cgi_destroy(&cgi);
1142 return -1;
1143 }
1144 }
1145 else
1146 {
1147 err = cgi_display(cgi, cs_file);
1148 if (err != STATUS_OK)
1149 {
1150 cgi_neo_error(cgi, err);
1151 nerr_log_error(err);
1152 cgi_destroy(&cgi);
1153 return -1;
1154 }
1155 }
1156 }
1157 cgi_destroy(&cgi);
1158 return 0;
1159 }
1160