From 89c58dc04c264c5778ae34d1428e12483f3ac5ac Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Thu, 26 Feb 2009 22:50:39 +0100 Subject: Autotoolize --- .gitignore | 20 + AUTHORS | 0 ChangeLog | 0 INSTALL | 0 Makefile | 43 -- Makefile.am | 18 + NEWS | 0 README | 2 +- autogen.sh | 89 ++++ cgg-dirgen | 54 --- cgg.c | 153 ------ config.h | 30 -- configure.ac | 103 ++++ gallery-utils.c | 262 ---------- gallery-utils.h | 53 -- generators-replace-table.c | 174 ------- generators-replace-table.h | 63 --- generators.c | 1035 --------------------------------------- generators.h | 64 --- items.c | 320 ------------- items.h | 96 ---- jpeg-utils.cpp | 429 ----------------- jpeg-utils.h | 94 ---- setup.c | 266 ----------- setup.h | 92 ---- src/Makefile.am | 41 ++ src/cgg-config.h | 30 ++ src/cgg-dirgen | 54 +++ src/cgg.c | 155 ++++++ src/gallery-utils.c | 262 ++++++++++ src/gallery-utils.h | 53 ++ src/generators-replace-table.c | 174 +++++++ src/generators-replace-table.h | 63 +++ src/generators.c | 1037 ++++++++++++++++++++++++++++++++++++++++ src/generators.h | 64 +++ src/items.c | 320 +++++++++++++ src/items.h | 96 ++++ src/jpeg-utils.cpp | 429 +++++++++++++++++ src/jpeg-utils.h | 94 ++++ src/setup.c | 268 +++++++++++ src/setup.h | 92 ++++ src/xml-parser.c | 261 ++++++++++ src/xml-parser.h | 67 +++ xml-parser.c | 261 ---------- xml-parser.h | 67 --- 45 files changed, 3791 insertions(+), 3557 deletions(-) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 INSTALL delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100644 NEWS create mode 100755 autogen.sh delete mode 100755 cgg-dirgen delete mode 100644 cgg.c delete mode 100644 config.h create mode 100644 configure.ac delete mode 100644 gallery-utils.c delete mode 100644 gallery-utils.h delete mode 100644 generators-replace-table.c delete mode 100644 generators-replace-table.h delete mode 100644 generators.c delete mode 100644 generators.h delete mode 100644 items.c delete mode 100644 items.h delete mode 100644 jpeg-utils.cpp delete mode 100644 jpeg-utils.h delete mode 100644 setup.c delete mode 100644 setup.h create mode 100644 src/Makefile.am create mode 100644 src/cgg-config.h create mode 100755 src/cgg-dirgen create mode 100644 src/cgg.c create mode 100644 src/gallery-utils.c create mode 100644 src/gallery-utils.h create mode 100644 src/generators-replace-table.c create mode 100644 src/generators-replace-table.h create mode 100644 src/generators.c create mode 100644 src/generators.h create mode 100644 src/items.c create mode 100644 src/items.h create mode 100644 src/jpeg-utils.cpp create mode 100644 src/jpeg-utils.h create mode 100644 src/setup.c create mode 100644 src/setup.h create mode 100644 src/xml-parser.c create mode 100644 src/xml-parser.h delete mode 100644 xml-parser.c delete mode 100644 xml-parser.h diff --git a/.gitignore b/.gitignore index 6e80970..a664f3c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,25 @@ sample/dst/ web/ sample-single/ validation/ +Makefile +Makefile.in +Makefile.old +aclocal.m4 +autom4te.cache/ +compile +config.guess +config.h +config.h.in +config.h.in~ +config.log +config.status +config.sub +configure +depcomp +install-sh +missing +stamp-h1 +src/.deps/ +src/Makefile *.o diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile deleted file mode 100644 index 930e25d..0000000 --- a/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# path definitions -INSTALLPREFIX = /usr -INSTALL=/usr/bin/install -c -INSTALL_DATA = ${INSTALL} -m 644 - -# compiler options -CC = gcc -CPP = g++ -CFLAGS = -I. -I/usr/include -Wall -fPIC -g \ - -D__DEBUG__ -D__DEBUG_ALL__x - -OBJECTS=gallery-utils.o jpeg-utils.o xml-parser.o setup.o items.o generators.o generators-replace-table.o cgg.o - -EXIV2_CFLAGS_EXTRA=`pkg-config --max-version=0.17.1 exiv2 || echo -D_EXIV2_NEW_API` - -.SUFFIXES: .c .cpp -.c.o: - $(CC) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 --cflags` `Wand-config --cflags` $(EXIV2_CFLAGS_EXTRA) -c $< -.cpp.o: - $(CPP) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 exiv2 --cflags` `Wand-config --cppflags` $(EXIV2_CFLAGS_EXTRA) -c $< - -all cgg: check $(OBJECTS) - $(CC) -o cgg $(OBJECTS) -lm $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 exiv2 --libs` `Wand-config --ldflags --libs` - -cgg.o: cgg.c -jpeg-utils.o: jpeg-utils.cpp jpeg-utils.h -gallery-utils.o: gallery-utils.c gallery-utils.h -setup.o: setup.c setup.h -xml-parser.o: xml-parser.c xml-parser.h -items.o: items.c items.h -generators.o: generators.c generators.h -generators-replace-table.o: generators-replace-table.c generators-replace-table.h - -check:: - @pkg-config --cflags libxml-2.0 glib-2.0 exiv2 > /dev/null || exit 1 - @Wand-config --cflags > /dev/null || exit 1 - -install:: - $(INSTALL) ./cgg $(INSTALLPREFIX)/bin - -clean: - rm -f *.o *.d cgg - diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..851db70 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = \ + src + +EXTRA_DIST = \ + intltool-extract.in \ + intltool-update.in \ + intltool-merge.in + +CLEANFILES = + +DISTCLEANFILES = \ + intltool-extract \ + intltool-update \ + intltool-merge \ + po/.intltool-merge-cache + + +ACLOCAL_AMFLAGS = -I m4 diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README index a3bd358..f00b9e4 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ CATARACT Static web photo gallery generator http://cgg.bzatek.net/ -version 0.99.1 [2009-01-11] +version 0.99.2 [2009-02-26] Copyright (C) 2008-2009 Tomas Bzatek diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..4de7bb5 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,89 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir +PROJECT=cataract +TEST_TYPE=-f +FILE=src/cgg.c + +DIE=0 + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $PROJECT." + echo "Install the appropriate package for your distribution," + echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/" + DIE=1 +} + +if automake --version < /dev/null > /dev/null 2>&1 ; then + AUTOMAKE=automake + ACLOCAL=aclocal +else + echo + echo "You must have automake 1.7.x installed to compile $PROJECT." + echo "Install the appropriate package for your distribution," + echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/" + DIE=1 +fi + +if test "$DIE" -eq 1; then + exit 1 +fi + +test $TEST_TYPE $FILE || { + echo "You must run this script in the top-level $PROJECT directory" + exit 1 +} + +if test -z "$AUTOGEN_SUBDIR_MODE"; then + if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." + fi +fi + +if test -z "$ACLOCAL_FLAGS"; then + + acdir=`$ACLOCAL --print-ac-dir` + m4list="glib-2.0.m4 glib-gettext.m4" + + for file in $m4list + do + if [ ! -f "$acdir/$file" ]; then + echo "WARNING: aclocal's directory is $acdir, but..." + echo " no file $acdir/$file" + echo " You may see fatal macro warnings below." + echo " If these files are installed in /some/dir, set the ACLOCAL_FLAGS " + echo " environment variable to \"-I /some/dir\", or install" + echo " $acdir/$file." + echo "" + fi + done +fi + +rm -rf autom4te.cache + +# README and INSTALL are required by automake, but may be deleted by clean +# up rules. to get automake to work, simply touch these here, they will be +# regenerated from their corresponding *.in files by ./configure anyway. +touch README INSTALL + +$ACLOCAL $ACLOCAL_FLAGS || exit $? + +autoheader || exit $? + +$AUTOMAKE --add-missing || exit $? +autoconf || exit $? +cd $ORIGDIR || exit $? + +if test -z "$AUTOGEN_SUBDIR_MODE"; then + $srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@" || exit $? + + echo + echo "Now type 'make' to compile $PROJECT." +fi diff --git a/cgg-dirgen b/cgg-dirgen deleted file mode 100755 index 44dd256..0000000 --- a/cgg-dirgen +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -## Cataract Gallery Generator - a simple static web photo gallery -## cgg-dirgen - Directory index.xml generator -## Copyright (C) 2008 Tomas Bzatek -## -## This program is free software; you can redistribute it and/or -## modify it under the terms of the GNU General Public License -## as published by the Free Software Foundation; either version 2 -## of the License, or any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -## - -## Optional arguments (must be in order, for now): -## -d Use preview pictures from the "preview" folder -## -o Do not include original image (removes link to original size) -## -t Generate thumbnails from the "thumbnails" folder - - -cat << XML_HEADER_STOP - - - - Album ID - Album Title - - ]]> - - - -XML_HEADER_STOP - -for i in `find -L . -maxdepth 1 -type f -iname '*.jpg' -or -iname '*.jpeg' -or -iname '*.gif' -or -iname '*.png' | sort`; do - INCL=""; - INCL2=""; - INCL3=""; - if [ "$1" = "-d" ]; then INCL=" preview=\"preview/`echo $i | cut -b 3-`\""; fi - if [ "$2" = "-o" ]; then INCL2=" \n"; fi - if [ "$3" = "-t" ]; then INCL3=" thumbnail=\"thumbnails/`echo $i | cut -b 3-`\""; fi - echo -e " \n${INCL2} \n \n \n"; -done - -cat << XML_FOOTER_STOP - - -XML_FOOTER_STOP - diff --git a/cgg.c b/cgg.c deleted file mode 100644 index a789c38..0000000 --- a/cgg.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include - -#include - -#include - -#include "config.h" -#include "setup.h" -#include "generators.h" - - - - - - -/* - * parse_cmd: parse commandline and fill global variable parameters - */ -gboolean -parse_cmd (int argc, char* argv[], char **source_dir, char **dst_dir, gboolean *verbose) -{ - static gboolean _verbose = FALSE; - static gchar *_source_dir = NULL; - static gchar *_dst_dir = NULL; - - static GOptionEntry entries[] = - { - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &_verbose, "Be verbose", NULL }, - { "source", 's', 0, G_OPTION_ARG_STRING, &_source_dir, "Specifies path to source structure", NULL }, - { "output", 'o', 0, G_OPTION_ARG_STRING, &_dst_dir, "Generate files to the specified directory instead of current", NULL }, - { NULL } - }; - - GError *error = NULL; - GOptionContext *context; - char *s1; - - g_set_prgname ("cgg"); - - context = g_option_context_new ("- web gallery generator"); - s1 = g_strdup_printf ("cgg v%s [%s] Copyright (c) 2008 Tomas Bzatek", APP_VERSION, APP_BUILD_DATE); - g_option_context_set_summary (context, s1); - g_free (s1); - g_option_context_add_main_entries (context, entries, NULL); - - if (argc == 1) { - s1 = g_option_context_get_help (context, TRUE, NULL); - g_print ("%s", s1); - g_free (s1); - g_option_context_free (context); - return FALSE; - } - - if (! g_option_context_parse (context, &argc, &argv, &error)) { - g_print ("option parsing failed: %s\n", error->message); - s1 = g_option_context_get_help (context, TRUE, NULL); - g_print ("%s", s1); - g_free (s1); - g_option_context_free (context); - return FALSE; - } - g_option_context_free (context); - - *source_dir = _source_dir; - *dst_dir = _dst_dir; - *verbose = _verbose; - - return TRUE; -} - - - -int -main(int argc, char* argv[]) -{ - char *source_dir; - char *dst_dir; - gboolean verbose; - TGallerySetup *setup; - - /* - * this initialize the library and check potential ABI mismatches - * between the version it was compiled for and the actual shared - * library used. - */ - LIBXML_TEST_VERSION; - - source_dir = NULL; - dst_dir = NULL; - setup = malloc(sizeof(TGallerySetup)); - - - /* Parse commandline */ - if (! parse_cmd (argc, argv, &source_dir, &dst_dir, &verbose)) - return -1; - - if ((! source_dir) || (access (source_dir, R_OK))) { - fprintf (stderr, "error: source directory must be specified and pointing to valid structure\n"); - return -4; - } - if (! dst_dir) { - fprintf (stderr, "error: target directory must be specified\n"); - return -5; - } - - /* Read gallery settings */ - if (! find_setup_xml (setup)) { - fprintf (stderr, "error: could not parse gallery settings file\n"); - return -2; - } - - setup->real_templates_dir = find_templates_directory (setup); - if (setup->real_templates_dir == NULL) { - fprintf (stderr, "error: could not determine templates directory\n"); - return -3; - } - - - /* Start building the gallery tree */ - setup->verbose = verbose; - build_tree (setup, source_dir, dst_dir, NULL); - - - /* Cleanup function for the XML library. */ - xmlCleanupParser(); - - free (source_dir); - free (dst_dir); - free_setup_data (setup); - - return (0); -} diff --git a/config.h b/config.h deleted file mode 100644 index bf9e613..0000000 --- a/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - - -/* Directory names of smaller images */ -#define THUMBNAIL_DIR "_thumb" -#define IMG_BIG_DIR "_big" -#define IMG_ORIG_DIR "_orig" - -#define SETUP_XML "setup.xml" - -#define APP_VERSION "0.99.0" -#define APP_BUILD_DATE "2008-07-27" - diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..931a27b --- /dev/null +++ b/configure.ac @@ -0,0 +1,103 @@ +AC_INIT + +PACKAGE=cataract +VERSION=0.99.2 +APP_BUILD_DATE=2009-02-26 +APP_COPYRIGHT_DATE=2008-2009 + +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) + +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AM_MAINTAINER_MODE +AM_CONFIG_HEADER(config.h) + +GLIB_REQUIRED=2.16.0 +EXIV2_REQUIRED=0.17 + +AC_C_CONST +AC_ISC_POSIX +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AM_PROG_CC_C_O + +dnl Check for pkgconfig first +AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no) +AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + +dnl Give error and exit if we don't have pkgconfig +if test "x$HAVE_PKGCONFIG" = "xno"; then + AC_MSG_ERROR(you need to have pkgconfig installed !) +fi + +PKG_CHECK_MODULES(LIBS, [ + glib-2.0 >= $GLIB_REQUIRED + libxml-2.0 + MagickWand + exiv2 >= $EXIV2_REQUIRED +]) +AC_SUBST(LIBS_CFLAGS) +AC_SUBST(LIBS_LIBS) + +AM_PATH_GLIB_2_0($GLIB_REQUIRED, :, + AC_MSG_ERROR([ +*** GLIB $GLIB_REQUIRED or better is required. The latest version of. +*** GLIB is always available from ftp://ftp.gtk.org/pub/gtk/.]), + gobject gmodule-no-export gthread) + + + +DISABLE_DEPRECATED_CFLAGS=" -DG_DISABLE_DEPRECATED" +AC_SUBST(DISABLE_DEPRECATED_CFLAGS) + +dnl WARN_CFLAGS="-Wall -Werror" +WARN_CFLAGS="-Wall" +AC_SUBST(WARN_CFLAGS) + + + +dnl ************************************************** +dnl *** Check for new exiv2 thumbnailing API *** +dnl ************************************************** + +AC_DEFUN([EXIV2_HAVE_NEW_THUMBNAILING_API], +[AC_CACHE_CHECK(for new Exiv2::ExifThumb API, +ac_cv_exiv2_have_new_exifthumb, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include +#include + +void test () { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(""); + Exiv2::ExifData &exifData = image->exifData(); + Exiv2::ExifThumb exifThumb(image->exifData()); + exifThumb.erase(); +} +],[return 0;], + ac_cv_exiv2_have_new_exifthumb=yes, ac_cv_exiv2_have_new_exifthumb=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_exiv2_have_new_exifthumb" = yes; then + AC_DEFINE(HAVE_EXIFTHUMB,,[new Exiv2::ExifThumb API]) +fi +]) + +EXIV2_HAVE_NEW_THUMBNAILING_API + +AC_DEFINE_UNQUOTED(APP_BUILD_DATE, ["$APP_BUILD_DATE"], [build date]) +AC_DEFINE_UNQUOTED(APP_COPYRIGHT_DATE, ["$APP_COPYRIGHT_DATE"], [copyright dates]) + + +AC_CONFIG_FILES([ + Makefile + src/Makefile +]) +AC_OUTPUT + + diff --git a/gallery-utils.c b/gallery-utils.c deleted file mode 100644 index 6378ae5..0000000 --- a/gallery-utils.c +++ /dev/null @@ -1,262 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gallery-utils.h" - - -/* - * str_replace: replace substring 'search' with a 'replace' string - * - multiple occurrences of the string are replaced - * - reallocates the original string - */ -void -str_replace (char **dst, const char *search, const char *replace) -{ - #define REPLACE_MAX_LENGTH 32768 - static char d[REPLACE_MAX_LENGTH]; - char *src; - char *found; - int i; - - /* TODO: add range checking */ - - if (strstr (*dst, search) == NULL || strlen (*dst) == 0 || strlen (search) == 0) - return; - - i = 0; - src = *dst; - while (strstr (src, search)) { - found = strstr (src, search); - - /* copy the data between search string */ - if (found > src) { - memcpy (&d[i], src, found - src); - i += found - src; - } - - /* copy replace string instead */ - if (strlen (replace) > 0) { - memcpy (&d[i], replace, strlen (replace)); - i += strlen (replace); - } - src = found + strlen (search); - } - - /* copy the rest */ - if (src) { - memcpy (&d[i], src, strlen (src)); - i += strlen (src); - } - d[i] = 0x0; - - -#ifdef __DEBUG_ALL__ - printf ("str_replace('%s', '%s') = '%s' --> '%s'\n", search, replace, *dst, &d[0]); -#endif - - /* return fixed string */ - free (*dst); - *dst = g_strdup (&d[0]); -} - - -/* - * copy_file: copy file from src to dst - */ -gboolean -copy_file (const char *src, const char *dst) -{ - #define BUFFER_SIZE 65536 - - FILE *fin; - FILE *fout; - void *buffer; - int size_r; - struct stat st; - struct utimbuf ut; - - fin = fopen (src, "r"); - if (fin == NULL) { - fprintf (stderr, "copy_file: error reading file \"%s\": %s\n", src, strerror (errno)); - return FALSE; - } - - fout = fopen (dst, "w"); - if (fout == NULL) { - fprintf (stderr, "copy_file: error writing to file \"%s\": %s\n", dst, strerror (errno)); - fclose (fin); - return FALSE; - } - - buffer = malloc (BUFFER_SIZE); - memset (buffer, 0, BUFFER_SIZE); - size_r = BUFFER_SIZE; - - while ((! feof (fin)) && (size_r == BUFFER_SIZE)) { - size_r = fread (buffer, 1, BUFFER_SIZE, fin); - fwrite (buffer, 1, size_r, fout); - } - - fclose (fout); - fclose (fin); - free (buffer); - - /* copy timestamps */ - memset (&st, 0, sizeof (st)); - if (stat (src, &st) == -1) { - fprintf (stderr, "copy_file: cannot stat source file \"%s\": %s\n", src, strerror (errno)); - return TRUE; - } - - memset (&ut, 0, sizeof (ut)); - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; - if (utime (dst, &ut) == -1) - fprintf (stderr, "copy_file: cannot set timestamps on target file \"%s\": %s\n", dst, strerror (errno)); - - return TRUE; -} - - -/* - * make_string: make string of 'substr' substrings - * - returns newly allocated string - */ -char * -make_string (const char* substr, const int count) -{ - int i; - char *s; - - s = malloc (strlen (substr) * count + 1); - for (i = 0; i < count; i++) - memcpy (s + (strlen (substr) * i), substr, strlen (substr)); - s[strlen (substr) * count] = 0; - return s; -} - - -/* - * fix_entities: replace all invalid & entities with & - * - returns newly allocated string - */ -void -fix_entities (char **str) -{ - static char d[REPLACE_MAX_LENGTH]; - char *src; - char *found; - char *scan; - int i; - - /* TODO: add range checking */ - - if (! *str || strstr (*str, "&") == NULL) - return; - - i = 0; - src = *str; - while (strstr (src, "&")) { - found = strstr (src, "&"); - - /* copy the data between search string */ - memcpy (&d[i], src, found - src + 1); - i += found - src + 1; - - /* scroll to next whitespace */ - scan = found + 1; - while (scan && ( - (*scan >= 0x41 && *scan <= 0x5a) || (*scan >= 0x61 && *scan <= 0x7a) || /* A-Z, a-z */ - (*scan >= 0x30 && *scan <= 0x39) || (*scan == 0x23) /* 0-9, # */ - )) - scan++; - - if (scan && (*scan == 0x3b)) { - /* this is semicolon, correctly closed entity */ - /* -- ignore */ - } - else { - /* replace with & */ - memcpy (&d[i], "amp;", 4); - i += 4; - } - src = found + 1; - } - - /* copy the rest */ - if (src) { - memcpy (&d[i], src, strlen (src)); - i += strlen (src); - } - d[i] = 0x0; - - -#ifdef __DEBUG_ALL__ - printf ("fix_entities: '%s' --> '%s'\n", *str, &d[0]); -#endif - - /* return fixed string */ - free (*str); - *str = g_strdup (&d[0]); -} - - -/* - * remove_tags: remove all occurences of tags beginning with tag_begin and ending with tag_end - * - e.g. remove_tags (&x, "") will remove all comments - * - returns newly allocated string - */ -void -remove_tags (char **str, const char *tag_begin, const char *tag_end) -{ - char *src; - char *found; - char *found2; - char *dest; - - if (! *str || ! tag_begin || ! tag_end || strlen (*str) == 0 || strlen (tag_begin) == 0 || strlen (tag_end) == 0) - return; - - src = *str; - - while ((found = strstr (src, tag_begin)) != NULL) { - found2 = strstr (found, tag_end); - if (found2) { - found2 += strlen (tag_end); - dest = malloc (strlen (src) - (found2 - found) + 1); - memcpy (dest, src, found - src); - memcpy (dest + (found - src), found2, strlen (found2) + 1); -#ifdef __DEBUG_ALL__ - printf ("found = %ld, found2 = %ld, strlen = %d, res = %d\n", (long int)found, (long int)found2, strlen (src), strlen (src) - (found2 - found) + 1); - printf ("orig = %s, new = %s, strlen = %d\n", src, dest, strlen (dest)); -#endif - g_free (src); - src = g_strdup (dest); - free (dest); - } - } - *str = src; -} diff --git a/gallery-utils.h b/gallery-utils.h deleted file mode 100644 index 53c82c0..0000000 --- a/gallery-utils.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include - -#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '~') -#define IS_EQUAL_SIGN(ch) ((ch) == '=') - - -/* - * str_replace: replace substring 'search' with a 'replace' string - * - multiple occurences of the string are replaced - * - reallocates the original string - */ -void str_replace (char **dst, const char *search, const char *replace); - -/* - * copy_file: copy file from src to dst - */ -gboolean copy_file (const char *src, const char *dst); - -/* - * make_string: make string of 'substr' substrings - * - returns newly allocated string - */ -char *make_string (const char* substr, const int count); - -/* - * fix_entities: replace all invalid & entities with & - * - returns newly allocated string - */ -void fix_entities (char **str); - -/* - * remove_tags: remove all occurences of tags beginning with tag_begin and ending with tag_end - * - e.g. remove_tags (&x, "") will remove all comments - * - returns newly allocated string - */ -void remove_tags (char **str, const char *tag_begin, const char *tag_end); diff --git a/generators-replace-table.c b/generators-replace-table.c deleted file mode 100644 index 23771fc..0000000 --- a/generators-replace-table.c +++ /dev/null @@ -1,174 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2009 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "generators-replace-table.h" -#include "gallery-utils.h" - - - - -#if 0 -static void -replace_table_destroy_notify (gpointer data) -{ - g_print ("replace_table_destroy_notify: %s\n", (gchar *) data); - - if ((gchar *) data) - g_free ((gchar *) data); -} -#endif - -ReplaceTable * -replace_table_new () -{ - return (ReplaceTable *) g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -} - -void -replace_table_free (ReplaceTable *table) -{ - g_return_if_fail (table != NULL); - - g_hash_table_destroy (table); -} - - -/* - * replace_table_add_key: add tag/value pair to replace - * - * tag, value will be referenced inside - * - */ -void -replace_table_add_key (ReplaceTable *table, const gchar *tag, const gchar *value) -{ - g_return_if_fail (table != NULL); - - if (tag != NULL && value != NULL) - g_hash_table_replace (table, g_strdup (tag), g_strdup (value)); -} - -void -replace_table_add_key_int (ReplaceTable *table, const gchar *tag, gint value) -{ - g_return_if_fail (table != NULL); - - if (tag != NULL) - g_hash_table_replace (table, g_strdup (tag), g_strdup_printf ("%d", value)); -} - -void -replace_table_add_key_printf (ReplaceTable *table, const gchar *tag, const gchar *format, ...) -{ - va_list args; - gchar *s = NULL; - - g_return_if_fail (table != NULL); - - if (tag != NULL && format != NULL) { - va_start (args, format); - g_vasprintf (&s, format, args); - g_hash_table_replace (table, g_strdup (tag), s); - va_end (args); - } -} - - - -static void -replace_table_process_value (gpointer key, gpointer value, gpointer user_data) -{ - gchar **buffer = user_data; - gchar *tag; - gchar *tag_value; - - g_return_if_fail (key != NULL); - g_return_if_fail (value != NULL); - g_return_if_fail (user_data != NULL); - - /* replace tags */ - tag = g_strdup_printf ("", (gchar *) key); - tag_value = g_strdup ((gchar *) value); - adjust_tags_normal (&tag_value); - while (strstr (*buffer, tag)) { - str_replace (buffer, tag, tag_value); - } - g_free (tag_value); - g_free (tag); - - /* replace $(xxx) tags */ - tag = g_strdup_printf ("$(%s)", (gchar *) key); - tag_value = g_strdup ((gchar *) value); - adjust_tags_parameter (&tag_value); - while (strstr (*buffer, tag)) { - str_replace (buffer, tag, tag_value); - } - g_free (tag_value); - g_free (tag); -} - -/* - * replace_table_process: process buffer and replace all tags filled in the replace table - * - * - reallocates source buffer - * - */ -void -replace_table_process (gchar **buffer, ReplaceTable *table) -{ - g_return_if_fail (table != NULL); - - g_hash_table_foreach (table, replace_table_process_value, buffer); - -/* - gchar *val = g_hash_table_lookup (table, "TAG"); - g_print ("replace_table_process: val = '%s'\n", val); -*/ -} - - -/* - * adjust_tags_normal: adjust string for normal HTML use - * adjust_tags_parameter: adjust string for use as tag parameter value - * - both funtions return newly allocated string - */ -void -adjust_tags_normal (char **str) -{ - fix_entities (str); -} - -void -adjust_tags_parameter (char **str) -{ - /* TODO: replace line endings with single space? */ - remove_tags (str, ""); /* comments */ - remove_tags (str, "<", ">"); /* tags */ - fix_entities (str); /* entities */ - str_replace (str, "\"", """); /* " */ - str_replace (str, "'", "'"); /* ' */ -} diff --git a/generators-replace-table.h b/generators-replace-table.h deleted file mode 100644 index d72d150..0000000 --- a/generators-replace-table.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2009 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - - -typedef GHashTable ReplaceTable; - -/* - * write_html_album: process album and index template files - * - * template_src = template file of the album/index - * dst = save generated file as - * items = array of items in the album/index - * - */ -ReplaceTable *replace_table_new (); - -void replace_table_free (ReplaceTable *table); - - -/* - * replace_table_add_key: add tag/value pair to replace - * - * tag, value will be referenced inside - * - */ -void replace_table_add_key (ReplaceTable *table, const gchar *tag, const gchar *value); -void replace_table_add_key_int (ReplaceTable *table, const gchar *tag, gint value); -void replace_table_add_key_printf (ReplaceTable *table, const gchar *tag, const gchar *format, ...) G_GNUC_PRINTF (3, 4); - -/* - * replace_table_process: process buffer and replace all tags filled in the replace table - * - * - reallocates source buffer - * - */ -void replace_table_process (gchar **buffer, ReplaceTable *table); - - -/* - * adjust_tags_normal: adjust string for normal HTML use - * adjust_tags_parameter: adjust string for use as tag parameter value - * - both funtions return newly allocated string - */ -void adjust_tags_normal (char **str); -void adjust_tags_parameter (char **str); - diff --git a/generators.c b/generators.c deleted file mode 100644 index 907412a..0000000 --- a/generators.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include - -#include - -#include "config.h" -#include "setup.h" -#include "items.h" -#include "jpeg-utils.h" -#include "gallery-utils.h" -#include "generators-replace-table.h" - - -/* - * generate_image: auxiliary function for write_html_album - * - img_src and thumb should be freed afterwards - */ -void -generate_image (TGallerySetup *setup, - TAlbum *items, - TIndexItem *item, - unsigned int item_index, - const char *dst, - unsigned long *img_w, unsigned long *img_h, - char **img_src, char **thumb) -{ - unsigned long new_w, new_h; - unsigned long thumb_w, thumb_h; - char *thumb_dst; - char *big_dst; - char *big_src; - char *orig_dst; - char *img_src_full; - char *thumb_src_full; - char *s1; - int bigq; - - - *img_src = NULL; - *thumb = NULL; - *img_w = 0; - *img_h = 0; - - if (items->type == GALLERY_TYPE_INDEX) { - if (item->thumbnail == NULL || strlen (item->thumbnail) == 0) - return; - img_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); - thumb_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); - *img_src = g_path_get_basename (item->thumbnail); - s1 = g_path_get_basename (item->thumbnail); - *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); - g_free (s1); - } - else - if (items->type == GALLERY_TYPE_ALBUM) { - *img_src = (item->path == NULL && item->preview) ? item->preview : item->path; - *thumb = (item->thumbnail) ? item->thumbnail : *img_src; - img_src_full = g_strconcat (items->base_dir, "/", *img_src, NULL); - thumb_src_full = g_strconcat (items->base_dir, "/", *thumb, NULL); - *img_src = g_path_get_basename (*img_src); - s1 = g_path_get_basename (*thumb); - *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); - g_free (s1); - } - - get_image_sizes (img_src_full, img_w, img_h); - - if ((img_w > 0) && (img_h > 0)) { - new_w = *img_w; - new_h = *img_h; - - /* Generate thumbnail */ - get_image_sizes (thumb_src_full, &thumb_w, &thumb_h); - s1 = g_path_get_dirname (dst); - thumb_dst = g_strconcat (s1, "/", THUMBNAIL_DIR, "/", *thumb, NULL); - g_free (s1); - if (setup->verbose) printf (" Generating thumbnail of '%s' ...", *thumb); - - if ((thumb_w > 0) && (thumb_h > 0)) { - if ((thumb_w / thumb_h) >= 1) - calculate_sizes (setup->thumbnail_landscape_width, setup->thumbnail_landscape_height, &thumb_w, &thumb_h); - else - calculate_sizes (setup->thumbnail_portrait_width, setup->thumbnail_portrait_height, &thumb_w, &thumb_h); - if (! resize_image (thumb_src_full, thumb_dst, thumb_w, thumb_h, setup->thumbnail_quality, TRUE)) - fprintf (stderr, "write_html_index: error resizing thumbnail %s\n", thumb_src_full); - else - if (setup->verbose) printf (" done.\n"); - g_free (thumb_dst); - } else - printf (" failed!\n"); - - - /* Generate/copy preview and original image */ - if (items->type == GALLERY_TYPE_ALBUM) - { - s1 = g_path_get_dirname (dst); - big_dst = g_strconcat (s1, "/", IMG_BIG_DIR, "/", *img_src, NULL); - g_free (s1); - - if (item->preview == NULL) { - /* No preview image supplied, generate it from original */ - bigq = setup->preview_quality; - if ((items->quality > 0) && (items->quality <= 100)) - bigq = items->quality; - if ((item->quality > 0) && (item->quality <= 100)) - bigq = item->quality; - new_w = *img_w; - new_h = *img_h; - - if (setup->verbose) printf (" Generating preview of '%s' ...", *img_src); - if ((item->width > 0) && (item->height > 0)) { - calculate_sizes (item->width, item->height, &new_w, &new_h); - } else { - if ((*img_w / *img_h) >= 1) - { - if ((items->landscape_width > 0) && (items->landscape_height > 0)) - calculate_sizes (items->landscape_width, items->landscape_height, &new_w, &new_h); - else - calculate_sizes (setup->preview_landscape_width, setup->preview_landscape_height, &new_w, &new_h); - } - else - { - if ((items->portrait_width > 0) && (items->portrait_height > 0)) - calculate_sizes (items->portrait_width, items->portrait_height, &new_w, &new_h); - else - calculate_sizes (setup->preview_portrait_width, setup->preview_portrait_height, &new_w, &new_h); - } - } - - if (! resize_image (img_src_full, big_dst, new_w, new_h, bigq, FALSE)) - fprintf (stderr, "write_html_index: error resizing big image %s\n", img_src_full); - else - if (setup->verbose) printf (" done.\n"); - } - else - { - /* Copy the preview (big) image provided */ - big_src = g_strconcat (items->base_dir, "/", item->preview, NULL); - if (setup->verbose) printf (" Copying preview image '%s' ...", *img_src); - if (! copy_file (big_src, big_dst)) - fprintf (stderr, "write_html_index: error copying preview image %s\n", big_src); - else - if (setup->verbose) printf (" done.\n"); - g_free (big_src); - } - modify_exif (big_dst, setup->erase_exif_thumbnail, setup->add_copyright); - g_free (big_dst); - - if (item->force_fullsize || (items->fullsize && ! item->force_nofullsize) || - (! item->force_nofullsize && ! items->nofullsize && ! setup->nofullsize)) - { - s1 = g_path_get_dirname(dst); - orig_dst = g_strconcat (s1, "/", IMG_ORIG_DIR, "/", *img_src, NULL); - g_free (s1); - if (setup->verbose) printf (" Copying original image '%s' ...", *img_src); - if (! copy_file(img_src_full, orig_dst)) - fprintf (stderr, "write_html_index: error copying original image %s\n", img_src_full); - else - if (setup->verbose) printf(" done.\n"); - modify_exif (orig_dst, setup->erase_exif_thumbnail, setup->add_copyright); - g_free (orig_dst); - } - } - } - g_free (img_src_full); - g_free (thumb_src_full); -} - - - -/* - * write_html_album: process album and index template files - * - * template_src = template file of the album/index - * dst = save generated file as - * items = array of items in the album/index - * - */ -gboolean -write_html_album (TGallerySetup *setup, - const char *template_src, - const char *dst, - TAlbum *items) -{ - #define BUFFER_SIZE 65536 - FILE *fin; - FILE *fout; - char *buffer; - char *buf_img_list_landscape; - char *buf_img_list_portrait; - char *buf_img_separator; - char *buf_go_up_string; - gboolean in_img_list; - gboolean in_img_list_landscape; - gboolean in_img_list_portrait; - gboolean in_img_separator; - gboolean in_go_up_string; - char *b; - char *s1, *s2, *s3, *s4, *s5; - TAlbum *parent; - TIndexItem *item; - TIndexItem *tmp_item; - int level, old_parent_item_index; - gboolean res, bb; - int i; - unsigned long img_w, img_h; - char *img_src; - char *thumb; - unsigned int real_total_items; - ReplaceTable *global_replace_table; - ReplaceTable *local_replace_table; - - - fin = fopen (template_src, "r"); - if (fin == NULL) { - fprintf (stderr, "write_html_index: error reading file \"%s\": %s\n", template_src, strerror (errno)); - return FALSE; - } - fout = fopen (dst, "w"); - if (fout == NULL) { - fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); - fclose (fin); - return FALSE; - } - - buffer = malloc (BUFFER_SIZE); - buf_img_list_landscape = malloc (BUFFER_SIZE); - buf_img_list_portrait = malloc (BUFFER_SIZE); - buf_img_separator = malloc (BUFFER_SIZE); - buf_go_up_string = malloc (BUFFER_SIZE); - in_img_list = FALSE; - in_img_list_landscape = FALSE; - in_img_list_portrait = FALSE; - in_img_separator = FALSE; - in_go_up_string = FALSE; - res = TRUE; - - global_replace_table = replace_table_new (); - - /* Get number of real pictures in the list */ - real_total_items = 0; - for (i = 0; i < items->items->len; i++) { - tmp_item = g_ptr_array_index (items->items, i); - if (tmp_item->type == INDEX_ITEM_TYPE_PICTURE) - real_total_items++; - } - replace_table_add_key_int (global_replace_table, "TOTAL_ITEMS", real_total_items); - - /* Page title */ - if (items->parent_index == NULL || setup->site_title == NULL) - s1 = g_strdup (setup->site_title ? setup->site_title : items->ID); - else - s1 = g_strdup_printf ("%s | %s", items->title, setup->site_title); - replace_table_add_key (global_replace_table, "PAGE_TITLE", s1); - g_free (s1); - - /* Simple placeholders */ - replace_table_add_key (global_replace_table, "ID", items->ID); - replace_table_add_key (global_replace_table, "TITLE", items->title); - replace_table_add_key (global_replace_table, "DESCRIPTION", items->desc); - replace_table_add_key (global_replace_table, "FOOTNOTE", items->footnote); - replace_table_add_key (global_replace_table, "FOOTER", setup->footer); - s1 = setup->use_inpage_links ? g_strdup_printf ("../index.html#i%d", items->parent_item_index + 1) : g_strdup ("../index.html"); - replace_table_add_key (global_replace_table, "GO_UP_LINK", s1); - g_free (s1); - - /* Navigation bar */ - s1 = g_strdup (items->ID); - old_parent_item_index = items->parent_item_index + 1; - parent = items->parent_index; - level = 1; - while (parent) { - s3 = make_string ("../", level); - s4 = g_strdup (parent->ID); - s5 = setup->use_inpage_links ? g_strdup_printf ("#i%d", old_parent_item_index) : g_strdup (""); - s2 = g_strdup_printf ("%s > %s", s3, s5, s4, s1); - free (s3); - g_free (s1); - g_free (s4); - g_free (s5); - s1 = s2; - old_parent_item_index = parent->parent_item_index + 1; - parent = parent->parent_index; - level++; - } - replace_table_add_key (global_replace_table, "NAV_BAR", s1); - g_free (s1); - - /* META tags */ - s1 = g_strdup_printf ("\t\n", APP_VERSION); - if (setup->meta_author || items->meta_author) { - s3 = g_strdup (items->meta_author ? items->meta_author : setup->meta_author); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - if (setup->meta_description || items->meta_description) { - s3 = g_strdup (items->meta_description ? items->meta_description : setup->meta_description); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - if (setup->meta_keywords || items->meta_keywords) { - s3 = g_strdup (items->meta_keywords ? items->meta_keywords : setup->meta_keywords); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - replace_table_add_key (global_replace_table, "CGG_META_TAGS", s1); - g_free (s1); - - - /* Read through the template and replace placeholders with real data */ - while (! feof (fin)) - { - memset (buffer, 0, BUFFER_SIZE); - if (! fgets (buffer, BUFFER_SIZE, fin)) - break; - - /* Block placeholders */ - if (in_img_list && (strstr (buffer, ""))) { - in_img_list_landscape = TRUE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_list_landscape = FALSE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_list_portrait = TRUE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_list_portrait = FALSE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_separator = TRUE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_separator = FALSE; - continue; - } - if (in_img_list && in_img_list_landscape) { - buf_img_list_landscape = strncat (buf_img_list_landscape, buffer, BUFFER_SIZE - strlen (buf_img_list_landscape) - 2); - continue; - } - if (in_img_list && in_img_list_portrait) { - buf_img_list_portrait = strncat (buf_img_list_portrait, buffer, BUFFER_SIZE - strlen (buf_img_list_portrait) - 2); - continue; - } - if (in_img_list && in_img_separator) { - buf_img_separator = strncat (buf_img_separator, buffer, BUFFER_SIZE - strlen (buf_img_separator) - 2); - continue; - } - - if (strstr (buffer, "")) { - memset (buf_go_up_string, 0, BUFFER_SIZE); - in_go_up_string = TRUE; - continue; - } - if (in_go_up_string && strstr (buffer, "")) { - in_go_up_string = FALSE; - if (! items->parent_index) - continue; - } - if (in_go_up_string) { - buf_go_up_string = strncat (buf_go_up_string, buffer, BUFFER_SIZE - strlen (buf_go_up_string) - 2); - continue; - } - - /* Image list, nested placeholders */ - if (strstr (buffer, "")) { - memset (buf_img_list_landscape, 0, BUFFER_SIZE); - memset (buf_img_list_portrait, 0, BUFFER_SIZE); - memset (buf_img_separator, 0, BUFFER_SIZE); - in_img_list = TRUE; - in_img_list_landscape = FALSE; - in_img_list_portrait = FALSE; - in_img_separator = FALSE; - continue; - } - if (in_img_list && (strstr (buffer, ""))) { - in_img_list = FALSE; - in_img_list_landscape = FALSE; - in_img_list_portrait = FALSE; - - /* Now we have all block placeholders read, generate the items: */ - for (i = 0; i < items->items->len; i++) - { - item = g_ptr_array_index (items->items, i); - if (item == NULL) { - fprintf (stderr, "write_html_index: error getting item %d\n", i); - continue; - } - - /* Generate the images (preview, original, thumbnail) */ - local_replace_table = replace_table_new (); - img_w = 0; - img_h = 0; - s1 = NULL; - - switch (item->type) { - case INDEX_ITEM_TYPE_PICTURE: - img_src = NULL; - thumb = NULL; - generate_image (setup, items, item, i, dst, &img_w, &img_h, &img_src, &thumb); - /* Skip HTML code generation if it's a hidden item */ - if (! item->hidden) { - if (img_w == 0 || img_h == 0 || (img_w / img_h) >= 1) - s1 = strdup (buf_img_list_landscape); - else - s1 = strdup (buf_img_list_portrait); - - replace_table_add_key_printf (local_replace_table, "ALBUM_SUBPATH", "%s/index.html", item->path); - replace_table_add_key_printf (local_replace_table, "IMG_SUBPAGE", "%s.html", img_src); - replace_table_add_key (local_replace_table, "IMG_TITLE", item->title); - replace_table_add_key (local_replace_table, "IMG_DESCRIPTION", item->title_description); - replace_table_add_key_printf (local_replace_table, "IMG_LIST_ID", "i%d", i + 1); - replace_table_add_key_printf (local_replace_table, "IMG_THUMBNAIL", "%s/%s", THUMBNAIL_DIR, thumb); - replace_table_add_key (local_replace_table, "IMG_FILENAME", img_src); - if (items->type == GALLERY_TYPE_INDEX) { - s3 = g_strconcat (items->base_dir, "/", item->path, "/index.xml", NULL); - replace_table_add_key_int (local_replace_table, "ALBUM_NUM_ITEMS", get_album_objects_count (s3)); - g_free (s3); - } - } - if (img_src) - g_free (img_src); - if (thumb) - g_free (thumb); - break; - - case INDEX_ITEM_TYPE_SEPARATOR: - s1 = strdup (buf_img_separator); - replace_table_add_key (local_replace_table, "LIST_SEPARATOR_TITLE", item->title); - break; - } - - bb = TRUE; - if (s1) { - replace_table_process (&s1, local_replace_table); - bb = fputs (s1, fout); - free (s1); - } - replace_table_free (local_replace_table); - if (! bb) { - fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); - res = FALSE; - break; - } - } - continue; /* no need to write anything */ - } - - /* Select apropriate line buffer */ - if (strstr (buffer, "") && items->parent_index) { - b = strdup (buf_go_up_string); - } else - b = strdup (buffer); - - /* Replace all known tags */ - replace_table_process (&b, global_replace_table); - - /* Write to file */ - bb = fputs (b, fout); - free (b); - if (! bb) { - fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); - res = FALSE; - break; - } - } - - fclose (fout); - fclose (fin); - replace_table_free (global_replace_table); - free (buffer); - free (buf_img_list_landscape); - free (buf_img_list_portrait); - free (buf_img_separator); - free (buf_go_up_string); - return res; -} - - -/* - * write_html_image: process single image template file - * - * template_src = template file of the album/index - * original_img = source image file (original full-size) to get EXIF data from - * dst = save generated file as - * item = data for the current item - * parent_items = array of items in the album, to determine our position and make links to previous/next image - * - */ -gboolean -write_html_image (TGallerySetup *setup, - const char *template_src, - const char *original_img, - const char *dst, - TIndexItem *item, - TAlbum *parent_items) -{ - #define BUFFER_SIZE 65536 - FILE *fin; - FILE *fout; - char *buffer; - char *big_dst; - char *orig_dst; - char *buf_img_fullsize_link; - gboolean in_img_fullsize_link; - TExifData *exif; - unsigned long img_big_w, img_big_h, img_orig_w, img_orig_h; - unsigned int item_index, real_item_index, real_total_items; - TIndexItem *previous_item; - TIndexItem *next_item; - TIndexItem *tmp_item; - TAlbum *parent; - int i; - char *s1, *s2, *s3, *s4, *s5; - char *imgname, *preload_imgname; - char *title, *title_desc; - char *b; - gboolean res, bb; - int level, old_parent_item_index; - gboolean override_title_meta; - gboolean image_fullsize; - ReplaceTable *replace_table; - - - fin = fopen (template_src, "r"); - if (fin == NULL) { - fprintf (stderr, "write_html_image: error reading file \"%s\": %s\n", template_src, strerror (errno)); - return FALSE; - } - fout = fopen (dst, "w"); - if (fout == NULL) { - fprintf (stderr, "write_html_image: error writing to file \"%s\": %s\n", dst, strerror (errno)); - fclose (fin); - return FALSE; - } - - buffer = malloc (BUFFER_SIZE); - preload_imgname = NULL; - - replace_table = replace_table_new (); - - /* Get our index in the album */ - item_index = 0; - real_item_index = 0; - real_total_items = 0; - for (i = 0; i < parent_items->items->len; i++) { - tmp_item = g_ptr_array_index (parent_items->items, i); - if (tmp_item->type == INDEX_ITEM_TYPE_PICTURE) { - if (! item_index) real_item_index++; - real_total_items++; - } - if (tmp_item == item) - item_index = i + 1; - } - - /* Get previous and next items */ - previous_item = NULL; - next_item = NULL; - for (i = item_index - 2; i >= 0 && (previous_item == NULL || previous_item->type != INDEX_ITEM_TYPE_PICTURE); i--) - previous_item = g_ptr_array_index (parent_items->items, i); - if (previous_item && previous_item->type != INDEX_ITEM_TYPE_PICTURE) - previous_item = NULL; - for (i = item_index; item_index < parent_items->items->len && (next_item == NULL || next_item->type != INDEX_ITEM_TYPE_PICTURE); i++) - next_item = g_ptr_array_index (parent_items->items, i); - if (next_item && next_item->type != INDEX_ITEM_TYPE_PICTURE) - next_item = NULL; - - /* Paths setup */ - imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); - if (next_item && setup->preload) { - s1 = g_path_get_basename ((next_item->path == NULL && next_item->preview) ? next_item->preview : next_item->path); - preload_imgname = g_strconcat (IMG_BIG_DIR, "/", s1, NULL); - g_free (s1); - } - s1 = g_path_get_dirname (dst); - big_dst = g_strconcat (s1, "/", IMG_BIG_DIR, "/", imgname, NULL); - orig_dst = g_strconcat (s1, "/", IMG_ORIG_DIR, "/", imgname, NULL); - g_free (s1); - buf_img_fullsize_link = malloc (BUFFER_SIZE); - memset (buf_img_fullsize_link, 0, BUFFER_SIZE); - in_img_fullsize_link = FALSE; - res = TRUE; - - /* Get EXIF data from the original image */ - if (get_exif (original_img, &exif)) - fprintf (stderr, "write_html_image: error getting exif data from file \"%s\"\n", orig_dst); - - /* Retrieve image sizes of preview and original image */ - get_image_sizes (big_dst, &img_big_w, &img_big_h); - image_fullsize = item->force_fullsize || (parent_items->fullsize && ! item->force_nofullsize) || - (! item->force_nofullsize && ! parent_items->nofullsize && ! setup->nofullsize); - if (image_fullsize) - get_image_sizes (orig_dst, &img_orig_w, &img_orig_h); - - /* Get title and description from IPTC/EXIF/JPEG if not defined */ - title = g_strdup (item->title); - title_desc = g_strdup (item->title_description); - if (setup->use_iptc_exif && title == NULL && title_desc == NULL) { - if (exif->iptc_caption) - title = g_strdup (exif->iptc_caption); - if (exif->jpeg_comment) { - if (! title) - title = g_strdup (exif->jpeg_comment); - else - title_desc = g_strdup (exif->jpeg_comment); - } - if (exif->exif_imgdesc) { - if (! title) - title = g_strdup (exif->exif_imgdesc); -/* if (! title_desc) -- disabled - title_desc = g_strdup (exif->exif_imgdesc); */ - } - if (exif->exif_usercomment) { - if (! title) - title = g_strdup (exif->exif_usercomment); - if (! title_desc) - title_desc = g_strdup (exif->exif_usercomment); - } - /* Convert line breaks to be visible in the HTML code */ - if (title) { - str_replace (&title, "\r\n", "
"); - str_replace (&title, "\n", "
"); - } - if (title_desc) { - str_replace (&title_desc, "\r\n", "
"); - str_replace (&title_desc, "\n", "
"); - } - } - if (title) title = g_strstrip (title); - if (title_desc) title_desc = g_strstrip (title_desc); - - /* Page title */ - s1 = (title && strlen (title) > 0) ? g_strdup_printf("%s | ", title) : NULL; - s2 = g_strdup_printf ("%s [%d/%d]", parent_items->title ? parent_items->title : parent_items->ID, real_item_index, real_total_items); - s3 = setup->site_title ? g_strdup_printf(" | %s", setup->site_title) : NULL; - s4 = g_strconcat (s1 ? s1 : "", s2, s3 ? s3 : "", NULL); - replace_table_add_key (replace_table, "PAGE_TITLE", s4); - if (s1) g_free (s1); - if (s2) g_free (s2); - if (s3) g_free (s3); - g_free (s4); - - /* Simple placeholders */ - replace_table_add_key (replace_table, "FILE_NAME", imgname); - replace_table_add_key (replace_table, "TITLE", title); - replace_table_add_key (replace_table, "DESCRIPTION", title_desc); - replace_table_add_key (replace_table, "FOOTER", setup->footer); - replace_table_add_key_int (replace_table, "TOTAL_ITEMS", real_total_items); - replace_table_add_key_int (replace_table, "FILE_NO", real_item_index); - replace_table_add_key_int (replace_table, "IMG_SIZE_BIG_W", img_big_w); - replace_table_add_key_int (replace_table, "IMG_SIZE_BIG_H", img_big_h); - replace_table_add_key_int (replace_table, "IMG_SIZE_ORIG_W", img_orig_w); - replace_table_add_key_int (replace_table, "IMG_SIZE_ORIG_H", img_orig_h); - replace_table_add_key_printf (replace_table, "IMG_SRC_BIG", "%s/%s", IMG_BIG_DIR, imgname); - replace_table_add_key_printf (replace_table, "IMG_SRC_FULL", "%s/%s", IMG_ORIG_DIR, imgname); - replace_table_add_key (replace_table, "IMG_SRC_PRELOAD", preload_imgname ? preload_imgname : ""); - - /* Navigation bar */ - s1 = g_strdup (imgname); - parent = parent_items; - level = 0; - while (parent) { - s3 = make_string ("../", level); - s4 = g_strdup (parent->ID); - s5 = setup->use_inpage_links ? g_strdup_printf ("#i%d", parent == parent_items ? item_index : old_parent_item_index) : g_strdup (""); - s2 = g_strdup_printf ("%s > %s", s3, s5, s4, s1); - free (s3); - g_free (s1); - g_free (s4); - g_free (s5); - s1 = s2; - old_parent_item_index = parent->parent_item_index + 1; - parent = parent->parent_index; - level++; - } - replace_table_add_key (replace_table, "NAV_BAR", s1); - g_free (s1); - - /* EXIF values */ - replace_table_add_key (replace_table, "EXIF_ISO", exif->iso ? exif->iso : "??"); - replace_table_add_key (replace_table, "EXIF_TIME", exif->exposure ? exif->exposure : "??"); - replace_table_add_key (replace_table, "EXIF_APERTURE", exif->aperture ? exif->aperture : "??"); - replace_table_add_key (replace_table, "EXIF_FOCAL_LENGTH", exif->focal_length ? exif->focal_length : "??"); - replace_table_add_key (replace_table, "EXIF_FLASH", exif->flash ? exif->flash : "??"); - replace_table_add_key (replace_table, "EXIF_DATE", exif->datetime ? exif->datetime : "??"); - replace_table_add_key (replace_table, "EXIF_CAMERA_MODEL", exif->camera_model ? exif->camera_model : "??"); - s1 = g_strdup_printf ("(%s)", exif->focal_length_35mm); - replace_table_add_key (replace_table, "EXIF_FOCAL_35", exif->focal_length_35mm ? s1 : ""); - g_free (s1); - - /* Border style */ - s1 = item->border_style; - if (s1 == NULL) - s1 = parent_items->border_style; - if (s1 == NULL) - s1 = setup->border_style; - if (s1 == NULL) - s1 = "border_single"; - replace_table_add_key (replace_table, "IMG_BORDER_STYLE", s1); - - /* Next/Previous links */ - if (next_item) { - s2 = g_path_get_basename ((next_item->path == NULL && next_item->preview) ? next_item->preview : next_item->path); - replace_table_add_key_printf (replace_table, "LINK_NEXT", "%s.html", s2); - g_free (s2); - } - else - replace_table_add_key (replace_table, "LINK_NEXT", "index.html"); - if (previous_item) { - s2 = g_path_get_basename ((previous_item->path == NULL && previous_item->preview) ? previous_item->preview : previous_item->path); - replace_table_add_key_printf (replace_table, "LINK_PREV", "%s.html", s2); - g_free (s2); - } - else - replace_table_add_key (replace_table, "LINK_PREV", "index.html"); - - /* META tags */ - override_title_meta = setup->use_title_as_meta && title && (strlen (title) > 0); - s1 = g_strdup_printf ("\t\n", APP_VERSION); - if (setup->meta_author || parent_items->meta_author) { - s3 = g_strdup (parent_items->meta_author ? parent_items->meta_author : setup->meta_author); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - if (setup->meta_description || parent_items->meta_description || override_title_meta) { - s3 = g_strdup (override_title_meta ? title : (parent_items->meta_description ? parent_items->meta_description : setup->meta_description)); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - if ((setup->meta_keywords || parent_items->meta_keywords) && (! override_title_meta)) { - s3 = g_strdup (parent_items->meta_keywords ? parent_items->meta_keywords : setup->meta_keywords); - adjust_tags_parameter (&s3); - s2 = g_strdup_printf ("%s\t\n", s1, s3); - g_free (s3); - g_free (s1); - s1 = s2; - } - replace_table_add_key (replace_table, "CGG_META_TAGS", s1); - g_free (s1); - - - /* Read through the template and replace placeholders with real data */ - while (! feof (fin)) { - memset (buffer, 0, BUFFER_SIZE); - if (! fgets (buffer, BUFFER_SIZE, fin)) - break; - - /* Block placeholders */ - if (strstr (buffer, "")) { - in_img_fullsize_link = TRUE; - continue; - } - if (strstr (buffer, "")) { - in_img_fullsize_link = FALSE; - if (! image_fullsize) /* write down the block later in this cycle */ - continue; - } - if (in_img_fullsize_link) { - buf_img_fullsize_link = strncat (buf_img_fullsize_link, buffer, BUFFER_SIZE - strlen (buf_img_fullsize_link) - 2); - continue; - } - - /* Select apropriate line buffer */ - if (strstr (buffer, "") && image_fullsize) { - b = strdup (buf_img_fullsize_link); - } else - b = strdup (buffer); - - /* Replace all known tags */ - replace_table_process (&b, replace_table); - - /* Write to file */ - bb = fputs (b, fout); - free (b); - if (! bb) { - fprintf (stderr, "write_html_image: error writing to file \"%s\": %s\n", dst, strerror (errno)); - res = FALSE; - break; - } - } - - fclose (fout); - fclose (fin); - if (title) g_free (title); - if (title_desc) g_free (title_desc); - free (buffer); - free (big_dst); - free (orig_dst); - free (buf_img_fullsize_link); - g_free (imgname); - if (preload_imgname) - g_free (preload_imgname); - free_exif_data (exif); - replace_table_free (replace_table); - return res; -} - - -/* - * build_tree: generate complete gallery tree based on source xml files - * - * src_tree = source directory of the items - * dst_dir = destination of the generated items - * parent_index = parent album to determine our descent in the tree - * - */ -gboolean -build_tree (TGallerySetup *setup, - const char *src_tree, - const char *dst_dir, - TAlbum *parent_index, - int parent_item_index) -{ - char *idx_file; - TAlbum *items; - TIndexItem *item; - char *s1, *s2, *s3; - char *thumb_dir; - char *img_big_dir; - char *img_orig_dir; - char *template; - char *imgname; - gboolean res; - int i; - - printf ("*** Entering directory '%s'\n", src_tree); - #ifdef __DEBUG_ALL__ - printf ("setup->real_templates_dir = %s\n", setup->real_templates_dir); - #endif - - /* Check access permissions */ - if (access (src_tree, R_OK)) { - fprintf (stderr, "error accessing source directory: %s\n", strerror (errno)); - return FALSE; - } - if (access (dst_dir, R_OK | W_OK | X_OK)) { - if (mkdir (dst_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { - fprintf (stderr, "error creating destination directory: %s\n", strerror (errno)); - return FALSE; - } - } - - /* Check the index file */ - idx_file = g_strconcat (src_tree, "/index.xml", NULL); - if (access (idx_file, R_OK)) { - fprintf (stderr, "error accessing index file '%s': %s\n", idx_file, strerror (errno)); - g_free (idx_file); - return FALSE; - } - - /* Read the index file and fill items array */ - items = malloc (sizeof (TAlbum)); - memset (items, 0, sizeof (TAlbum)); - if (! parse_album_xml (idx_file, items)) { - fprintf (stderr, "error reading index file '%s'\n", idx_file); - g_free (idx_file); - free_album_data (items); - return FALSE; - } - g_free (idx_file); - items->parent_index = parent_index; - items->parent_item_index = parent_item_index; - - - /* Copy support files */ - if (setup->verbose) printf ("Writing '%s' ...", setup->styles); - s1 = g_strconcat (setup->real_templates_dir, "/", setup->styles, NULL); - s2 = g_strconcat (dst_dir, "/", setup->styles, NULL); - copy_file (s1, s2); - g_free (s1); - g_free (s2); - if (setup->verbose) printf (" done.\n"); - - if (setup->verbose) printf ("Writing '%s' ...", setup->scripts); - s1 = g_strconcat (setup->real_templates_dir, "/", setup->scripts, NULL); - s2 = g_strconcat (dst_dir, "/", setup->scripts, NULL); - copy_file (s1, s2); - g_free (s1); - g_free (s2); - if (setup->verbose) printf (" done.\n"); - - - /* Prepare target thumbnail directory */ - thumb_dir = g_strconcat (dst_dir, "/", THUMBNAIL_DIR, NULL); - if (access (thumb_dir, R_OK | W_OK | X_OK)) - if (mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { - fprintf (stderr, "error making target thumbnail directory: %s\n", strerror (errno)); - g_free (thumb_dir); - free_album_data (items); - return FALSE; - } - g_free (thumb_dir); - - /* Prepare target preview and orig directories */ - if (items->type == GALLERY_TYPE_ALBUM) - { - res = TRUE; - img_big_dir = g_strconcat (dst_dir, "/", IMG_BIG_DIR, NULL); - img_orig_dir = g_strconcat (dst_dir, "/", IMG_ORIG_DIR, NULL); - if (access (img_big_dir, R_OK | W_OK | X_OK)) - if (mkdir (img_big_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { - fprintf (stderr, "error making target preview directory: %s\n", strerror (errno)); - res = FALSE; - } - if (access (img_orig_dir, R_OK | W_OK | X_OK)) - if (mkdir (img_orig_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { - fprintf (stderr, "error making target full size directory: %s\n", strerror (errno)); - res = FALSE; - } - g_free (img_big_dir); - g_free (img_orig_dir); - if (! res) { - free_album_data (items); - return FALSE; - } - } - - - /* Start generating items */ - if (items->type == GALLERY_TYPE_INDEX) - template = g_strconcat ("/", setup->template_index, NULL); - else - if (items->type == GALLERY_TYPE_ALBUM) - template = g_strconcat ("/", setup->template_album, NULL); - - if (setup->verbose) printf ("Writing 'index.html' ...\n"); - s1 = g_strconcat (setup->real_templates_dir, template, NULL); - s2 = g_strconcat (dst_dir, "/index.html", NULL); - res = write_html_album (setup, s1, s2, items); - g_free (s1); - g_free (s2); - g_free (template); - if (! res) { - fprintf (stderr, "error generating target index file\n"); - free_album_data (items); - return FALSE; - } - if (setup->verbose) printf (" done.\n"); - - - /* Recurse to sub-albums (in case of album index) */ - if (items->type == GALLERY_TYPE_INDEX) - { - if (items->items->len > 0) { - for (i = 0; i < items->items->len; i++) { - item = g_ptr_array_index (items->items, i); - if (item == NULL) { - fprintf (stderr, "build_tree: error getting item %d\n", i); - continue; - } - if (item->type == INDEX_ITEM_TYPE_PICTURE) { - s1 = g_strconcat (src_tree, "/", item->path, "/", NULL); - s2 = g_strconcat (dst_dir, "/", item->path, "/", NULL); - build_tree (setup, s1, s2, items, i); - g_free (s1); - g_free (s2); - } - } - } - } - - /* Generate separate image pages (in case of album) */ - if (items->type == GALLERY_TYPE_ALBUM) - { - if (items->items->len > 0) { - for (i = 0; i < items->items->len; i++) { - item = g_ptr_array_index (items->items, i); - if (item == NULL) { - fprintf (stderr, "build_tree: error getting item %d\n", i); - continue; - } - if (item->type == INDEX_ITEM_TYPE_PICTURE) { - imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); - if (setup->verbose) printf ("Writing '%s.html' ...", imgname); - s1 = g_strconcat (setup->real_templates_dir, "/", setup->template_photo, NULL); - s2 = g_strconcat (items->base_dir, "/", (item->path == NULL && item->preview) ? item->preview : item->path, NULL); - s3 = g_strconcat (dst_dir, "/", imgname, ".html", NULL); - res = write_html_image (setup, s1, s2, s3, item, items); - g_free (s1); - g_free (s2); - g_free (s3); - g_free (imgname); - if (! res ) continue; - if (setup->verbose) printf (" done.\n"); - } - } - } - } - - printf ("*** Leaving directory '%s'\n", src_tree); - free_album_data (items); - - return TRUE; -} diff --git a/generators.h b/generators.h deleted file mode 100644 index c87e8a3..0000000 --- a/generators.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include "setup.h" -#include "items.h" - - -/* - * write_html_album: process album and index template files - * - * template_src = template file of the album/index - * dst = save generated file as - * items = array of items in the album/index - * - */ -gboolean write_html_album (TGallerySetup *setup, - const char *template_src, - const char *dst, - TAlbum *items); - -/* - * write_html_image: process single image template file - * - * template_src = template file of the album/index - * original_img = source image file (original full-size) to get EXIF data from - * dst = save generated file as - * item = data for the current item - * parent_items = array of items in the album, to determine our position and make links to previous/next image - * - */ -gboolean write_html_image (TGallerySetup *setup, - const char *template_src, - const char *original_img, - const char *dst, - TIndexItem *item, - TAlbum *parent_items); - -/* - * build_tree: generate complete gallery tree based on source xml files - * - * src_tree = source directory of the items - * dst_dir = destination of the generated items - * parent_index = parent album to determine our descent in the tree - * - */ -gboolean build_tree (TGallerySetup *setup, - const char *src_tree, - const char *dst_dir, - TAlbum *parent_index); - diff --git a/items.c b/items.c deleted file mode 100644 index 986fd6c..0000000 --- a/items.c +++ /dev/null @@ -1,320 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include - -#include -#include -#include -#include - -#include "items.h" -#include "xml-parser.h" - - - -/* - * parse_album_xml: XML parser for gallery index.xml files - */ -gboolean -parse_album_xml (const char *filename, TAlbum *index) -{ - TXMLFile *xml; - char *gallery_type; - int count; - int i; - char *s, *s2; - char *node_name; - TIndexItem *item; - - xml = xml_parser_load (filename); - if (xml == NULL) - return FALSE; - - /* Initialize data struct */ - if (index == NULL) - index = malloc (sizeof (TAlbum)); - memset (index, 0, sizeof (TAlbum)); - - index->base_dir = g_path_get_dirname (filename); - - /* Retrieve gallery type */ - gallery_type = xml_file_get_node_attribute (xml, "/gallery", "type"); - #ifdef __DEBUG_ALL__ - printf("gallery_type = %s\n", gallery_type); - #endif - if (strcmp (gallery_type, "index") == 0) - index->type = GALLERY_TYPE_INDEX; - else - if (strcmp (gallery_type, "album") == 0) - index->type = GALLERY_TYPE_ALBUM; - else { - printf ("Invalid gallery type (%s)\n", gallery_type); - free (index); - return FALSE; - } - - /* Section General */ - index->ID = xml_file_get_node_value (xml, "/gallery/general/ID/text()"); - index->title = xml_file_get_node_value (xml, "/gallery/general/title/text()"); - index->desc = xml_file_get_node_value (xml, "/gallery/general/description/text()"); - index->footnote = xml_file_get_node_value (xml, "/gallery/general/footnote/text()"); - - index->quality = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "quality", -1); - index->landscape_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_w", 0); - index->landscape_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_h", 0); - index->portrait_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_w", 0); - index->portrait_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_h", 0); - - index->border_style = xml_file_get_node_attribute (xml, "/gallery/general/border", "style"); - index->meta_author = xml_file_get_node_value (xml, "/gallery/general/meta/author/text()"); - index->meta_description = xml_file_get_node_value (xml, "/gallery/general/meta/description/text()"); - index->meta_keywords = xml_file_get_node_value (xml, "/gallery/general/meta/keywords/text()"); - - index->nofullsize = xml_file_get_node_present (xml, "/gallery/general/nofullsize"); - index->fullsize = xml_file_get_node_present (xml, "/gallery/general/fullsize"); - - /* Section Items */ - count = xml_file_node_get_children_count (xml, "/gallery/items/*"); - #ifdef __DEBUG_ALL__ - printf("parse_album_xml: items count = %d\n", count); - #endif - index->items = g_ptr_array_new(); - - for (i = 0; i < count; i++) - { - item = malloc (sizeof (TIndexItem)); - memset (item, 0, sizeof (TIndexItem)); - - s = g_strdup_printf ("/gallery/items/*[%d]", i + 1); - node_name = xml_file_get_node_name (xml, s); - if (! node_name) continue; - #ifdef __DEBUG_ALL__ - printf("parse_album_xml: item[%d] = '%s'\n", i + 1, node_name); - #endif - - if (strcmp (node_name, "item") == 0) { - item->type = INDEX_ITEM_TYPE_PICTURE; - if (index->type == GALLERY_TYPE_INDEX) - item->path = xml_file_get_node_attribute (xml, s, "path"); - else - item->path = xml_file_get_node_attribute (xml, s, "src"); - item->preview = xml_file_get_node_attribute (xml, s, "preview"); - item->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1); - item->width = xml_file_get_node_attribute_long (xml, s, "width", 0); - item->height = xml_file_get_node_attribute_long (xml, s, "height", 0); - item->border_style = xml_file_get_node_attribute (xml, s, "border"); - if (index->type == GALLERY_TYPE_ALBUM) - item->thumbnail = xml_file_get_node_attribute (xml, s, "thumbnail"); - g_free (s); - - s = g_strdup_printf ("/gallery/items/*[%d]/title/text()", i + 1); - item->title = xml_file_get_node_value (xml, s); - g_free (s); - - s = g_strdup_printf ("/gallery/items/*[%d]/title_description/text()", i + 1); - item->title_description = xml_file_get_node_value (xml, s); - g_free (s); - - if (index->type == GALLERY_TYPE_INDEX) { - s = g_strdup_printf ("/gallery/items/*[%d]/thumbnail", i + 1); - item->thumbnail = xml_file_get_node_attribute (xml, s, "src"); - g_free (s); - } - - s = g_strdup_printf ("/gallery/items/*[%d]/nofullsize", i + 1); - item->force_nofullsize = (xml_file_get_node_present (xml, s) || item->path == NULL); - g_free (s); - - s = g_strdup_printf ("/gallery/items/*[%d]/fullsize", i + 1); - item->force_fullsize = xml_file_get_node_present (xml, s); - g_free (s); - - s = g_strdup_printf ("/gallery/items/*[%d]/hidden", i + 1); - item->hidden = (xml_file_get_node_present (xml, s)); - g_free (s); - - /* Retrieve title and description from linked album if not defined here */ - if (index->type == GALLERY_TYPE_INDEX && - item->title == NULL && item->title_description == NULL) { - s = g_strconcat (index->base_dir, "/", item->path, "/index.xml", NULL); - get_album_titles (s, &item->title, &item->title_description, NULL); - g_free (s); - } - - /* Retrieve thumbnail from linked album if not defined here */ - if (index->type == GALLERY_TYPE_INDEX && item->thumbnail == NULL) { - s = g_strconcat (index->base_dir, "/", item->path, "/index.xml", NULL); - s2 = NULL; - get_album_titles (s, NULL, NULL, &s2); - if (s2) { - item->thumbnail = g_strconcat (item->path, "/", s2, NULL); - g_free (s2); - } - g_free (s); - } - - if (item->path || item->preview) - { - g_ptr_array_add (index->items, item); - } - else - { - fprintf (stderr, "%s: No image src specified, skipping!\n", filename); - free (item); - } - } - else - if (strcmp (node_name, "separator") == 0) { - item->type = INDEX_ITEM_TYPE_SEPARATOR; - - s = g_strdup_printf ("/gallery/items/*[%d]/text()", i + 1); - item->title = xml_file_get_node_value (xml, s); - g_free (s); - - g_ptr_array_add (index->items, item); - } - else { - /* Free the item if nobody cares */ - free (item); - } - free (node_name); - } - - xml_parser_close (xml); - - /* Print the items */ - #ifdef __DEBUG_ALL__ - printf ("ID = '%s'\ntitle = '%s'\ndescription = '%s'\n", index->ID, index->title, index->desc); - for (i = 0; i < index->items->len; i++) { - TIndexItem *item = g_ptr_array_index (index->items, i); - printf ("item %d: path = '%s', title = '%s', title_description = '%s', thumbnail = '%s'\n", - i, item->path, item->title, item->title_description, item->thumbnail); - } - #endif - return TRUE; -} - - -/* - * free_album_data: free allocated album data - */ -void -free_album_data (TAlbum *album) -{ - if (album) { - if (album->ID) - free (album->ID); - if (album->title) - free (album->title); - if (album->desc) - free (album->desc); - if (album->footnote) - free (album->footnote); - if (album->base_dir) - free (album->base_dir); - if (album->border_style) - free (album->border_style); - if (album->meta_author) - free (album->meta_author); - if (album->meta_description) - free (album->meta_description); - if (album->meta_keywords) - free (album->meta_keywords); - - if (album->items) { - if (album->items->len > 0) { - TIndexItem *item; - int i; - - for (i = 0; i < album->items->len; i++) { - item = g_ptr_array_index (album->items, i); - if (item != NULL) { - if (item->path) - free (item->path); - if (item->title) - free (item->title); - if (item->title_description) - free (item->title_description); - if (item->thumbnail) - free (item->thumbnail); - if (item->preview) - free (item->preview); - if (item->border_style) - free (item->border_style); - free (item); - } - } - } - g_ptr_array_free (album->items, TRUE); - } - free (album); - album = NULL; - } -} - - -/* - * get_gallery_objects_count: retrieve number of items in specified album - */ -int -get_album_objects_count (const char *filename) -{ - TXMLFile *xml; - int count; - - xml = xml_parser_load (filename); - if (xml == NULL) - return 0; - - count = xml_file_node_get_children_count (xml, "/gallery/items/item"); - xml_parser_close (xml); - - #ifdef __DEBUG_ALL__ - printf ("get_objects_count(%s) = %d\n", filename, count); - #endif - return count; -} - -/* - * get_album_titles: retrieve title, description and first thumbnail from specified album - */ -void -get_album_titles (const char *filename, char **title, char **description, char **thumbnail) -{ - TXMLFile *xml; - - xml = xml_parser_load (filename); - if (xml == NULL) - return; - - if (title) - *title = xml_file_get_node_value (xml, "/gallery/general/title/text()"); - if (description) - *description = xml_file_get_node_value (xml, "/gallery/general/description/text()"); - if (thumbnail) { - *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]/thumbnail", "src"); - if (! *thumbnail) - *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "src"); - if (! *thumbnail) - *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "preview"); - } - - xml_parser_close (xml); -} diff --git a/items.h b/items.h deleted file mode 100644 index 9fd6822..0000000 --- a/items.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef __ITEMS_H__ -#define __ITEMS_H__ - - -#include - - -typedef enum { - GALLERY_TYPE_INDEX = 1 << 0, - GALLERY_TYPE_ALBUM = 1 << 1 -} TGalleryType; - -typedef enum { - INDEX_ITEM_TYPE_PICTURE = 1 << 0, - INDEX_ITEM_TYPE_SEPARATOR = 1 << 1 -} TIndexItemType; - -typedef struct { - TGalleryType type; - char *ID; - char *title; - char *desc; - char *footnote; - GPtrArray *items; - char *base_dir; - void *parent_index; /* pointer to the parent TAlbum structure */ - int parent_item_index; /* item index in the parent album */ - int quality; - unsigned long landscape_width; - unsigned long landscape_height; - unsigned long portrait_width; - unsigned long portrait_height; - char *border_style; - char *meta_author; - char *meta_description; - char *meta_keywords; - gboolean nofullsize; - gboolean fullsize; -} TAlbum; - -typedef struct { - char *path; - char *title; - char *title_description; - char *thumbnail; - char *preview; - int quality; - unsigned long width; - unsigned long height; - gboolean force_nofullsize; - gboolean force_fullsize; - char *border_style; - TIndexItemType type; - gboolean hidden; -} TIndexItem; - - - -/* - * parse_album_xml: XML parser for gallery index.xml files - */ -gboolean parse_album_xml (const char *filename, TAlbum *index); - -/* - * free_album_data: free allocated album data - */ -void free_album_data (TAlbum *index); - -/* - * get_album_objects_count: retrieve number of items in specified album - */ -int get_album_objects_count (const char *filename); - -/* - * get_album_titles: retrieve title, description and first thumbnail from specified album - */ -void get_album_titles (const char *filename, char **title, char **description, char **thumbnail); - -#endif /* __ITEMS_H__ */ diff --git a/jpeg-utils.cpp b/jpeg-utils.cpp deleted file mode 100644 index 6ccf491..0000000 --- a/jpeg-utils.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include - -#include -#include - -#include - -#include "jpeg-utils.h" - - - -/* - * get_exif: retrieve EXIF informations from a JPEG image - */ -int -get_exif (const char *filename, TExifData **exif_data) -{ - TExifData *data; - - data = (TExifData*) malloc (sizeof (TExifData)); - memset (data, 0, sizeof (TExifData)); - *exif_data = data; - - try - { - Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename); - g_assert (image.get() != 0); - image->readMetadata(); - - Exiv2::ExifData &exifData = image->exifData(); - if (! exifData.empty()) { - /* EXIF::Aperture */ - try { - float val = exifData["Exif.Photo.FNumber"].toFloat(); - if (val >= 0) - data->aperture = g_strdup_printf ("f/%.1f", val); - } catch (...) { } - - /* EXIF::Camera model */ - try { - const char *val = exifData["Exif.Image.Model"].toString().c_str(); - if (val && strlen(val) > 0) - data->camera_model = strdup (val); - } catch (...) { } - - /* EXIF::DateTime */ - try { - const char *val = NULL; - try { - val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str(); - } catch (...) { } - if ((! val) || (strlen(val) == 0)) - try { - val = exifData["Exif.Image.DateTime"].toString().c_str(); - } catch (...) { } - - if (val && strlen(val) > 0) { - static struct tm tt; - static char conv[1024]; - - if (sscanf (val, "%d:%d:%d %d:%d:%d", &tt.tm_year, &tt.tm_mon, &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec) == 6) - { - tt.tm_year -= 1900; - tt.tm_mon--; - if (strftime (&conv[0], sizeof(conv), "%c", &tt)) - data->datetime = strdup (&conv[0]); - } - } - } catch (...) { } - - /* EXIF::Shutter speed */ - try { - float val = exifData["Exif.Photo.ExposureTime"].toFloat(); - if (val > 0) { - if (val < 0.5) - data->exposure = g_strdup_printf ("1/%.0f s", 1/val); - else - data->exposure = g_strdup_printf ("%.1f s", val); - } - } catch (...) { } - - /* EXIF::Flash */ - try { - long int val = exifData["Exif.Photo.Flash"].toLong(); - if ((val > 0) && ((val & 1) == 1)) - data->flash = strdup ((char *) "Flash fired"); - else - data->flash = strdup ((char *) "--"); - } catch (...) { } - - /* EXIF::Focal length */ - try { - float val = exifData["Exif.Photo.FocalLength"].toFloat(); - if (val >= 0) - data->focal_length = g_strdup_printf ("%.0f mm", val); - } catch (...) { } - - /* EXIF::ISO */ - try { - long int val = exifData["Exif.Photo.ISOSpeedRatings"].toLong(); - if (val > 0) - data->iso = g_strdup_printf ("%ld", val); - } catch (...) { } - - /* EXIF::Software */ - try { - data->exif_software = strdup (exifData["Exif.Image.Software"].toString().c_str()); - } catch (...) { } - - /* EXIF::Image description */ - try { - data->exif_imgdesc = strdup (exifData["Exif.Image.ImageDescription"].toString().c_str()); - } catch (...) { } - - /* EXIF::Artist */ - try { - data->exif_artist = strdup (exifData["Exif.Image.Artist"].toString().c_str()); - } catch (...) { } - - /* EXIF::Copyright */ - try { - data->exif_copyright = strdup (exifData["Exif.Image.Copyright"].toString().c_str()); - } catch (...) { } - - /* EXIF::User comment */ - try { - data->exif_usercomment = strdup (exifData["Exif.Photo.UserComment"].toString().c_str()); - } catch (...) { } - } - - Exiv2::IptcData &iptcData = image->iptcData(); - if (! iptcData.empty()) { - /* IPTC::Object name */ - try { - data->iptc_objectname = strdup (iptcData["Iptc.Application2.ObjectName"].toString().c_str()); - } catch (...) { } - - /* IPTC::Copyright */ - try { - data->iptc_copyright = strdup (iptcData["Iptc.Application2.Copyright"].toString().c_str()); - } catch (...) { } - - /* IPTC::Credit */ - try { - data->iptc_credit = strdup (iptcData["Iptc.Application2.Credit"].toString().c_str()); - } catch (...) { } - - /* IPTC::Caption */ - try { - data->iptc_caption = strdup (iptcData["Iptc.Application2.Caption"].toString().c_str()); - } catch (...) { } - - /* IPTC::Author */ - try { - data->iptc_author = strdup (iptcData["Iptc.Application2.Byline"].toString().c_str()); - } catch (...) { } - } - - /* JPEG::Comment */ - try { - data->jpeg_comment = strdup (image->comment().c_str()); - } catch (...) { } - } - catch (Exiv2::AnyError& e) - { - fprintf (stderr, "get_exif: Caught Exiv2 exception: '%s'\n", e.what()); - return -1; - } - -#ifdef __DEBUG_ALL__ - printf("EXIF_TAG_DATE_TIME = '%s'\n", data->datetime); - printf("EXIF_TAG_MODEL = '%s'\n", data->camera_model); - printf("EXIF_TAG_ISO_SPEED_RATINGS = '%s'\n", data->iso); - printf("EXIF_TAG_FOCAL_LENGTH = '%s'\n", data->focal_length); - printf("EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = '%s'\n", data->focal_length_35mm); - printf("EXIF_TAG_FNUMBER = '%s'\n", data->aperture); - printf("EXIF_TAG_EXPOSURE_TIME = '%s'\n", data->exposure); - printf("EXIF_TAG_FLASH = '%s'\n", data->flash); - printf("Exif.Image.Software = '%s'\n", data->exif_software); - printf("Exif.Image.ImageDescription = '%s'\n", data->exif_imgdesc); - printf("Exif.Image.Artist = '%s'\n", data->exif_artist); - printf("Exif.Image.Copyright = '%s'\n", data->exif_copyright); - printf("Exif.Photo.UserComment = '%s'\n", data->exif_usercomment); - printf("Iptc.Application2.ObjectName = '%s'\n", data->iptc_objectname); - printf("Iptc.Application2.Copyright = '%s'\n", data->iptc_copyright); - printf("Iptc.Application2.Credit = '%s'\n", data->iptc_credit); - printf("Iptc.Application2.Caption = '%s'\n", data->iptc_caption); - printf("Iptc.Application2.Byline = '%s'\n", data->iptc_author); - printf("JPEG comment = '%s'\n", data->jpeg_comment); -#endif - - return 0; -} - -/* - * free_exif_struct: free allocated structure - */ -void -free_exif_data (TExifData *data) -{ - if (data) { - if (data->aperture) - free (data->aperture); - if (data->camera_model) - free (data->camera_model); - if (data->datetime) - free (data->datetime); - if (data->exposure) - free (data->exposure); - if (data->flash) - free (data->flash); - if (data->focal_length) - free (data->focal_length); - if (data->focal_length_35mm) - free (data->focal_length_35mm); - if (data->iso) - free (data->iso); - - if (data->exif_software) - free (data->exif_software); - if (data->exif_imgdesc) - free (data->exif_imgdesc); - if (data->exif_artist) - free (data->exif_artist); - if (data->exif_copyright) - free (data->exif_copyright); - if (data->exif_usercomment) - free (data->exif_usercomment); - - if (data->iptc_objectname) - free (data->iptc_objectname); - if (data->iptc_copyright) - free (data->iptc_copyright); - if (data->iptc_credit) - free (data->iptc_credit); - if (data->iptc_caption) - free (data->iptc_caption); - if (data->iptc_author) - free (data->iptc_author); - - if (data->jpeg_comment) - free (data->jpeg_comment); - - free (data); - data = NULL; - } -} - - -/* - * resize_image: resize image pointed by src and save result to dst - */ -gboolean -resize_image (const char *src, const char *dst, - int size_x, int size_y, - int quality, - gboolean thumbnail) -{ - #define ThrowWandException(wand) \ - { \ - char *description; \ - ExceptionType severity; \ - \ - description = MagickGetException (wand, &severity); \ - (void) fprintf (stderr, "Error converting image: %s %s %ld %s\n", GetMagickModule(), description); \ - description = (char*) MagickRelinquishMemory (description); \ - return FALSE; \ - } - - MagickBooleanType status; - MagickWand *magick_wand; - - /* Read an image. */ - MagickWandGenesis(); - magick_wand = NewMagickWand(); - status = MagickReadImage (magick_wand, src); - if (status == MagickFalse) - ThrowWandException (magick_wand); - if (thumbnail) - MagickThumbnailImage (magick_wand, size_x, size_y); - else - MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0); - MagickSetImageCompressionQuality (magick_wand, quality); - - /* Write the image and destroy it. */ - status = MagickWriteImage (magick_wand, dst); - if (status == MagickFalse) - ThrowWandException (magick_wand); - magick_wand = DestroyMagickWand (magick_wand); - MagickWandTerminus(); - - return TRUE; -} - - -/* - * get_image_sizes: retrieve image dimensions - */ -void -get_image_sizes (const char *img, - unsigned long *width, unsigned long *height) -{ - #define xThrowWandException(wand) \ - { \ - char *description; \ - ExceptionType severity; \ - \ - description = MagickGetException (wand, &severity); \ - (void) fprintf (stderr, "Error reading image info: %s %s %ld %s\n", GetMagickModule(), description); \ - description = (char*) MagickRelinquishMemory(description); \ - return; \ - } - - MagickBooleanType status; - MagickWand *magick_wand; - - *width = -1; - *height = -1; - - /* Read an image. */ - MagickWandGenesis(); - magick_wand = NewMagickWand(); - status = MagickPingImage (magick_wand, img); - if (status == MagickFalse) - xThrowWandException (magick_wand); - *width = MagickGetImageWidth (magick_wand); - *height = MagickGetImageHeight (magick_wand); - - magick_wand = DestroyMagickWand (magick_wand); - MagickWandTerminus(); -} - - -/* - * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio - */ -void -calculate_sizes (const unsigned long max_width, const unsigned long max_height, - unsigned long *width, unsigned long *height) -{ - if ((max_width > *width) && (max_height > *height)) - return; - - double max_ratio = (double) max_width / (double) max_height; - double real_ratio = (double) *width / (double) *height; - - if ((*width > *height) && (max_ratio <= real_ratio)) - { - *height = (unsigned long) (max_width / real_ratio); - *width = max_width; - } - else - { - *width = (unsigned long) (max_height * real_ratio); - *height = max_height; - } -} - - -/* - * modify_exif: - strip thumbnail stored in EXIF table - * - add copyright to Exif::Image::Copyright and Iptc::Application2::Copyright - */ -void -modify_exif (const char *filename, gboolean strip_thumbnail, const char *add_copyright) -{ - bool was_modified = false; - - if ((! strip_thumbnail) && (add_copyright == NULL)) - return; - - try - { - Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename); - g_assert (image.get() != 0); - - image->readMetadata(); - Exiv2::ExifData &exifData = image->exifData(); - if (add_copyright) { - exifData["Exif.Image.Copyright"] = add_copyright; - image->iptcData()["Iptc.Application2.Copyright"] = add_copyright; - was_modified = true; - } - - if (strip_thumbnail && (! exifData.empty())) { -#ifdef _EXIV2_NEW_API - Exiv2::ExifThumb exifThumb(image->exifData()); - std::string thumbExt = exifThumb.extension(); -#else - std::string thumbExt = exifData.thumbnailExtension(); -#endif - - if (! thumbExt.empty()) { -#ifdef _EXIV2_NEW_API - exifThumb.erase(); -#else - exifData.eraseThumbnail(); -#endif - was_modified = true; - } - } - - if (was_modified) - image->writeMetadata(); - } - catch (Exiv2::AnyError& e) - { - fprintf (stderr, "modify_exif: Caught Exiv2 exception: '%s'\n", e.what()); - } -} diff --git a/jpeg-utils.h b/jpeg-utils.h deleted file mode 100644 index 9b8919f..0000000 --- a/jpeg-utils.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef __cplusplus - extern "C" { -#endif - -#include - - -/* TODO: we want to have numerical values here at some point in the future */ -typedef struct { - char *datetime; - char *camera_model; - char *iso; - char *focal_length; - char *focal_length_35mm; - char *aperture; - char *exposure; - char *flash; - - char *exif_software; - char *exif_imgdesc; - char *exif_artist; - char *exif_copyright; - char *exif_usercomment; - - char *iptc_objectname; - char *iptc_copyright; - char *iptc_credit; - char *iptc_caption; - char *iptc_author; - - char *jpeg_comment; -} TExifData; - - -/* - * get_exif: retrieve EXIF info from a JPEG image - */ -int get_exif (const char *filename, TExifData **exif_data); - -/* - * free_exif_struct: free allocated structure - */ -void free_exif_data (TExifData *data); - - -/* - * resize_image: resize image pointed by src and save result to dst - * - setting thumbnail flag will remove all profiles and optimize for size - */ -gboolean resize_image (const char *src, const char *dst, - int size_x, int size_y, - int quality, - gboolean thumbnail); - -/* - * get_image_sizes: retrieve image dimensions - */ -void get_image_sizes (const char *img, - unsigned long *width, unsigned long *height); - -/* - * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio - */ -void calculate_sizes (const unsigned long max_width, const unsigned long max_height, - unsigned long *width, unsigned long *height); - -/* - * modify_exif: - strip thumbnail stored in EXIF table - * - add copyright to Exif::Image::Copyright and Iptc::Application2::Copyright - */ -void modify_exif (const char *filename, gboolean strip_thumbnail, const char *add_copyright); - - -#ifdef __cplusplus - } -#endif diff --git a/setup.c b/setup.c deleted file mode 100644 index d9b9464..0000000 --- a/setup.c +++ /dev/null @@ -1,266 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "config.h" -#include "gallery-utils.h" -#include "setup.h" -#include "xml-parser.h" - - - -/* - * find_setup_xml: try to find setup.xml in standard paths - */ -gboolean -find_setup_xml (TGallerySetup *setup) -{ - #define BUFFER_SIZE 65536 - - char *pth; - char *cwd; - gboolean b; - - cwd = malloc (BUFFER_SIZE); - cwd = getcwd (cwd, BUFFER_SIZE); - pth = g_strconcat (cwd, "/", SETUP_XML, NULL); - free (cwd); - - b = parse_setup_xml (pth, setup); - g_free (pth); - if (b) return TRUE; - - pth = g_strconcat (getenv ("HOME"), "/.cgg/", SETUP_XML, NULL); - b = parse_setup_xml (pth, setup); - g_free (pth); - if (b) return TRUE; - - pth = g_strconcat("/usr/share/cgg/", SETUP_XML, NULL); - b = parse_setup_xml (pth, setup); - g_free (pth); - if (b) return TRUE; - - pth = g_strconcat("/usr/local/share/cgg/", SETUP_XML, NULL); - b = parse_setup_xml (pth, setup); - g_free (pth); - return b; -} - - -/* - * parse_setup_xml: XML parser for setup.xml file - */ -gboolean -parse_setup_xml (const char *filename, TGallerySetup *setup) -{ - TXMLFile *xml; - char *s; - - xml = xml_parser_load (filename); - if (xml == NULL) - return FALSE; - - /* initialize data struct */ - if (setup == NULL) - return FALSE; - memset (setup, 0, sizeof (TGallerySetup)); - setup->setup_xml_path = strdup (filename); - - setup->templates_path = xml_file_get_node_value (xml, "/gallery_setup/templates/path/text()"); - setup->template_index = xml_file_get_node_value (xml, "/gallery_setup/templates/index/text()"); - setup->template_album = xml_file_get_node_value (xml, "/gallery_setup/templates/album/text()"); - setup->template_photo = xml_file_get_node_value (xml, "/gallery_setup/templates/photo/text()"); - setup->styles = xml_file_get_node_value (xml, "/gallery_setup/templates/styles/text()"); - setup->scripts = xml_file_get_node_value (xml, "/gallery_setup/templates/scripts/text()"); - setup->thumbnail_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_w", 0); - setup->thumbnail_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_h", 0); - setup->thumbnail_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_w", 0); - setup->thumbnail_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_h", 0); - setup->thumbnail_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "quality", -1); - setup->preview_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_w", 0); - setup->preview_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_h", 0); - setup->preview_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_w", 0); - setup->preview_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_h", 0); - setup->preview_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "quality", -1); - setup->footer = xml_file_get_node_value (xml, "/gallery_setup/footer/text()"); - setup->border_style = xml_file_get_node_attribute (xml, "/gallery_setup/images/border", "style"); - setup->meta_author = xml_file_get_node_value (xml, "/gallery_setup/meta/author/text()"); - setup->meta_description = xml_file_get_node_value (xml, "/gallery_setup/meta/description/text()"); - setup->meta_keywords = xml_file_get_node_value (xml, "/gallery_setup/meta/keywords/text()"); - - s = xml_file_get_node_attribute (xml, "/gallery_setup/images/preload", "value"); - setup->preload = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ - if (s) g_free (s); - s = xml_file_get_node_attribute (xml, "/gallery_setup/images/use_iptc_exif", "value"); - setup->use_iptc_exif = s ? strcasecmp (s, "yes") == 0 : FALSE; /* default to FALSE */ - if (s) g_free (s); - s = xml_file_get_node_attribute (xml, "/gallery_setup/images/erase_embed_thumbnail", "value"); - setup->erase_exif_thumbnail = s ? strcasecmp (s, "yes") == 0 : FALSE; /* default to FALSE */ - if (s) g_free (s); - s = xml_file_get_node_attribute (xml, "/gallery_setup/meta/use_title_as_meta", "value"); - setup->use_title_as_meta = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ - if (s) g_free (s); - - setup->site_title = xml_file_get_node_attribute (xml, "/gallery_setup/meta/site", "title"); - setup->add_copyright = xml_file_get_node_value (xml, "/gallery_setup/meta/add_copyright/text()"); - s = xml_file_get_node_attribute (xml, "/gallery_setup/navigation/use_inpage_links", "value"); - setup->use_inpage_links = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ - if (s) g_free (s); - - setup->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize"); - - xml_parser_close (xml); - - #ifdef __DEBUG_ALL__ - printf("setup: templates_path = '%s'\n", setup->templates_path); - printf("setup: template_index = '%s'\n", setup->template_index); - printf("setup: template_album = '%s'\n", setup->template_album); - printf("setup: template_photo = '%s'\n", setup->template_photo); - printf("setup: styles = '%s'\n", setup->styles); - printf("setup: scripts = '%s'\n", setup->scripts); - printf("setup: thumbnail_quality = %d\n", setup->thumbnail_quality); - printf("setup: thumbnail_landscape_width = %ld\n", setup->thumbnail_landscape_width); - printf("setup: thumbnail_landscape_height = %ld\n", setup->thumbnail_landscape_height); - printf("setup: thumbnail_portrait_width = %ld\n", setup->thumbnail_portrait_width); - printf("setup: thumbnail_portrait_height = %ld\n", setup->thumbnail_portrait_height); - printf("setup: preview_quality = %d\n", setup->preview_quality); - printf("setup: preview_landscape_width = %ld\n", setup->preview_landscape_width); - printf("setup: preview_landscape_height = %ld\n", setup->preview_landscape_height); - printf("setup: preview_portrait_width = %ld\n", setup->preview_portrait_width); - printf("setup: preview_portrait_height = %ld\n", setup->preview_portrait_height); - printf("setup: footer = '%s'\n", setup->footer); - printf("setup: border_style = '%s'\n", setup->border_style); - printf("setup: meta_author = '%s'\n", setup->meta_author); - printf("setup: meta_description = '%s'\n", setup->meta_description); - printf("setup: meta_keywords = '%s'\n", setup->meta_keywords); - printf("setup: preload = %d\n", setup->preload); - printf("setup: use_iptc_exif = %d\n", setup->use_iptc_exif); - printf("setup: erase_exif_thumbnail = %d\n", setup->erase_exif_thumbnail); - #endif - - return TRUE; -} - - - -int -test_tmpl_access (const char *dir, const char *path) -{ - char *s; - int b; - - s = g_strconcat (dir, "/", path, NULL); - b = access (s, R_OK); - g_free (s); - return b; -} - -int -test_tmpl_files (const char *dir, TGallerySetup *setup) -{ - return test_tmpl_access (dir, setup->template_album) | test_tmpl_access (dir, setup->template_photo) | - test_tmpl_access (dir, setup->template_index) | test_tmpl_access (dir, setup->styles) | - test_tmpl_access (dir, setup->scripts); -} - -/* - * find_templates_directory: absolute/relative path checks, trying to find templates directory - * - returned string should be freed - */ -char * -find_templates_directory (TGallerySetup *setup) -{ - char *base_dir; - char *pth; - - if (IS_DIR_SEP (*setup->templates_path)) - { - #ifdef __DEBUG_ALL__ - printf("Warning: using absolute paths to templates\n"); - #endif - - if (! test_tmpl_files (setup->templates_path, setup)) - return strdup (setup->templates_path); - } - else - { - base_dir = g_path_get_dirname (setup->setup_xml_path); - pth = g_strconcat (base_dir, "/", setup->templates_path, NULL); - g_free (base_dir); - - #ifdef __DEBUG_ALL__ - printf("Warning: using relative paths to templates\n"); - #endif - - if (! test_tmpl_files (pth, setup)) - return pth; - } - - fprintf (stderr, "Couldn't find proper templates directory (tried '%s')\n", setup->templates_path); - return NULL; -} - - -/* - * free_setup_data: free allocated setup data - */ -void -free_setup_data (TGallerySetup *setup) -{ - if (setup) { - if (setup->real_templates_dir) - free (setup->real_templates_dir); - if (setup->setup_xml_path) - free (setup->setup_xml_path); - if (setup->templates_path) - free (setup->templates_path); - if (setup->template_index) - free (setup->template_index); - if (setup->template_album) - free (setup->template_album); - if (setup->template_photo) - free (setup->template_photo); - if (setup->styles) - free (setup->styles); - if (setup->scripts) - free (setup->scripts); - if (setup->footer) - free (setup->footer); - if (setup->meta_author) - free (setup->meta_author); - if (setup->border_style) - free (setup->border_style); - if (setup->site_title) - free (setup->site_title); - if (setup->add_copyright) - free (setup->add_copyright); - free (setup); - setup = NULL; - } -} diff --git a/setup.h b/setup.h deleted file mode 100644 index eea4b17..0000000 --- a/setup.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef __SETUP_H__ -#define __SETUP_H__ - - -#include - - -typedef struct { - gboolean verbose; - char *real_templates_dir; - - char *setup_xml_path; - - char *templates_path; - char *template_index; - char *template_album; - char *template_photo; - char *styles; - char *scripts; - - char *footer; - char *meta_author; - char *meta_description; - char *meta_keywords; - gboolean use_title_as_meta; - - int thumbnail_quality; - unsigned long thumbnail_landscape_width; - unsigned long thumbnail_landscape_height; - unsigned long thumbnail_portrait_width; - unsigned long thumbnail_portrait_height; - - int preview_quality; - unsigned long preview_landscape_width; - unsigned long preview_landscape_height; - unsigned long preview_portrait_width; - unsigned long preview_portrait_height; - - char *border_style; - gboolean nofullsize; - - gboolean preload; - gboolean use_iptc_exif; - gboolean erase_exif_thumbnail; - - char *site_title; - char *add_copyright; - gboolean use_inpage_links; -} TGallerySetup; - - - -/* - * find_setup_xml: try to find setup.xml in standard paths - */ -gboolean find_setup_xml (TGallerySetup *setup); - -/* - * parse_setup_xml: XML parser for setup.xml file - */ -gboolean parse_setup_xml (const char *filename, TGallerySetup *setup); - -/* - * free_setup_data: free allocated setup data - */ -void free_setup_data (TGallerySetup *setup); - -/* - * find_templates_directory: absolute/relative path checks, trying to find templates directory - * - returned string should be freed - */ -char *find_templates_directory (TGallerySetup *setup); - - -#endif /* __SETUP_H__ */ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..443d2f1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,41 @@ +NULL = + +INCLUDES = \ + -DDATADIR=\"$(datadir)\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(WARN_CFLAGS) \ + $(DISABLE_DEPRECATED_CFLAGS) \ + $(LIBS_CFLAGS) \ + -DG_LOG_DOMAIN=\"cgg\" + +bin_PROGRAMS = \ + cgg \ + $(NULL) + +bin_SCRIPTS = \ + cgg-dirgen \ + $(NULL) + +cgg_SOURCES = \ + cgg.c \ + cgg-config.h \ + gallery-utils.c \ + gallery-utils.h \ + generators.c \ + generators.h \ + generators-replace-table.c \ + generators-replace-table.h \ + items.c \ + items.h \ + jpeg-utils.cpp \ + jpeg-utils.h \ + setup.c \ + setup.h \ + xml-parser.c \ + xml-parser.h \ + $(NULL) + +cgg_LDADD = $(LIBS_LIBS) + +EXTRA_DIST = cgg-dirgen diff --git a/src/cgg-config.h b/src/cgg-config.h new file mode 100644 index 0000000..7a447d7 --- /dev/null +++ b/src/cgg-config.h @@ -0,0 +1,30 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + + +/* Directory names of smaller images */ +#define THUMBNAIL_DIR "_thumb" +#define IMG_BIG_DIR "_big" +#define IMG_ORIG_DIR "_orig" + +#define SETUP_XML "setup.xml" + +// #define APP_VERSION "0.99.0" +// #define APP_BUILD_DATE "2008-07-27" + diff --git a/src/cgg-dirgen b/src/cgg-dirgen new file mode 100755 index 0000000..44dd256 --- /dev/null +++ b/src/cgg-dirgen @@ -0,0 +1,54 @@ +#!/bin/bash +## Cataract Gallery Generator - a simple static web photo gallery +## cgg-dirgen - Directory index.xml generator +## Copyright (C) 2008 Tomas Bzatek +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## + +## Optional arguments (must be in order, for now): +## -d Use preview pictures from the "preview" folder +## -o Do not include original image (removes link to original size) +## -t Generate thumbnails from the "thumbnails" folder + + +cat << XML_HEADER_STOP + + + + Album ID + Album Title + + ]]> + + + +XML_HEADER_STOP + +for i in `find -L . -maxdepth 1 -type f -iname '*.jpg' -or -iname '*.jpeg' -or -iname '*.gif' -or -iname '*.png' | sort`; do + INCL=""; + INCL2=""; + INCL3=""; + if [ "$1" = "-d" ]; then INCL=" preview=\"preview/`echo $i | cut -b 3-`\""; fi + if [ "$2" = "-o" ]; then INCL2=" \n"; fi + if [ "$3" = "-t" ]; then INCL3=" thumbnail=\"thumbnails/`echo $i | cut -b 3-`\""; fi + echo -e " \n${INCL2} \n \n \n"; +done + +cat << XML_FOOTER_STOP + + +XML_FOOTER_STOP + diff --git a/src/cgg.c b/src/cgg.c new file mode 100644 index 0000000..042e114 --- /dev/null +++ b/src/cgg.c @@ -0,0 +1,155 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "cgg-config.h" +#include "setup.h" +#include "generators.h" + + + + + + +/* + * parse_cmd: parse commandline and fill global variable parameters + */ +gboolean +parse_cmd (int argc, char* argv[], char **source_dir, char **dst_dir, gboolean *verbose) +{ + static gboolean _verbose = FALSE; + static gchar *_source_dir = NULL; + static gchar *_dst_dir = NULL; + + static GOptionEntry entries[] = + { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &_verbose, "Be verbose", NULL }, + { "source", 's', 0, G_OPTION_ARG_STRING, &_source_dir, "Specifies path to source structure", NULL }, + { "output", 'o', 0, G_OPTION_ARG_STRING, &_dst_dir, "Generate files to the specified directory instead of current", NULL }, + { NULL } + }; + + GError *error = NULL; + GOptionContext *context; + char *s1; + + g_set_prgname ("cgg"); + + context = g_option_context_new ("- web gallery generator"); + s1 = g_strdup_printf ("cgg v%s [%s] Copyright (c) %s Tomas Bzatek", VERSION, APP_BUILD_DATE, APP_COPYRIGHT_DATE); + g_option_context_set_summary (context, s1); + g_free (s1); + g_option_context_add_main_entries (context, entries, NULL); + + if (argc == 1) { + s1 = g_option_context_get_help (context, TRUE, NULL); + g_print ("%s", s1); + g_free (s1); + g_option_context_free (context); + return FALSE; + } + + if (! g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("option parsing failed: %s\n", error->message); + s1 = g_option_context_get_help (context, TRUE, NULL); + g_print ("%s", s1); + g_free (s1); + g_option_context_free (context); + return FALSE; + } + g_option_context_free (context); + + *source_dir = _source_dir; + *dst_dir = _dst_dir; + *verbose = _verbose; + + return TRUE; +} + + + +int +main(int argc, char* argv[]) +{ + char *source_dir; + char *dst_dir; + gboolean verbose; + TGallerySetup *setup; + + /* + * this initialize the library and check potential ABI mismatches + * between the version it was compiled for and the actual shared + * library used. + */ + LIBXML_TEST_VERSION; + + source_dir = NULL; + dst_dir = NULL; + setup = malloc(sizeof(TGallerySetup)); + + + /* Parse commandline */ + if (! parse_cmd (argc, argv, &source_dir, &dst_dir, &verbose)) + return -1; + + if ((! source_dir) || (access (source_dir, R_OK))) { + fprintf (stderr, "error: source directory must be specified and pointing to valid structure\n"); + return -4; + } + if (! dst_dir) { + fprintf (stderr, "error: target directory must be specified\n"); + return -5; + } + + /* Read gallery settings */ + if (! find_setup_xml (setup)) { + fprintf (stderr, "error: could not parse gallery settings file\n"); + return -2; + } + + setup->real_templates_dir = find_templates_directory (setup); + if (setup->real_templates_dir == NULL) { + fprintf (stderr, "error: could not determine templates directory\n"); + return -3; + } + + + /* Start building the gallery tree */ + setup->verbose = verbose; + build_tree (setup, source_dir, dst_dir, NULL); + + + /* Cleanup function for the XML library. */ + xmlCleanupParser(); + + free (source_dir); + free (dst_dir); + free_setup_data (setup); + + return (0); +} diff --git a/src/gallery-utils.c b/src/gallery-utils.c new file mode 100644 index 0000000..6378ae5 --- /dev/null +++ b/src/gallery-utils.c @@ -0,0 +1,262 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gallery-utils.h" + + +/* + * str_replace: replace substring 'search' with a 'replace' string + * - multiple occurrences of the string are replaced + * - reallocates the original string + */ +void +str_replace (char **dst, const char *search, const char *replace) +{ + #define REPLACE_MAX_LENGTH 32768 + static char d[REPLACE_MAX_LENGTH]; + char *src; + char *found; + int i; + + /* TODO: add range checking */ + + if (strstr (*dst, search) == NULL || strlen (*dst) == 0 || strlen (search) == 0) + return; + + i = 0; + src = *dst; + while (strstr (src, search)) { + found = strstr (src, search); + + /* copy the data between search string */ + if (found > src) { + memcpy (&d[i], src, found - src); + i += found - src; + } + + /* copy replace string instead */ + if (strlen (replace) > 0) { + memcpy (&d[i], replace, strlen (replace)); + i += strlen (replace); + } + src = found + strlen (search); + } + + /* copy the rest */ + if (src) { + memcpy (&d[i], src, strlen (src)); + i += strlen (src); + } + d[i] = 0x0; + + +#ifdef __DEBUG_ALL__ + printf ("str_replace('%s', '%s') = '%s' --> '%s'\n", search, replace, *dst, &d[0]); +#endif + + /* return fixed string */ + free (*dst); + *dst = g_strdup (&d[0]); +} + + +/* + * copy_file: copy file from src to dst + */ +gboolean +copy_file (const char *src, const char *dst) +{ + #define BUFFER_SIZE 65536 + + FILE *fin; + FILE *fout; + void *buffer; + int size_r; + struct stat st; + struct utimbuf ut; + + fin = fopen (src, "r"); + if (fin == NULL) { + fprintf (stderr, "copy_file: error reading file \"%s\": %s\n", src, strerror (errno)); + return FALSE; + } + + fout = fopen (dst, "w"); + if (fout == NULL) { + fprintf (stderr, "copy_file: error writing to file \"%s\": %s\n", dst, strerror (errno)); + fclose (fin); + return FALSE; + } + + buffer = malloc (BUFFER_SIZE); + memset (buffer, 0, BUFFER_SIZE); + size_r = BUFFER_SIZE; + + while ((! feof (fin)) && (size_r == BUFFER_SIZE)) { + size_r = fread (buffer, 1, BUFFER_SIZE, fin); + fwrite (buffer, 1, size_r, fout); + } + + fclose (fout); + fclose (fin); + free (buffer); + + /* copy timestamps */ + memset (&st, 0, sizeof (st)); + if (stat (src, &st) == -1) { + fprintf (stderr, "copy_file: cannot stat source file \"%s\": %s\n", src, strerror (errno)); + return TRUE; + } + + memset (&ut, 0, sizeof (ut)); + ut.actime = st.st_atime; + ut.modtime = st.st_mtime; + if (utime (dst, &ut) == -1) + fprintf (stderr, "copy_file: cannot set timestamps on target file \"%s\": %s\n", dst, strerror (errno)); + + return TRUE; +} + + +/* + * make_string: make string of 'substr' substrings + * - returns newly allocated string + */ +char * +make_string (const char* substr, const int count) +{ + int i; + char *s; + + s = malloc (strlen (substr) * count + 1); + for (i = 0; i < count; i++) + memcpy (s + (strlen (substr) * i), substr, strlen (substr)); + s[strlen (substr) * count] = 0; + return s; +} + + +/* + * fix_entities: replace all invalid & entities with & + * - returns newly allocated string + */ +void +fix_entities (char **str) +{ + static char d[REPLACE_MAX_LENGTH]; + char *src; + char *found; + char *scan; + int i; + + /* TODO: add range checking */ + + if (! *str || strstr (*str, "&") == NULL) + return; + + i = 0; + src = *str; + while (strstr (src, "&")) { + found = strstr (src, "&"); + + /* copy the data between search string */ + memcpy (&d[i], src, found - src + 1); + i += found - src + 1; + + /* scroll to next whitespace */ + scan = found + 1; + while (scan && ( + (*scan >= 0x41 && *scan <= 0x5a) || (*scan >= 0x61 && *scan <= 0x7a) || /* A-Z, a-z */ + (*scan >= 0x30 && *scan <= 0x39) || (*scan == 0x23) /* 0-9, # */ + )) + scan++; + + if (scan && (*scan == 0x3b)) { + /* this is semicolon, correctly closed entity */ + /* -- ignore */ + } + else { + /* replace with & */ + memcpy (&d[i], "amp;", 4); + i += 4; + } + src = found + 1; + } + + /* copy the rest */ + if (src) { + memcpy (&d[i], src, strlen (src)); + i += strlen (src); + } + d[i] = 0x0; + + +#ifdef __DEBUG_ALL__ + printf ("fix_entities: '%s' --> '%s'\n", *str, &d[0]); +#endif + + /* return fixed string */ + free (*str); + *str = g_strdup (&d[0]); +} + + +/* + * remove_tags: remove all occurences of tags beginning with tag_begin and ending with tag_end + * - e.g. remove_tags (&x, "") will remove all comments + * - returns newly allocated string + */ +void +remove_tags (char **str, const char *tag_begin, const char *tag_end) +{ + char *src; + char *found; + char *found2; + char *dest; + + if (! *str || ! tag_begin || ! tag_end || strlen (*str) == 0 || strlen (tag_begin) == 0 || strlen (tag_end) == 0) + return; + + src = *str; + + while ((found = strstr (src, tag_begin)) != NULL) { + found2 = strstr (found, tag_end); + if (found2) { + found2 += strlen (tag_end); + dest = malloc (strlen (src) - (found2 - found) + 1); + memcpy (dest, src, found - src); + memcpy (dest + (found - src), found2, strlen (found2) + 1); +#ifdef __DEBUG_ALL__ + printf ("found = %ld, found2 = %ld, strlen = %d, res = %d\n", (long int)found, (long int)found2, strlen (src), strlen (src) - (found2 - found) + 1); + printf ("orig = %s, new = %s, strlen = %d\n", src, dest, strlen (dest)); +#endif + g_free (src); + src = g_strdup (dest); + free (dest); + } + } + *str = src; +} diff --git a/src/gallery-utils.h b/src/gallery-utils.h new file mode 100644 index 0000000..53c82c0 --- /dev/null +++ b/src/gallery-utils.h @@ -0,0 +1,53 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '~') +#define IS_EQUAL_SIGN(ch) ((ch) == '=') + + +/* + * str_replace: replace substring 'search' with a 'replace' string + * - multiple occurences of the string are replaced + * - reallocates the original string + */ +void str_replace (char **dst, const char *search, const char *replace); + +/* + * copy_file: copy file from src to dst + */ +gboolean copy_file (const char *src, const char *dst); + +/* + * make_string: make string of 'substr' substrings + * - returns newly allocated string + */ +char *make_string (const char* substr, const int count); + +/* + * fix_entities: replace all invalid & entities with & + * - returns newly allocated string + */ +void fix_entities (char **str); + +/* + * remove_tags: remove all occurences of tags beginning with tag_begin and ending with tag_end + * - e.g. remove_tags (&x, "") will remove all comments + * - returns newly allocated string + */ +void remove_tags (char **str, const char *tag_begin, const char *tag_end); diff --git a/src/generators-replace-table.c b/src/generators-replace-table.c new file mode 100644 index 0000000..23771fc --- /dev/null +++ b/src/generators-replace-table.c @@ -0,0 +1,174 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2009 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "generators-replace-table.h" +#include "gallery-utils.h" + + + + +#if 0 +static void +replace_table_destroy_notify (gpointer data) +{ + g_print ("replace_table_destroy_notify: %s\n", (gchar *) data); + + if ((gchar *) data) + g_free ((gchar *) data); +} +#endif + +ReplaceTable * +replace_table_new () +{ + return (ReplaceTable *) g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +} + +void +replace_table_free (ReplaceTable *table) +{ + g_return_if_fail (table != NULL); + + g_hash_table_destroy (table); +} + + +/* + * replace_table_add_key: add tag/value pair to replace + * + * tag, value will be referenced inside + * + */ +void +replace_table_add_key (ReplaceTable *table, const gchar *tag, const gchar *value) +{ + g_return_if_fail (table != NULL); + + if (tag != NULL && value != NULL) + g_hash_table_replace (table, g_strdup (tag), g_strdup (value)); +} + +void +replace_table_add_key_int (ReplaceTable *table, const gchar *tag, gint value) +{ + g_return_if_fail (table != NULL); + + if (tag != NULL) + g_hash_table_replace (table, g_strdup (tag), g_strdup_printf ("%d", value)); +} + +void +replace_table_add_key_printf (ReplaceTable *table, const gchar *tag, const gchar *format, ...) +{ + va_list args; + gchar *s = NULL; + + g_return_if_fail (table != NULL); + + if (tag != NULL && format != NULL) { + va_start (args, format); + g_vasprintf (&s, format, args); + g_hash_table_replace (table, g_strdup (tag), s); + va_end (args); + } +} + + + +static void +replace_table_process_value (gpointer key, gpointer value, gpointer user_data) +{ + gchar **buffer = user_data; + gchar *tag; + gchar *tag_value; + + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + g_return_if_fail (user_data != NULL); + + /* replace tags */ + tag = g_strdup_printf ("", (gchar *) key); + tag_value = g_strdup ((gchar *) value); + adjust_tags_normal (&tag_value); + while (strstr (*buffer, tag)) { + str_replace (buffer, tag, tag_value); + } + g_free (tag_value); + g_free (tag); + + /* replace $(xxx) tags */ + tag = g_strdup_printf ("$(%s)", (gchar *) key); + tag_value = g_strdup ((gchar *) value); + adjust_tags_parameter (&tag_value); + while (strstr (*buffer, tag)) { + str_replace (buffer, tag, tag_value); + } + g_free (tag_value); + g_free (tag); +} + +/* + * replace_table_process: process buffer and replace all tags filled in the replace table + * + * - reallocates source buffer + * + */ +void +replace_table_process (gchar **buffer, ReplaceTable *table) +{ + g_return_if_fail (table != NULL); + + g_hash_table_foreach (table, replace_table_process_value, buffer); + +/* + gchar *val = g_hash_table_lookup (table, "TAG"); + g_print ("replace_table_process: val = '%s'\n", val); +*/ +} + + +/* + * adjust_tags_normal: adjust string for normal HTML use + * adjust_tags_parameter: adjust string for use as tag parameter value + * - both funtions return newly allocated string + */ +void +adjust_tags_normal (char **str) +{ + fix_entities (str); +} + +void +adjust_tags_parameter (char **str) +{ + /* TODO: replace line endings with single space? */ + remove_tags (str, ""); /* comments */ + remove_tags (str, "<", ">"); /* tags */ + fix_entities (str); /* entities */ + str_replace (str, "\"", """); /* " */ + str_replace (str, "'", "'"); /* ' */ +} diff --git a/src/generators-replace-table.h b/src/generators-replace-table.h new file mode 100644 index 0000000..d72d150 --- /dev/null +++ b/src/generators-replace-table.h @@ -0,0 +1,63 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2009 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + + +typedef GHashTable ReplaceTable; + +/* + * write_html_album: process album and index template files + * + * template_src = template file of the album/index + * dst = save generated file as + * items = array of items in the album/index + * + */ +ReplaceTable *replace_table_new (); + +void replace_table_free (ReplaceTable *table); + + +/* + * replace_table_add_key: add tag/value pair to replace + * + * tag, value will be referenced inside + * + */ +void replace_table_add_key (ReplaceTable *table, const gchar *tag, const gchar *value); +void replace_table_add_key_int (ReplaceTable *table, const gchar *tag, gint value); +void replace_table_add_key_printf (ReplaceTable *table, const gchar *tag, const gchar *format, ...) G_GNUC_PRINTF (3, 4); + +/* + * replace_table_process: process buffer and replace all tags filled in the replace table + * + * - reallocates source buffer + * + */ +void replace_table_process (gchar **buffer, ReplaceTable *table); + + +/* + * adjust_tags_normal: adjust string for normal HTML use + * adjust_tags_parameter: adjust string for use as tag parameter value + * - both funtions return newly allocated string + */ +void adjust_tags_normal (char **str); +void adjust_tags_parameter (char **str); + diff --git a/src/generators.c b/src/generators.c new file mode 100644 index 0000000..8a2053a --- /dev/null +++ b/src/generators.c @@ -0,0 +1,1037 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "cgg-config.h" +#include "setup.h" +#include "items.h" +#include "jpeg-utils.h" +#include "gallery-utils.h" +#include "generators-replace-table.h" + + +/* + * generate_image: auxiliary function for write_html_album + * - img_src and thumb should be freed afterwards + */ +void +generate_image (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + unsigned int item_index, + const char *dst, + unsigned long *img_w, unsigned long *img_h, + char **img_src, char **thumb) +{ + unsigned long new_w, new_h; + unsigned long thumb_w, thumb_h; + char *thumb_dst; + char *big_dst; + char *big_src; + char *orig_dst; + char *img_src_full; + char *thumb_src_full; + char *s1; + int bigq; + + + *img_src = NULL; + *thumb = NULL; + *img_w = 0; + *img_h = 0; + + if (items->type == GALLERY_TYPE_INDEX) { + if (item->thumbnail == NULL || strlen (item->thumbnail) == 0) + return; + img_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); + thumb_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); + *img_src = g_path_get_basename (item->thumbnail); + s1 = g_path_get_basename (item->thumbnail); + *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); + g_free (s1); + } + else + if (items->type == GALLERY_TYPE_ALBUM) { + *img_src = (item->path == NULL && item->preview) ? item->preview : item->path; + *thumb = (item->thumbnail) ? item->thumbnail : *img_src; + img_src_full = g_strconcat (items->base_dir, "/", *img_src, NULL); + thumb_src_full = g_strconcat (items->base_dir, "/", *thumb, NULL); + *img_src = g_path_get_basename (*img_src); + s1 = g_path_get_basename (*thumb); + *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); + g_free (s1); + } + + get_image_sizes (img_src_full, img_w, img_h); + + if ((img_w > 0) && (img_h > 0)) { + new_w = *img_w; + new_h = *img_h; + + /* Generate thumbnail */ + get_image_sizes (thumb_src_full, &thumb_w, &thumb_h); + s1 = g_path_get_dirname (dst); + thumb_dst = g_strconcat (s1, "/", THUMBNAIL_DIR, "/", *thumb, NULL); + g_free (s1); + if (setup->verbose) printf (" Generating thumbnail of '%s' ...", *thumb); + + if ((thumb_w > 0) && (thumb_h > 0)) { + if ((thumb_w / thumb_h) >= 1) + calculate_sizes (setup->thumbnail_landscape_width, setup->thumbnail_landscape_height, &thumb_w, &thumb_h); + else + calculate_sizes (setup->thumbnail_portrait_width, setup->thumbnail_portrait_height, &thumb_w, &thumb_h); + if (! resize_image (thumb_src_full, thumb_dst, thumb_w, thumb_h, setup->thumbnail_quality, TRUE)) + fprintf (stderr, "write_html_index: error resizing thumbnail %s\n", thumb_src_full); + else + if (setup->verbose) printf (" done.\n"); + g_free (thumb_dst); + } else + printf (" failed!\n"); + + + /* Generate/copy preview and original image */ + if (items->type == GALLERY_TYPE_ALBUM) + { + s1 = g_path_get_dirname (dst); + big_dst = g_strconcat (s1, "/", IMG_BIG_DIR, "/", *img_src, NULL); + g_free (s1); + + if (item->preview == NULL) { + /* No preview image supplied, generate it from original */ + bigq = setup->preview_quality; + if ((items->quality > 0) && (items->quality <= 100)) + bigq = items->quality; + if ((item->quality > 0) && (item->quality <= 100)) + bigq = item->quality; + new_w = *img_w; + new_h = *img_h; + + if (setup->verbose) printf (" Generating preview of '%s' ...", *img_src); + if ((item->width > 0) && (item->height > 0)) { + calculate_sizes (item->width, item->height, &new_w, &new_h); + } else { + if ((*img_w / *img_h) >= 1) + { + if ((items->landscape_width > 0) && (items->landscape_height > 0)) + calculate_sizes (items->landscape_width, items->landscape_height, &new_w, &new_h); + else + calculate_sizes (setup->preview_landscape_width, setup->preview_landscape_height, &new_w, &new_h); + } + else + { + if ((items->portrait_width > 0) && (items->portrait_height > 0)) + calculate_sizes (items->portrait_width, items->portrait_height, &new_w, &new_h); + else + calculate_sizes (setup->preview_portrait_width, setup->preview_portrait_height, &new_w, &new_h); + } + } + + if (! resize_image (img_src_full, big_dst, new_w, new_h, bigq, FALSE)) + fprintf (stderr, "write_html_index: error resizing big image %s\n", img_src_full); + else + if (setup->verbose) printf (" done.\n"); + } + else + { + /* Copy the preview (big) image provided */ + big_src = g_strconcat (items->base_dir, "/", item->preview, NULL); + if (setup->verbose) printf (" Copying preview image '%s' ...", *img_src); + if (! copy_file (big_src, big_dst)) + fprintf (stderr, "write_html_index: error copying preview image %s\n", big_src); + else + if (setup->verbose) printf (" done.\n"); + g_free (big_src); + } + modify_exif (big_dst, setup->erase_exif_thumbnail, setup->add_copyright); + g_free (big_dst); + + if (item->force_fullsize || (items->fullsize && ! item->force_nofullsize) || + (! item->force_nofullsize && ! items->nofullsize && ! setup->nofullsize)) + { + s1 = g_path_get_dirname(dst); + orig_dst = g_strconcat (s1, "/", IMG_ORIG_DIR, "/", *img_src, NULL); + g_free (s1); + if (setup->verbose) printf (" Copying original image '%s' ...", *img_src); + if (! copy_file(img_src_full, orig_dst)) + fprintf (stderr, "write_html_index: error copying original image %s\n", img_src_full); + else + if (setup->verbose) printf(" done.\n"); + modify_exif (orig_dst, setup->erase_exif_thumbnail, setup->add_copyright); + g_free (orig_dst); + } + } + } + g_free (img_src_full); + g_free (thumb_src_full); +} + + + +/* + * write_html_album: process album and index template files + * + * template_src = template file of the album/index + * dst = save generated file as + * items = array of items in the album/index + * + */ +gboolean +write_html_album (TGallerySetup *setup, + const char *template_src, + const char *dst, + TAlbum *items) +{ + #define BUFFER_SIZE 65536 + FILE *fin; + FILE *fout; + char *buffer; + char *buf_img_list_landscape; + char *buf_img_list_portrait; + char *buf_img_separator; + char *buf_go_up_string; + gboolean in_img_list; + gboolean in_img_list_landscape; + gboolean in_img_list_portrait; + gboolean in_img_separator; + gboolean in_go_up_string; + char *b; + char *s1, *s2, *s3, *s4, *s5; + TAlbum *parent; + TIndexItem *item; + TIndexItem *tmp_item; + int level, old_parent_item_index; + gboolean res, bb; + int i; + unsigned long img_w, img_h; + char *img_src; + char *thumb; + unsigned int real_total_items; + ReplaceTable *global_replace_table; + ReplaceTable *local_replace_table; + + + fin = fopen (template_src, "r"); + if (fin == NULL) { + fprintf (stderr, "write_html_index: error reading file \"%s\": %s\n", template_src, strerror (errno)); + return FALSE; + } + fout = fopen (dst, "w"); + if (fout == NULL) { + fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); + fclose (fin); + return FALSE; + } + + buffer = malloc (BUFFER_SIZE); + buf_img_list_landscape = malloc (BUFFER_SIZE); + buf_img_list_portrait = malloc (BUFFER_SIZE); + buf_img_separator = malloc (BUFFER_SIZE); + buf_go_up_string = malloc (BUFFER_SIZE); + in_img_list = FALSE; + in_img_list_landscape = FALSE; + in_img_list_portrait = FALSE; + in_img_separator = FALSE; + in_go_up_string = FALSE; + res = TRUE; + + global_replace_table = replace_table_new (); + + /* Get number of real pictures in the list */ + real_total_items = 0; + for (i = 0; i < items->items->len; i++) { + tmp_item = g_ptr_array_index (items->items, i); + if (tmp_item->type == INDEX_ITEM_TYPE_PICTURE) + real_total_items++; + } + replace_table_add_key_int (global_replace_table, "TOTAL_ITEMS", real_total_items); + + /* Page title */ + if (items->parent_index == NULL || setup->site_title == NULL) + s1 = g_strdup (setup->site_title ? setup->site_title : items->ID); + else + s1 = g_strdup_printf ("%s | %s", items->title, setup->site_title); + replace_table_add_key (global_replace_table, "PAGE_TITLE", s1); + g_free (s1); + + /* Simple placeholders */ + replace_table_add_key (global_replace_table, "ID", items->ID); + replace_table_add_key (global_replace_table, "TITLE", items->title); + replace_table_add_key (global_replace_table, "DESCRIPTION", items->desc); + replace_table_add_key (global_replace_table, "FOOTNOTE", items->footnote); + replace_table_add_key (global_replace_table, "FOOTER", setup->footer); + s1 = setup->use_inpage_links ? g_strdup_printf ("../index.html#i%d", items->parent_item_index + 1) : g_strdup ("../index.html"); + replace_table_add_key (global_replace_table, "GO_UP_LINK", s1); + g_free (s1); + + /* Navigation bar */ + s1 = g_strdup (items->ID); + old_parent_item_index = items->parent_item_index + 1; + parent = items->parent_index; + level = 1; + while (parent) { + s3 = make_string ("../", level); + s4 = g_strdup (parent->ID); + s5 = setup->use_inpage_links ? g_strdup_printf ("#i%d", old_parent_item_index) : g_strdup (""); + s2 = g_strdup_printf ("%s > %s", s3, s5, s4, s1); + free (s3); + g_free (s1); + g_free (s4); + g_free (s5); + s1 = s2; + old_parent_item_index = parent->parent_item_index + 1; + parent = parent->parent_index; + level++; + } + replace_table_add_key (global_replace_table, "NAV_BAR", s1); + g_free (s1); + + /* META tags */ + s1 = g_strdup_printf ("\t\n", VERSION); + if (setup->meta_author || items->meta_author) { + s3 = g_strdup (items->meta_author ? items->meta_author : setup->meta_author); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + if (setup->meta_description || items->meta_description) { + s3 = g_strdup (items->meta_description ? items->meta_description : setup->meta_description); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + if (setup->meta_keywords || items->meta_keywords) { + s3 = g_strdup (items->meta_keywords ? items->meta_keywords : setup->meta_keywords); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + replace_table_add_key (global_replace_table, "CGG_META_TAGS", s1); + g_free (s1); + + + /* Read through the template and replace placeholders with real data */ + while (! feof (fin)) + { + memset (buffer, 0, BUFFER_SIZE); + if (! fgets (buffer, BUFFER_SIZE, fin)) + break; + + /* Block placeholders */ + if (in_img_list && (strstr (buffer, ""))) { + in_img_list_landscape = TRUE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_list_landscape = FALSE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_list_portrait = TRUE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_list_portrait = FALSE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_separator = TRUE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_separator = FALSE; + continue; + } + if (in_img_list && in_img_list_landscape) { + buf_img_list_landscape = strncat (buf_img_list_landscape, buffer, BUFFER_SIZE - strlen (buf_img_list_landscape) - 2); + continue; + } + if (in_img_list && in_img_list_portrait) { + buf_img_list_portrait = strncat (buf_img_list_portrait, buffer, BUFFER_SIZE - strlen (buf_img_list_portrait) - 2); + continue; + } + if (in_img_list && in_img_separator) { + buf_img_separator = strncat (buf_img_separator, buffer, BUFFER_SIZE - strlen (buf_img_separator) - 2); + continue; + } + + if (strstr (buffer, "")) { + memset (buf_go_up_string, 0, BUFFER_SIZE); + in_go_up_string = TRUE; + continue; + } + if (in_go_up_string && strstr (buffer, "")) { + in_go_up_string = FALSE; + if (! items->parent_index) + continue; + } + if (in_go_up_string) { + buf_go_up_string = strncat (buf_go_up_string, buffer, BUFFER_SIZE - strlen (buf_go_up_string) - 2); + continue; + } + + /* Image list, nested placeholders */ + if (strstr (buffer, "")) { + memset (buf_img_list_landscape, 0, BUFFER_SIZE); + memset (buf_img_list_portrait, 0, BUFFER_SIZE); + memset (buf_img_separator, 0, BUFFER_SIZE); + in_img_list = TRUE; + in_img_list_landscape = FALSE; + in_img_list_portrait = FALSE; + in_img_separator = FALSE; + continue; + } + if (in_img_list && (strstr (buffer, ""))) { + in_img_list = FALSE; + in_img_list_landscape = FALSE; + in_img_list_portrait = FALSE; + + /* Now we have all block placeholders read, generate the items: */ + for (i = 0; i < items->items->len; i++) + { + item = g_ptr_array_index (items->items, i); + if (item == NULL) { + fprintf (stderr, "write_html_index: error getting item %d\n", i); + continue; + } + + /* Generate the images (preview, original, thumbnail) */ + local_replace_table = replace_table_new (); + img_w = 0; + img_h = 0; + s1 = NULL; + + switch (item->type) { + case INDEX_ITEM_TYPE_PICTURE: + img_src = NULL; + thumb = NULL; + generate_image (setup, items, item, i, dst, &img_w, &img_h, &img_src, &thumb); + /* Skip HTML code generation if it's a hidden item */ + if (! item->hidden) { + if (img_w == 0 || img_h == 0 || (img_w / img_h) >= 1) + s1 = strdup (buf_img_list_landscape); + else + s1 = strdup (buf_img_list_portrait); + + replace_table_add_key_printf (local_replace_table, "ALBUM_SUBPATH", "%s/index.html", item->path); + replace_table_add_key_printf (local_replace_table, "IMG_SUBPAGE", "%s.html", img_src); + replace_table_add_key (local_replace_table, "IMG_TITLE", item->title); + replace_table_add_key (local_replace_table, "IMG_DESCRIPTION", item->title_description); + replace_table_add_key_printf (local_replace_table, "IMG_LIST_ID", "i%d", i + 1); + replace_table_add_key_printf (local_replace_table, "IMG_THUMBNAIL", "%s/%s", THUMBNAIL_DIR, thumb); + replace_table_add_key (local_replace_table, "IMG_FILENAME", img_src); + if (items->type == GALLERY_TYPE_INDEX) { + s3 = g_strconcat (items->base_dir, "/", item->path, "/index.xml", NULL); + replace_table_add_key_int (local_replace_table, "ALBUM_NUM_ITEMS", get_album_objects_count (s3)); + g_free (s3); + } + } + if (img_src) + g_free (img_src); + if (thumb) + g_free (thumb); + break; + + case INDEX_ITEM_TYPE_SEPARATOR: + s1 = strdup (buf_img_separator); + replace_table_add_key (local_replace_table, "LIST_SEPARATOR_TITLE", item->title); + break; + } + + bb = TRUE; + if (s1) { + replace_table_process (&s1, local_replace_table); + bb = fputs (s1, fout); + free (s1); + } + replace_table_free (local_replace_table); + if (! bb) { + fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); + res = FALSE; + break; + } + } + continue; /* no need to write anything */ + } + + /* Select apropriate line buffer */ + if (strstr (buffer, "") && items->parent_index) { + b = strdup (buf_go_up_string); + } else + b = strdup (buffer); + + /* Replace all known tags */ + replace_table_process (&b, global_replace_table); + + /* Write to file */ + bb = fputs (b, fout); + free (b); + if (! bb) { + fprintf (stderr, "write_html_index: error writing to file \"%s\": %s\n", dst, strerror (errno)); + res = FALSE; + break; + } + } + + fclose (fout); + fclose (fin); + replace_table_free (global_replace_table); + free (buffer); + free (buf_img_list_landscape); + free (buf_img_list_portrait); + free (buf_img_separator); + free (buf_go_up_string); + return res; +} + + +/* + * write_html_image: process single image template file + * + * template_src = template file of the album/index + * original_img = source image file (original full-size) to get EXIF data from + * dst = save generated file as + * item = data for the current item + * parent_items = array of items in the album, to determine our position and make links to previous/next image + * + */ +gboolean +write_html_image (TGallerySetup *setup, + const char *template_src, + const char *original_img, + const char *dst, + TIndexItem *item, + TAlbum *parent_items) +{ + #define BUFFER_SIZE 65536 + FILE *fin; + FILE *fout; + char *buffer; + char *big_dst; + char *orig_dst; + char *buf_img_fullsize_link; + gboolean in_img_fullsize_link; + TExifData *exif; + unsigned long img_big_w, img_big_h, img_orig_w, img_orig_h; + unsigned int item_index, real_item_index, real_total_items; + TIndexItem *previous_item; + TIndexItem *next_item; + TIndexItem *tmp_item; + TAlbum *parent; + int i; + char *s1, *s2, *s3, *s4, *s5; + char *imgname, *preload_imgname; + char *title, *title_desc; + char *b; + gboolean res, bb; + int level, old_parent_item_index; + gboolean override_title_meta; + gboolean image_fullsize; + ReplaceTable *replace_table; + + + fin = fopen (template_src, "r"); + if (fin == NULL) { + fprintf (stderr, "write_html_image: error reading file \"%s\": %s\n", template_src, strerror (errno)); + return FALSE; + } + fout = fopen (dst, "w"); + if (fout == NULL) { + fprintf (stderr, "write_html_image: error writing to file \"%s\": %s\n", dst, strerror (errno)); + fclose (fin); + return FALSE; + } + + buffer = malloc (BUFFER_SIZE); + preload_imgname = NULL; + + replace_table = replace_table_new (); + + /* Get our index in the album */ + item_index = 0; + real_item_index = 0; + real_total_items = 0; + for (i = 0; i < parent_items->items->len; i++) { + tmp_item = g_ptr_array_index (parent_items->items, i); + if (tmp_item->type == INDEX_ITEM_TYPE_PICTURE) { + if (! item_index) real_item_index++; + real_total_items++; + } + if (tmp_item == item) + item_index = i + 1; + } + + /* Get previous and next items */ + previous_item = NULL; + next_item = NULL; + for (i = item_index - 2; i >= 0 && (previous_item == NULL || previous_item->type != INDEX_ITEM_TYPE_PICTURE); i--) + previous_item = g_ptr_array_index (parent_items->items, i); + if (previous_item && previous_item->type != INDEX_ITEM_TYPE_PICTURE) + previous_item = NULL; + for (i = item_index; item_index < parent_items->items->len && (next_item == NULL || next_item->type != INDEX_ITEM_TYPE_PICTURE); i++) + next_item = g_ptr_array_index (parent_items->items, i); + if (next_item && next_item->type != INDEX_ITEM_TYPE_PICTURE) + next_item = NULL; + + /* Paths setup */ + imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); + if (next_item && setup->preload) { + s1 = g_path_get_basename ((next_item->path == NULL && next_item->preview) ? next_item->preview : next_item->path); + preload_imgname = g_strconcat (IMG_BIG_DIR, "/", s1, NULL); + g_free (s1); + } + s1 = g_path_get_dirname (dst); + big_dst = g_strconcat (s1, "/", IMG_BIG_DIR, "/", imgname, NULL); + orig_dst = g_strconcat (s1, "/", IMG_ORIG_DIR, "/", imgname, NULL); + g_free (s1); + buf_img_fullsize_link = malloc (BUFFER_SIZE); + memset (buf_img_fullsize_link, 0, BUFFER_SIZE); + in_img_fullsize_link = FALSE; + res = TRUE; + + /* Get EXIF data from the original image */ + if (get_exif (original_img, &exif)) + fprintf (stderr, "write_html_image: error getting exif data from file \"%s\"\n", orig_dst); + + /* Retrieve image sizes of preview and original image */ + get_image_sizes (big_dst, &img_big_w, &img_big_h); + image_fullsize = item->force_fullsize || (parent_items->fullsize && ! item->force_nofullsize) || + (! item->force_nofullsize && ! parent_items->nofullsize && ! setup->nofullsize); + if (image_fullsize) + get_image_sizes (orig_dst, &img_orig_w, &img_orig_h); + + /* Get title and description from IPTC/EXIF/JPEG if not defined */ + title = g_strdup (item->title); + title_desc = g_strdup (item->title_description); + if (setup->use_iptc_exif && title == NULL && title_desc == NULL) { + if (exif->iptc_caption) + title = g_strdup (exif->iptc_caption); + if (exif->jpeg_comment) { + if (! title) + title = g_strdup (exif->jpeg_comment); + else + title_desc = g_strdup (exif->jpeg_comment); + } + if (exif->exif_imgdesc) { + if (! title) + title = g_strdup (exif->exif_imgdesc); +/* if (! title_desc) -- disabled + title_desc = g_strdup (exif->exif_imgdesc); */ + } + if (exif->exif_usercomment) { + if (! title) + title = g_strdup (exif->exif_usercomment); + if (! title_desc) + title_desc = g_strdup (exif->exif_usercomment); + } + /* Convert line breaks to be visible in the HTML code */ + if (title) { + str_replace (&title, "\r\n", "
"); + str_replace (&title, "\n", "
"); + } + if (title_desc) { + str_replace (&title_desc, "\r\n", "
"); + str_replace (&title_desc, "\n", "
"); + } + } + if (title) title = g_strstrip (title); + if (title_desc) title_desc = g_strstrip (title_desc); + + /* Page title */ + s1 = (title && strlen (title) > 0) ? g_strdup_printf("%s | ", title) : NULL; + s2 = g_strdup_printf ("%s [%d/%d]", parent_items->title ? parent_items->title : parent_items->ID, real_item_index, real_total_items); + s3 = setup->site_title ? g_strdup_printf(" | %s", setup->site_title) : NULL; + s4 = g_strconcat (s1 ? s1 : "", s2, s3 ? s3 : "", NULL); + replace_table_add_key (replace_table, "PAGE_TITLE", s4); + if (s1) g_free (s1); + if (s2) g_free (s2); + if (s3) g_free (s3); + g_free (s4); + + /* Simple placeholders */ + replace_table_add_key (replace_table, "FILE_NAME", imgname); + replace_table_add_key (replace_table, "TITLE", title); + replace_table_add_key (replace_table, "DESCRIPTION", title_desc); + replace_table_add_key (replace_table, "FOOTER", setup->footer); + replace_table_add_key_int (replace_table, "TOTAL_ITEMS", real_total_items); + replace_table_add_key_int (replace_table, "FILE_NO", real_item_index); + replace_table_add_key_int (replace_table, "IMG_SIZE_BIG_W", img_big_w); + replace_table_add_key_int (replace_table, "IMG_SIZE_BIG_H", img_big_h); + replace_table_add_key_int (replace_table, "IMG_SIZE_ORIG_W", img_orig_w); + replace_table_add_key_int (replace_table, "IMG_SIZE_ORIG_H", img_orig_h); + replace_table_add_key_printf (replace_table, "IMG_SRC_BIG", "%s/%s", IMG_BIG_DIR, imgname); + replace_table_add_key_printf (replace_table, "IMG_SRC_FULL", "%s/%s", IMG_ORIG_DIR, imgname); + replace_table_add_key (replace_table, "IMG_SRC_PRELOAD", preload_imgname ? preload_imgname : ""); + + /* Navigation bar */ + s1 = g_strdup (imgname); + parent = parent_items; + level = 0; + while (parent) { + s3 = make_string ("../", level); + s4 = g_strdup (parent->ID); + s5 = setup->use_inpage_links ? g_strdup_printf ("#i%d", parent == parent_items ? item_index : old_parent_item_index) : g_strdup (""); + s2 = g_strdup_printf ("%s > %s", s3, s5, s4, s1); + free (s3); + g_free (s1); + g_free (s4); + g_free (s5); + s1 = s2; + old_parent_item_index = parent->parent_item_index + 1; + parent = parent->parent_index; + level++; + } + replace_table_add_key (replace_table, "NAV_BAR", s1); + g_free (s1); + + /* EXIF values */ + replace_table_add_key (replace_table, "EXIF_ISO", exif->iso ? exif->iso : "??"); + replace_table_add_key (replace_table, "EXIF_TIME", exif->exposure ? exif->exposure : "??"); + replace_table_add_key (replace_table, "EXIF_APERTURE", exif->aperture ? exif->aperture : "??"); + replace_table_add_key (replace_table, "EXIF_FOCAL_LENGTH", exif->focal_length ? exif->focal_length : "??"); + replace_table_add_key (replace_table, "EXIF_FLASH", exif->flash ? exif->flash : "??"); + replace_table_add_key (replace_table, "EXIF_DATE", exif->datetime ? exif->datetime : "??"); + replace_table_add_key (replace_table, "EXIF_CAMERA_MODEL", exif->camera_model ? exif->camera_model : "??"); + s1 = g_strdup_printf ("(%s)", exif->focal_length_35mm); + replace_table_add_key (replace_table, "EXIF_FOCAL_35", exif->focal_length_35mm ? s1 : ""); + g_free (s1); + + /* Border style */ + s1 = item->border_style; + if (s1 == NULL) + s1 = parent_items->border_style; + if (s1 == NULL) + s1 = setup->border_style; + if (s1 == NULL) + s1 = "border_single"; + replace_table_add_key (replace_table, "IMG_BORDER_STYLE", s1); + + /* Next/Previous links */ + if (next_item) { + s2 = g_path_get_basename ((next_item->path == NULL && next_item->preview) ? next_item->preview : next_item->path); + replace_table_add_key_printf (replace_table, "LINK_NEXT", "%s.html", s2); + g_free (s2); + } + else + replace_table_add_key (replace_table, "LINK_NEXT", "index.html"); + if (previous_item) { + s2 = g_path_get_basename ((previous_item->path == NULL && previous_item->preview) ? previous_item->preview : previous_item->path); + replace_table_add_key_printf (replace_table, "LINK_PREV", "%s.html", s2); + g_free (s2); + } + else + replace_table_add_key (replace_table, "LINK_PREV", "index.html"); + + /* META tags */ + override_title_meta = setup->use_title_as_meta && title && (strlen (title) > 0); + s1 = g_strdup_printf ("\t\n", VERSION); + if (setup->meta_author || parent_items->meta_author) { + s3 = g_strdup (parent_items->meta_author ? parent_items->meta_author : setup->meta_author); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + if (setup->meta_description || parent_items->meta_description || override_title_meta) { + s3 = g_strdup (override_title_meta ? title : (parent_items->meta_description ? parent_items->meta_description : setup->meta_description)); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + if ((setup->meta_keywords || parent_items->meta_keywords) && (! override_title_meta)) { + s3 = g_strdup (parent_items->meta_keywords ? parent_items->meta_keywords : setup->meta_keywords); + adjust_tags_parameter (&s3); + s2 = g_strdup_printf ("%s\t\n", s1, s3); + g_free (s3); + g_free (s1); + s1 = s2; + } + replace_table_add_key (replace_table, "CGG_META_TAGS", s1); + g_free (s1); + + + /* Read through the template and replace placeholders with real data */ + while (! feof (fin)) { + memset (buffer, 0, BUFFER_SIZE); + if (! fgets (buffer, BUFFER_SIZE, fin)) + break; + + /* Block placeholders */ + if (strstr (buffer, "")) { + in_img_fullsize_link = TRUE; + continue; + } + if (strstr (buffer, "")) { + in_img_fullsize_link = FALSE; + if (! image_fullsize) /* write down the block later in this cycle */ + continue; + } + if (in_img_fullsize_link) { + buf_img_fullsize_link = strncat (buf_img_fullsize_link, buffer, BUFFER_SIZE - strlen (buf_img_fullsize_link) - 2); + continue; + } + + /* Select apropriate line buffer */ + if (strstr (buffer, "") && image_fullsize) { + b = strdup (buf_img_fullsize_link); + } else + b = strdup (buffer); + + /* Replace all known tags */ + replace_table_process (&b, replace_table); + + /* Write to file */ + bb = fputs (b, fout); + free (b); + if (! bb) { + fprintf (stderr, "write_html_image: error writing to file \"%s\": %s\n", dst, strerror (errno)); + res = FALSE; + break; + } + } + + fclose (fout); + fclose (fin); + if (title) g_free (title); + if (title_desc) g_free (title_desc); + free (buffer); + free (big_dst); + free (orig_dst); + free (buf_img_fullsize_link); + g_free (imgname); + if (preload_imgname) + g_free (preload_imgname); + free_exif_data (exif); + replace_table_free (replace_table); + return res; +} + + +/* + * build_tree: generate complete gallery tree based on source xml files + * + * src_tree = source directory of the items + * dst_dir = destination of the generated items + * parent_index = parent album to determine our descent in the tree + * + */ +gboolean +build_tree (TGallerySetup *setup, + const char *src_tree, + const char *dst_dir, + TAlbum *parent_index, + int parent_item_index) +{ + char *idx_file; + TAlbum *items; + TIndexItem *item; + char *s1, *s2, *s3; + char *thumb_dir; + char *img_big_dir; + char *img_orig_dir; + char *template; + char *imgname; + gboolean res; + int i; + + printf ("*** Entering directory '%s'\n", src_tree); + #ifdef __DEBUG_ALL__ + printf ("setup->real_templates_dir = %s\n", setup->real_templates_dir); + #endif + + /* Check access permissions */ + if (access (src_tree, R_OK)) { + fprintf (stderr, "error accessing source directory: %s\n", strerror (errno)); + return FALSE; + } + if (access (dst_dir, R_OK | W_OK | X_OK)) { + if (mkdir (dst_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + fprintf (stderr, "error creating destination directory: %s\n", strerror (errno)); + return FALSE; + } + } + + /* Check the index file */ + idx_file = g_strconcat (src_tree, "/index.xml", NULL); + if (access (idx_file, R_OK)) { + fprintf (stderr, "error accessing index file '%s': %s\n", idx_file, strerror (errno)); + g_free (idx_file); + return FALSE; + } + + /* Read the index file and fill items array */ + items = malloc (sizeof (TAlbum)); + memset (items, 0, sizeof (TAlbum)); + if (! parse_album_xml (idx_file, items)) { + fprintf (stderr, "error reading index file '%s'\n", idx_file); + g_free (idx_file); + free_album_data (items); + return FALSE; + } + g_free (idx_file); + items->parent_index = parent_index; + items->parent_item_index = parent_item_index; + + + /* Copy support files */ + if (setup->verbose) printf ("Writing '%s' ...", setup->styles); + s1 = g_strconcat (setup->real_templates_dir, "/", setup->styles, NULL); + s2 = g_strconcat (dst_dir, "/", setup->styles, NULL); + copy_file (s1, s2); + g_free (s1); + g_free (s2); + if (setup->verbose) printf (" done.\n"); + + if (setup->verbose) printf ("Writing '%s' ...", setup->scripts); + s1 = g_strconcat (setup->real_templates_dir, "/", setup->scripts, NULL); + s2 = g_strconcat (dst_dir, "/", setup->scripts, NULL); + copy_file (s1, s2); + g_free (s1); + g_free (s2); + if (setup->verbose) printf (" done.\n"); + + + /* Prepare target thumbnail directory */ + thumb_dir = g_strconcat (dst_dir, "/", THUMBNAIL_DIR, NULL); + if (access (thumb_dir, R_OK | W_OK | X_OK)) + if (mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + fprintf (stderr, "error making target thumbnail directory: %s\n", strerror (errno)); + g_free (thumb_dir); + free_album_data (items); + return FALSE; + } + g_free (thumb_dir); + + /* Prepare target preview and orig directories */ + if (items->type == GALLERY_TYPE_ALBUM) + { + res = TRUE; + img_big_dir = g_strconcat (dst_dir, "/", IMG_BIG_DIR, NULL); + img_orig_dir = g_strconcat (dst_dir, "/", IMG_ORIG_DIR, NULL); + if (access (img_big_dir, R_OK | W_OK | X_OK)) + if (mkdir (img_big_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + fprintf (stderr, "error making target preview directory: %s\n", strerror (errno)); + res = FALSE; + } + if (access (img_orig_dir, R_OK | W_OK | X_OK)) + if (mkdir (img_orig_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { + fprintf (stderr, "error making target full size directory: %s\n", strerror (errno)); + res = FALSE; + } + g_free (img_big_dir); + g_free (img_orig_dir); + if (! res) { + free_album_data (items); + return FALSE; + } + } + + + /* Start generating items */ + if (items->type == GALLERY_TYPE_INDEX) + template = g_strconcat ("/", setup->template_index, NULL); + else + if (items->type == GALLERY_TYPE_ALBUM) + template = g_strconcat ("/", setup->template_album, NULL); + + if (setup->verbose) printf ("Writing 'index.html' ...\n"); + s1 = g_strconcat (setup->real_templates_dir, template, NULL); + s2 = g_strconcat (dst_dir, "/index.html", NULL); + res = write_html_album (setup, s1, s2, items); + g_free (s1); + g_free (s2); + g_free (template); + if (! res) { + fprintf (stderr, "error generating target index file\n"); + free_album_data (items); + return FALSE; + } + if (setup->verbose) printf (" done.\n"); + + + /* Recurse to sub-albums (in case of album index) */ + if (items->type == GALLERY_TYPE_INDEX) + { + if (items->items->len > 0) { + for (i = 0; i < items->items->len; i++) { + item = g_ptr_array_index (items->items, i); + if (item == NULL) { + fprintf (stderr, "build_tree: error getting item %d\n", i); + continue; + } + if (item->type == INDEX_ITEM_TYPE_PICTURE) { + s1 = g_strconcat (src_tree, "/", item->path, "/", NULL); + s2 = g_strconcat (dst_dir, "/", item->path, "/", NULL); + build_tree (setup, s1, s2, items, i); + g_free (s1); + g_free (s2); + } + } + } + } + + /* Generate separate image pages (in case of album) */ + if (items->type == GALLERY_TYPE_ALBUM) + { + if (items->items->len > 0) { + for (i = 0; i < items->items->len; i++) { + item = g_ptr_array_index (items->items, i); + if (item == NULL) { + fprintf (stderr, "build_tree: error getting item %d\n", i); + continue; + } + if (item->type == INDEX_ITEM_TYPE_PICTURE) { + imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); + if (setup->verbose) printf ("Writing '%s.html' ...", imgname); + s1 = g_strconcat (setup->real_templates_dir, "/", setup->template_photo, NULL); + s2 = g_strconcat (items->base_dir, "/", (item->path == NULL && item->preview) ? item->preview : item->path, NULL); + s3 = g_strconcat (dst_dir, "/", imgname, ".html", NULL); + res = write_html_image (setup, s1, s2, s3, item, items); + g_free (s1); + g_free (s2); + g_free (s3); + g_free (imgname); + if (! res ) continue; + if (setup->verbose) printf (" done.\n"); + } + } + } + } + + printf ("*** Leaving directory '%s'\n", src_tree); + free_album_data (items); + + return TRUE; +} diff --git a/src/generators.h b/src/generators.h new file mode 100644 index 0000000..c87e8a3 --- /dev/null +++ b/src/generators.h @@ -0,0 +1,64 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "setup.h" +#include "items.h" + + +/* + * write_html_album: process album and index template files + * + * template_src = template file of the album/index + * dst = save generated file as + * items = array of items in the album/index + * + */ +gboolean write_html_album (TGallerySetup *setup, + const char *template_src, + const char *dst, + TAlbum *items); + +/* + * write_html_image: process single image template file + * + * template_src = template file of the album/index + * original_img = source image file (original full-size) to get EXIF data from + * dst = save generated file as + * item = data for the current item + * parent_items = array of items in the album, to determine our position and make links to previous/next image + * + */ +gboolean write_html_image (TGallerySetup *setup, + const char *template_src, + const char *original_img, + const char *dst, + TIndexItem *item, + TAlbum *parent_items); + +/* + * build_tree: generate complete gallery tree based on source xml files + * + * src_tree = source directory of the items + * dst_dir = destination of the generated items + * parent_index = parent album to determine our descent in the tree + * + */ +gboolean build_tree (TGallerySetup *setup, + const char *src_tree, + const char *dst_dir, + TAlbum *parent_index); + diff --git a/src/items.c b/src/items.c new file mode 100644 index 0000000..986fd6c --- /dev/null +++ b/src/items.c @@ -0,0 +1,320 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include + +#include +#include +#include +#include + +#include "items.h" +#include "xml-parser.h" + + + +/* + * parse_album_xml: XML parser for gallery index.xml files + */ +gboolean +parse_album_xml (const char *filename, TAlbum *index) +{ + TXMLFile *xml; + char *gallery_type; + int count; + int i; + char *s, *s2; + char *node_name; + TIndexItem *item; + + xml = xml_parser_load (filename); + if (xml == NULL) + return FALSE; + + /* Initialize data struct */ + if (index == NULL) + index = malloc (sizeof (TAlbum)); + memset (index, 0, sizeof (TAlbum)); + + index->base_dir = g_path_get_dirname (filename); + + /* Retrieve gallery type */ + gallery_type = xml_file_get_node_attribute (xml, "/gallery", "type"); + #ifdef __DEBUG_ALL__ + printf("gallery_type = %s\n", gallery_type); + #endif + if (strcmp (gallery_type, "index") == 0) + index->type = GALLERY_TYPE_INDEX; + else + if (strcmp (gallery_type, "album") == 0) + index->type = GALLERY_TYPE_ALBUM; + else { + printf ("Invalid gallery type (%s)\n", gallery_type); + free (index); + return FALSE; + } + + /* Section General */ + index->ID = xml_file_get_node_value (xml, "/gallery/general/ID/text()"); + index->title = xml_file_get_node_value (xml, "/gallery/general/title/text()"); + index->desc = xml_file_get_node_value (xml, "/gallery/general/description/text()"); + index->footnote = xml_file_get_node_value (xml, "/gallery/general/footnote/text()"); + + index->quality = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "quality", -1); + index->landscape_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_w", 0); + index->landscape_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_h", 0); + index->portrait_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_w", 0); + index->portrait_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_h", 0); + + index->border_style = xml_file_get_node_attribute (xml, "/gallery/general/border", "style"); + index->meta_author = xml_file_get_node_value (xml, "/gallery/general/meta/author/text()"); + index->meta_description = xml_file_get_node_value (xml, "/gallery/general/meta/description/text()"); + index->meta_keywords = xml_file_get_node_value (xml, "/gallery/general/meta/keywords/text()"); + + index->nofullsize = xml_file_get_node_present (xml, "/gallery/general/nofullsize"); + index->fullsize = xml_file_get_node_present (xml, "/gallery/general/fullsize"); + + /* Section Items */ + count = xml_file_node_get_children_count (xml, "/gallery/items/*"); + #ifdef __DEBUG_ALL__ + printf("parse_album_xml: items count = %d\n", count); + #endif + index->items = g_ptr_array_new(); + + for (i = 0; i < count; i++) + { + item = malloc (sizeof (TIndexItem)); + memset (item, 0, sizeof (TIndexItem)); + + s = g_strdup_printf ("/gallery/items/*[%d]", i + 1); + node_name = xml_file_get_node_name (xml, s); + if (! node_name) continue; + #ifdef __DEBUG_ALL__ + printf("parse_album_xml: item[%d] = '%s'\n", i + 1, node_name); + #endif + + if (strcmp (node_name, "item") == 0) { + item->type = INDEX_ITEM_TYPE_PICTURE; + if (index->type == GALLERY_TYPE_INDEX) + item->path = xml_file_get_node_attribute (xml, s, "path"); + else + item->path = xml_file_get_node_attribute (xml, s, "src"); + item->preview = xml_file_get_node_attribute (xml, s, "preview"); + item->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1); + item->width = xml_file_get_node_attribute_long (xml, s, "width", 0); + item->height = xml_file_get_node_attribute_long (xml, s, "height", 0); + item->border_style = xml_file_get_node_attribute (xml, s, "border"); + if (index->type == GALLERY_TYPE_ALBUM) + item->thumbnail = xml_file_get_node_attribute (xml, s, "thumbnail"); + g_free (s); + + s = g_strdup_printf ("/gallery/items/*[%d]/title/text()", i + 1); + item->title = xml_file_get_node_value (xml, s); + g_free (s); + + s = g_strdup_printf ("/gallery/items/*[%d]/title_description/text()", i + 1); + item->title_description = xml_file_get_node_value (xml, s); + g_free (s); + + if (index->type == GALLERY_TYPE_INDEX) { + s = g_strdup_printf ("/gallery/items/*[%d]/thumbnail", i + 1); + item->thumbnail = xml_file_get_node_attribute (xml, s, "src"); + g_free (s); + } + + s = g_strdup_printf ("/gallery/items/*[%d]/nofullsize", i + 1); + item->force_nofullsize = (xml_file_get_node_present (xml, s) || item->path == NULL); + g_free (s); + + s = g_strdup_printf ("/gallery/items/*[%d]/fullsize", i + 1); + item->force_fullsize = xml_file_get_node_present (xml, s); + g_free (s); + + s = g_strdup_printf ("/gallery/items/*[%d]/hidden", i + 1); + item->hidden = (xml_file_get_node_present (xml, s)); + g_free (s); + + /* Retrieve title and description from linked album if not defined here */ + if (index->type == GALLERY_TYPE_INDEX && + item->title == NULL && item->title_description == NULL) { + s = g_strconcat (index->base_dir, "/", item->path, "/index.xml", NULL); + get_album_titles (s, &item->title, &item->title_description, NULL); + g_free (s); + } + + /* Retrieve thumbnail from linked album if not defined here */ + if (index->type == GALLERY_TYPE_INDEX && item->thumbnail == NULL) { + s = g_strconcat (index->base_dir, "/", item->path, "/index.xml", NULL); + s2 = NULL; + get_album_titles (s, NULL, NULL, &s2); + if (s2) { + item->thumbnail = g_strconcat (item->path, "/", s2, NULL); + g_free (s2); + } + g_free (s); + } + + if (item->path || item->preview) + { + g_ptr_array_add (index->items, item); + } + else + { + fprintf (stderr, "%s: No image src specified, skipping!\n", filename); + free (item); + } + } + else + if (strcmp (node_name, "separator") == 0) { + item->type = INDEX_ITEM_TYPE_SEPARATOR; + + s = g_strdup_printf ("/gallery/items/*[%d]/text()", i + 1); + item->title = xml_file_get_node_value (xml, s); + g_free (s); + + g_ptr_array_add (index->items, item); + } + else { + /* Free the item if nobody cares */ + free (item); + } + free (node_name); + } + + xml_parser_close (xml); + + /* Print the items */ + #ifdef __DEBUG_ALL__ + printf ("ID = '%s'\ntitle = '%s'\ndescription = '%s'\n", index->ID, index->title, index->desc); + for (i = 0; i < index->items->len; i++) { + TIndexItem *item = g_ptr_array_index (index->items, i); + printf ("item %d: path = '%s', title = '%s', title_description = '%s', thumbnail = '%s'\n", + i, item->path, item->title, item->title_description, item->thumbnail); + } + #endif + return TRUE; +} + + +/* + * free_album_data: free allocated album data + */ +void +free_album_data (TAlbum *album) +{ + if (album) { + if (album->ID) + free (album->ID); + if (album->title) + free (album->title); + if (album->desc) + free (album->desc); + if (album->footnote) + free (album->footnote); + if (album->base_dir) + free (album->base_dir); + if (album->border_style) + free (album->border_style); + if (album->meta_author) + free (album->meta_author); + if (album->meta_description) + free (album->meta_description); + if (album->meta_keywords) + free (album->meta_keywords); + + if (album->items) { + if (album->items->len > 0) { + TIndexItem *item; + int i; + + for (i = 0; i < album->items->len; i++) { + item = g_ptr_array_index (album->items, i); + if (item != NULL) { + if (item->path) + free (item->path); + if (item->title) + free (item->title); + if (item->title_description) + free (item->title_description); + if (item->thumbnail) + free (item->thumbnail); + if (item->preview) + free (item->preview); + if (item->border_style) + free (item->border_style); + free (item); + } + } + } + g_ptr_array_free (album->items, TRUE); + } + free (album); + album = NULL; + } +} + + +/* + * get_gallery_objects_count: retrieve number of items in specified album + */ +int +get_album_objects_count (const char *filename) +{ + TXMLFile *xml; + int count; + + xml = xml_parser_load (filename); + if (xml == NULL) + return 0; + + count = xml_file_node_get_children_count (xml, "/gallery/items/item"); + xml_parser_close (xml); + + #ifdef __DEBUG_ALL__ + printf ("get_objects_count(%s) = %d\n", filename, count); + #endif + return count; +} + +/* + * get_album_titles: retrieve title, description and first thumbnail from specified album + */ +void +get_album_titles (const char *filename, char **title, char **description, char **thumbnail) +{ + TXMLFile *xml; + + xml = xml_parser_load (filename); + if (xml == NULL) + return; + + if (title) + *title = xml_file_get_node_value (xml, "/gallery/general/title/text()"); + if (description) + *description = xml_file_get_node_value (xml, "/gallery/general/description/text()"); + if (thumbnail) { + *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]/thumbnail", "src"); + if (! *thumbnail) + *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "src"); + if (! *thumbnail) + *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "preview"); + } + + xml_parser_close (xml); +} diff --git a/src/items.h b/src/items.h new file mode 100644 index 0000000..9fd6822 --- /dev/null +++ b/src/items.h @@ -0,0 +1,96 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __ITEMS_H__ +#define __ITEMS_H__ + + +#include + + +typedef enum { + GALLERY_TYPE_INDEX = 1 << 0, + GALLERY_TYPE_ALBUM = 1 << 1 +} TGalleryType; + +typedef enum { + INDEX_ITEM_TYPE_PICTURE = 1 << 0, + INDEX_ITEM_TYPE_SEPARATOR = 1 << 1 +} TIndexItemType; + +typedef struct { + TGalleryType type; + char *ID; + char *title; + char *desc; + char *footnote; + GPtrArray *items; + char *base_dir; + void *parent_index; /* pointer to the parent TAlbum structure */ + int parent_item_index; /* item index in the parent album */ + int quality; + unsigned long landscape_width; + unsigned long landscape_height; + unsigned long portrait_width; + unsigned long portrait_height; + char *border_style; + char *meta_author; + char *meta_description; + char *meta_keywords; + gboolean nofullsize; + gboolean fullsize; +} TAlbum; + +typedef struct { + char *path; + char *title; + char *title_description; + char *thumbnail; + char *preview; + int quality; + unsigned long width; + unsigned long height; + gboolean force_nofullsize; + gboolean force_fullsize; + char *border_style; + TIndexItemType type; + gboolean hidden; +} TIndexItem; + + + +/* + * parse_album_xml: XML parser for gallery index.xml files + */ +gboolean parse_album_xml (const char *filename, TAlbum *index); + +/* + * free_album_data: free allocated album data + */ +void free_album_data (TAlbum *index); + +/* + * get_album_objects_count: retrieve number of items in specified album + */ +int get_album_objects_count (const char *filename); + +/* + * get_album_titles: retrieve title, description and first thumbnail from specified album + */ +void get_album_titles (const char *filename, char **title, char **description, char **thumbnail); + +#endif /* __ITEMS_H__ */ diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp new file mode 100644 index 0000000..501f7ea --- /dev/null +++ b/src/jpeg-utils.cpp @@ -0,0 +1,429 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include + +#include +#include + +#include + +#include "jpeg-utils.h" + + + +/* + * get_exif: retrieve EXIF informations from a JPEG image + */ +int +get_exif (const char *filename, TExifData **exif_data) +{ + TExifData *data; + + data = (TExifData*) malloc (sizeof (TExifData)); + memset (data, 0, sizeof (TExifData)); + *exif_data = data; + + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename); + g_assert (image.get() != 0); + image->readMetadata(); + + Exiv2::ExifData &exifData = image->exifData(); + if (! exifData.empty()) { + /* EXIF::Aperture */ + try { + float val = exifData["Exif.Photo.FNumber"].toFloat(); + if (val >= 0) + data->aperture = g_strdup_printf ("f/%.1f", val); + } catch (...) { } + + /* EXIF::Camera model */ + try { + const char *val = exifData["Exif.Image.Model"].toString().c_str(); + if (val && strlen(val) > 0) + data->camera_model = strdup (val); + } catch (...) { } + + /* EXIF::DateTime */ + try { + const char *val = NULL; + try { + val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str(); + } catch (...) { } + if ((! val) || (strlen(val) == 0)) + try { + val = exifData["Exif.Image.DateTime"].toString().c_str(); + } catch (...) { } + + if (val && strlen(val) > 0) { + static struct tm tt; + static char conv[1024]; + + if (sscanf (val, "%d:%d:%d %d:%d:%d", &tt.tm_year, &tt.tm_mon, &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec) == 6) + { + tt.tm_year -= 1900; + tt.tm_mon--; + if (strftime (&conv[0], sizeof(conv), "%c", &tt)) + data->datetime = strdup (&conv[0]); + } + } + } catch (...) { } + + /* EXIF::Shutter speed */ + try { + float val = exifData["Exif.Photo.ExposureTime"].toFloat(); + if (val > 0) { + if (val < 0.5) + data->exposure = g_strdup_printf ("1/%.0f s", 1/val); + else + data->exposure = g_strdup_printf ("%.1f s", val); + } + } catch (...) { } + + /* EXIF::Flash */ + try { + long int val = exifData["Exif.Photo.Flash"].toLong(); + if ((val > 0) && ((val & 1) == 1)) + data->flash = strdup ((char *) "Flash fired"); + else + data->flash = strdup ((char *) "--"); + } catch (...) { } + + /* EXIF::Focal length */ + try { + float val = exifData["Exif.Photo.FocalLength"].toFloat(); + if (val >= 0) + data->focal_length = g_strdup_printf ("%.0f mm", val); + } catch (...) { } + + /* EXIF::ISO */ + try { + long int val = exifData["Exif.Photo.ISOSpeedRatings"].toLong(); + if (val > 0) + data->iso = g_strdup_printf ("%ld", val); + } catch (...) { } + + /* EXIF::Software */ + try { + data->exif_software = strdup (exifData["Exif.Image.Software"].toString().c_str()); + } catch (...) { } + + /* EXIF::Image description */ + try { + data->exif_imgdesc = strdup (exifData["Exif.Image.ImageDescription"].toString().c_str()); + } catch (...) { } + + /* EXIF::Artist */ + try { + data->exif_artist = strdup (exifData["Exif.Image.Artist"].toString().c_str()); + } catch (...) { } + + /* EXIF::Copyright */ + try { + data->exif_copyright = strdup (exifData["Exif.Image.Copyright"].toString().c_str()); + } catch (...) { } + + /* EXIF::User comment */ + try { + data->exif_usercomment = strdup (exifData["Exif.Photo.UserComment"].toString().c_str()); + } catch (...) { } + } + + Exiv2::IptcData &iptcData = image->iptcData(); + if (! iptcData.empty()) { + /* IPTC::Object name */ + try { + data->iptc_objectname = strdup (iptcData["Iptc.Application2.ObjectName"].toString().c_str()); + } catch (...) { } + + /* IPTC::Copyright */ + try { + data->iptc_copyright = strdup (iptcData["Iptc.Application2.Copyright"].toString().c_str()); + } catch (...) { } + + /* IPTC::Credit */ + try { + data->iptc_credit = strdup (iptcData["Iptc.Application2.Credit"].toString().c_str()); + } catch (...) { } + + /* IPTC::Caption */ + try { + data->iptc_caption = strdup (iptcData["Iptc.Application2.Caption"].toString().c_str()); + } catch (...) { } + + /* IPTC::Author */ + try { + data->iptc_author = strdup (iptcData["Iptc.Application2.Byline"].toString().c_str()); + } catch (...) { } + } + + /* JPEG::Comment */ + try { + data->jpeg_comment = strdup (image->comment().c_str()); + } catch (...) { } + } + catch (Exiv2::AnyError& e) + { + fprintf (stderr, "get_exif: Caught Exiv2 exception: '%s'\n", e.what()); + return -1; + } + +#ifdef __DEBUG_ALL__ + printf("EXIF_TAG_DATE_TIME = '%s'\n", data->datetime); + printf("EXIF_TAG_MODEL = '%s'\n", data->camera_model); + printf("EXIF_TAG_ISO_SPEED_RATINGS = '%s'\n", data->iso); + printf("EXIF_TAG_FOCAL_LENGTH = '%s'\n", data->focal_length); + printf("EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = '%s'\n", data->focal_length_35mm); + printf("EXIF_TAG_FNUMBER = '%s'\n", data->aperture); + printf("EXIF_TAG_EXPOSURE_TIME = '%s'\n", data->exposure); + printf("EXIF_TAG_FLASH = '%s'\n", data->flash); + printf("Exif.Image.Software = '%s'\n", data->exif_software); + printf("Exif.Image.ImageDescription = '%s'\n", data->exif_imgdesc); + printf("Exif.Image.Artist = '%s'\n", data->exif_artist); + printf("Exif.Image.Copyright = '%s'\n", data->exif_copyright); + printf("Exif.Photo.UserComment = '%s'\n", data->exif_usercomment); + printf("Iptc.Application2.ObjectName = '%s'\n", data->iptc_objectname); + printf("Iptc.Application2.Copyright = '%s'\n", data->iptc_copyright); + printf("Iptc.Application2.Credit = '%s'\n", data->iptc_credit); + printf("Iptc.Application2.Caption = '%s'\n", data->iptc_caption); + printf("Iptc.Application2.Byline = '%s'\n", data->iptc_author); + printf("JPEG comment = '%s'\n", data->jpeg_comment); +#endif + + return 0; +} + +/* + * free_exif_struct: free allocated structure + */ +void +free_exif_data (TExifData *data) +{ + if (data) { + if (data->aperture) + free (data->aperture); + if (data->camera_model) + free (data->camera_model); + if (data->datetime) + free (data->datetime); + if (data->exposure) + free (data->exposure); + if (data->flash) + free (data->flash); + if (data->focal_length) + free (data->focal_length); + if (data->focal_length_35mm) + free (data->focal_length_35mm); + if (data->iso) + free (data->iso); + + if (data->exif_software) + free (data->exif_software); + if (data->exif_imgdesc) + free (data->exif_imgdesc); + if (data->exif_artist) + free (data->exif_artist); + if (data->exif_copyright) + free (data->exif_copyright); + if (data->exif_usercomment) + free (data->exif_usercomment); + + if (data->iptc_objectname) + free (data->iptc_objectname); + if (data->iptc_copyright) + free (data->iptc_copyright); + if (data->iptc_credit) + free (data->iptc_credit); + if (data->iptc_caption) + free (data->iptc_caption); + if (data->iptc_author) + free (data->iptc_author); + + if (data->jpeg_comment) + free (data->jpeg_comment); + + free (data); + data = NULL; + } +} + + +/* + * resize_image: resize image pointed by src and save result to dst + */ +gboolean +resize_image (const char *src, const char *dst, + int size_x, int size_y, + int quality, + gboolean thumbnail) +{ + #define ThrowWandException(wand) \ + { \ + char *description; \ + ExceptionType severity; \ + \ + description = MagickGetException (wand, &severity); \ + (void) fprintf (stderr, "Error converting image: %s %s %ld %s\n", GetMagickModule(), description); \ + description = (char*) MagickRelinquishMemory (description); \ + return FALSE; \ + } + + MagickBooleanType status; + MagickWand *magick_wand; + + /* Read an image. */ + MagickWandGenesis(); + magick_wand = NewMagickWand(); + status = MagickReadImage (magick_wand, src); + if (status == MagickFalse) + ThrowWandException (magick_wand); + if (thumbnail) + MagickThumbnailImage (magick_wand, size_x, size_y); + else + MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0); + MagickSetImageCompressionQuality (magick_wand, quality); + + /* Write the image and destroy it. */ + status = MagickWriteImage (magick_wand, dst); + if (status == MagickFalse) + ThrowWandException (magick_wand); + magick_wand = DestroyMagickWand (magick_wand); + MagickWandTerminus(); + + return TRUE; +} + + +/* + * get_image_sizes: retrieve image dimensions + */ +void +get_image_sizes (const char *img, + unsigned long *width, unsigned long *height) +{ + #define xThrowWandException(wand) \ + { \ + char *description; \ + ExceptionType severity; \ + \ + description = MagickGetException (wand, &severity); \ + (void) fprintf (stderr, "Error reading image info: %s %s %ld %s\n", GetMagickModule(), description); \ + description = (char*) MagickRelinquishMemory(description); \ + return; \ + } + + MagickBooleanType status; + MagickWand *magick_wand; + + *width = -1; + *height = -1; + + /* Read an image. */ + MagickWandGenesis(); + magick_wand = NewMagickWand(); + status = MagickPingImage (magick_wand, img); + if (status == MagickFalse) + xThrowWandException (magick_wand); + *width = MagickGetImageWidth (magick_wand); + *height = MagickGetImageHeight (magick_wand); + + magick_wand = DestroyMagickWand (magick_wand); + MagickWandTerminus(); +} + + +/* + * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio + */ +void +calculate_sizes (const unsigned long max_width, const unsigned long max_height, + unsigned long *width, unsigned long *height) +{ + if ((max_width > *width) && (max_height > *height)) + return; + + double max_ratio = (double) max_width / (double) max_height; + double real_ratio = (double) *width / (double) *height; + + if ((*width > *height) && (max_ratio <= real_ratio)) + { + *height = (unsigned long) (max_width / real_ratio); + *width = max_width; + } + else + { + *width = (unsigned long) (max_height * real_ratio); + *height = max_height; + } +} + + +/* + * modify_exif: - strip thumbnail stored in EXIF table + * - add copyright to Exif::Image::Copyright and Iptc::Application2::Copyright + */ +void +modify_exif (const char *filename, gboolean strip_thumbnail, const char *add_copyright) +{ + bool was_modified = false; + + if ((! strip_thumbnail) && (add_copyright == NULL)) + return; + + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename); + g_assert (image.get() != 0); + + image->readMetadata(); + Exiv2::ExifData &exifData = image->exifData(); + if (add_copyright) { + exifData["Exif.Image.Copyright"] = add_copyright; + image->iptcData()["Iptc.Application2.Copyright"] = add_copyright; + was_modified = true; + } + + if (strip_thumbnail && (! exifData.empty())) { +#ifdef HAVE_EXIFTHUMB + Exiv2::ExifThumb exifThumb(image->exifData()); + std::string thumbExt = exifThumb.extension(); +#else + std::string thumbExt = exifData.thumbnailExtension(); +#endif + + if (! thumbExt.empty()) { +#ifdef HAVE_EXIFTHUMB + exifThumb.erase(); +#else + exifData.eraseThumbnail(); +#endif + was_modified = true; + } + } + + if (was_modified) + image->writeMetadata(); + } + catch (Exiv2::AnyError& e) + { + fprintf (stderr, "modify_exif: Caught Exiv2 exception: '%s'\n", e.what()); + } +} diff --git a/src/jpeg-utils.h b/src/jpeg-utils.h new file mode 100644 index 0000000..9b8919f --- /dev/null +++ b/src/jpeg-utils.h @@ -0,0 +1,94 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +#include + + +/* TODO: we want to have numerical values here at some point in the future */ +typedef struct { + char *datetime; + char *camera_model; + char *iso; + char *focal_length; + char *focal_length_35mm; + char *aperture; + char *exposure; + char *flash; + + char *exif_software; + char *exif_imgdesc; + char *exif_artist; + char *exif_copyright; + char *exif_usercomment; + + char *iptc_objectname; + char *iptc_copyright; + char *iptc_credit; + char *iptc_caption; + char *iptc_author; + + char *jpeg_comment; +} TExifData; + + +/* + * get_exif: retrieve EXIF info from a JPEG image + */ +int get_exif (const char *filename, TExifData **exif_data); + +/* + * free_exif_struct: free allocated structure + */ +void free_exif_data (TExifData *data); + + +/* + * resize_image: resize image pointed by src and save result to dst + * - setting thumbnail flag will remove all profiles and optimize for size + */ +gboolean resize_image (const char *src, const char *dst, + int size_x, int size_y, + int quality, + gboolean thumbnail); + +/* + * get_image_sizes: retrieve image dimensions + */ +void get_image_sizes (const char *img, + unsigned long *width, unsigned long *height); + +/* + * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio + */ +void calculate_sizes (const unsigned long max_width, const unsigned long max_height, + unsigned long *width, unsigned long *height); + +/* + * modify_exif: - strip thumbnail stored in EXIF table + * - add copyright to Exif::Image::Copyright and Iptc::Application2::Copyright + */ +void modify_exif (const char *filename, gboolean strip_thumbnail, const char *add_copyright); + + +#ifdef __cplusplus + } +#endif diff --git a/src/setup.c b/src/setup.c new file mode 100644 index 0000000..aafd218 --- /dev/null +++ b/src/setup.c @@ -0,0 +1,268 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "cgg-config.h" +#include "gallery-utils.h" +#include "setup.h" +#include "xml-parser.h" + + + +/* + * find_setup_xml: try to find setup.xml in standard paths + */ +gboolean +find_setup_xml (TGallerySetup *setup) +{ + #define BUFFER_SIZE 65536 + + char *pth; + char *cwd; + gboolean b; + + cwd = malloc (BUFFER_SIZE); + cwd = getcwd (cwd, BUFFER_SIZE); + pth = g_strconcat (cwd, "/", SETUP_XML, NULL); + free (cwd); + + b = parse_setup_xml (pth, setup); + g_free (pth); + if (b) return TRUE; + + pth = g_strconcat (getenv ("HOME"), "/.cgg/", SETUP_XML, NULL); + b = parse_setup_xml (pth, setup); + g_free (pth); + if (b) return TRUE; + + pth = g_strconcat("/usr/share/cgg/", SETUP_XML, NULL); + b = parse_setup_xml (pth, setup); + g_free (pth); + if (b) return TRUE; + + pth = g_strconcat("/usr/local/share/cgg/", SETUP_XML, NULL); + b = parse_setup_xml (pth, setup); + g_free (pth); + return b; +} + + +/* + * parse_setup_xml: XML parser for setup.xml file + */ +gboolean +parse_setup_xml (const char *filename, TGallerySetup *setup) +{ + TXMLFile *xml; + char *s; + + xml = xml_parser_load (filename); + if (xml == NULL) + return FALSE; + + /* initialize data struct */ + if (setup == NULL) + return FALSE; + memset (setup, 0, sizeof (TGallerySetup)); + setup->setup_xml_path = strdup (filename); + + setup->templates_path = xml_file_get_node_value (xml, "/gallery_setup/templates/path/text()"); + setup->template_index = xml_file_get_node_value (xml, "/gallery_setup/templates/index/text()"); + setup->template_album = xml_file_get_node_value (xml, "/gallery_setup/templates/album/text()"); + setup->template_photo = xml_file_get_node_value (xml, "/gallery_setup/templates/photo/text()"); + setup->styles = xml_file_get_node_value (xml, "/gallery_setup/templates/styles/text()"); + setup->scripts = xml_file_get_node_value (xml, "/gallery_setup/templates/scripts/text()"); + setup->thumbnail_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_w", 0); + setup->thumbnail_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_h", 0); + setup->thumbnail_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_w", 0); + setup->thumbnail_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_h", 0); + setup->thumbnail_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "quality", -1); + setup->preview_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_w", 0); + setup->preview_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_h", 0); + setup->preview_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_w", 0); + setup->preview_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_h", 0); + setup->preview_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "quality", -1); + setup->footer = xml_file_get_node_value (xml, "/gallery_setup/footer/text()"); + setup->border_style = xml_file_get_node_attribute (xml, "/gallery_setup/images/border", "style"); + setup->meta_author = xml_file_get_node_value (xml, "/gallery_setup/meta/author/text()"); + setup->meta_description = xml_file_get_node_value (xml, "/gallery_setup/meta/description/text()"); + setup->meta_keywords = xml_file_get_node_value (xml, "/gallery_setup/meta/keywords/text()"); + + s = xml_file_get_node_attribute (xml, "/gallery_setup/images/preload", "value"); + setup->preload = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ + if (s) g_free (s); + s = xml_file_get_node_attribute (xml, "/gallery_setup/images/use_iptc_exif", "value"); + setup->use_iptc_exif = s ? strcasecmp (s, "yes") == 0 : FALSE; /* default to FALSE */ + if (s) g_free (s); + s = xml_file_get_node_attribute (xml, "/gallery_setup/images/erase_embed_thumbnail", "value"); + setup->erase_exif_thumbnail = s ? strcasecmp (s, "yes") == 0 : FALSE; /* default to FALSE */ + if (s) g_free (s); + s = xml_file_get_node_attribute (xml, "/gallery_setup/meta/use_title_as_meta", "value"); + setup->use_title_as_meta = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ + if (s) g_free (s); + + setup->site_title = xml_file_get_node_attribute (xml, "/gallery_setup/meta/site", "title"); + setup->add_copyright = xml_file_get_node_value (xml, "/gallery_setup/meta/add_copyright/text()"); + s = xml_file_get_node_attribute (xml, "/gallery_setup/navigation/use_inpage_links", "value"); + setup->use_inpage_links = s ? strcasecmp (s, "yes") == 0 : TRUE; /* default to TRUE */ + if (s) g_free (s); + + setup->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize"); + + xml_parser_close (xml); + + #ifdef __DEBUG_ALL__ + printf("setup: templates_path = '%s'\n", setup->templates_path); + printf("setup: template_index = '%s'\n", setup->template_index); + printf("setup: template_album = '%s'\n", setup->template_album); + printf("setup: template_photo = '%s'\n", setup->template_photo); + printf("setup: styles = '%s'\n", setup->styles); + printf("setup: scripts = '%s'\n", setup->scripts); + printf("setup: thumbnail_quality = %d\n", setup->thumbnail_quality); + printf("setup: thumbnail_landscape_width = %ld\n", setup->thumbnail_landscape_width); + printf("setup: thumbnail_landscape_height = %ld\n", setup->thumbnail_landscape_height); + printf("setup: thumbnail_portrait_width = %ld\n", setup->thumbnail_portrait_width); + printf("setup: thumbnail_portrait_height = %ld\n", setup->thumbnail_portrait_height); + printf("setup: preview_quality = %d\n", setup->preview_quality); + printf("setup: preview_landscape_width = %ld\n", setup->preview_landscape_width); + printf("setup: preview_landscape_height = %ld\n", setup->preview_landscape_height); + printf("setup: preview_portrait_width = %ld\n", setup->preview_portrait_width); + printf("setup: preview_portrait_height = %ld\n", setup->preview_portrait_height); + printf("setup: footer = '%s'\n", setup->footer); + printf("setup: border_style = '%s'\n", setup->border_style); + printf("setup: meta_author = '%s'\n", setup->meta_author); + printf("setup: meta_description = '%s'\n", setup->meta_description); + printf("setup: meta_keywords = '%s'\n", setup->meta_keywords); + printf("setup: preload = %d\n", setup->preload); + printf("setup: use_iptc_exif = %d\n", setup->use_iptc_exif); + printf("setup: erase_exif_thumbnail = %d\n", setup->erase_exif_thumbnail); + #endif + + return TRUE; +} + + + +int +test_tmpl_access (const char *dir, const char *path) +{ + char *s; + int b; + + s = g_strconcat (dir, "/", path, NULL); + b = access (s, R_OK); + g_free (s); + return b; +} + +int +test_tmpl_files (const char *dir, TGallerySetup *setup) +{ + return test_tmpl_access (dir, setup->template_album) | test_tmpl_access (dir, setup->template_photo) | + test_tmpl_access (dir, setup->template_index) | test_tmpl_access (dir, setup->styles) | + test_tmpl_access (dir, setup->scripts); +} + +/* + * find_templates_directory: absolute/relative path checks, trying to find templates directory + * - returned string should be freed + */ +char * +find_templates_directory (TGallerySetup *setup) +{ + char *base_dir; + char *pth; + + if (IS_DIR_SEP (*setup->templates_path)) + { + #ifdef __DEBUG_ALL__ + printf("Warning: using absolute paths to templates\n"); + #endif + + if (! test_tmpl_files (setup->templates_path, setup)) + return strdup (setup->templates_path); + } + else + { + base_dir = g_path_get_dirname (setup->setup_xml_path); + pth = g_strconcat (base_dir, "/", setup->templates_path, NULL); + g_free (base_dir); + + #ifdef __DEBUG_ALL__ + printf("Warning: using relative paths to templates\n"); + #endif + + if (! test_tmpl_files (pth, setup)) + return pth; + } + + fprintf (stderr, "Couldn't find proper templates directory (tried '%s')\n", setup->templates_path); + return NULL; +} + + +/* + * free_setup_data: free allocated setup data + */ +void +free_setup_data (TGallerySetup *setup) +{ + if (setup) { + if (setup->real_templates_dir) + free (setup->real_templates_dir); + if (setup->setup_xml_path) + free (setup->setup_xml_path); + if (setup->templates_path) + free (setup->templates_path); + if (setup->template_index) + free (setup->template_index); + if (setup->template_album) + free (setup->template_album); + if (setup->template_photo) + free (setup->template_photo); + if (setup->styles) + free (setup->styles); + if (setup->scripts) + free (setup->scripts); + if (setup->footer) + free (setup->footer); + if (setup->meta_author) + free (setup->meta_author); + if (setup->border_style) + free (setup->border_style); + if (setup->site_title) + free (setup->site_title); + if (setup->add_copyright) + free (setup->add_copyright); + free (setup); + setup = NULL; + } +} diff --git a/src/setup.h b/src/setup.h new file mode 100644 index 0000000..eea4b17 --- /dev/null +++ b/src/setup.h @@ -0,0 +1,92 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __SETUP_H__ +#define __SETUP_H__ + + +#include + + +typedef struct { + gboolean verbose; + char *real_templates_dir; + + char *setup_xml_path; + + char *templates_path; + char *template_index; + char *template_album; + char *template_photo; + char *styles; + char *scripts; + + char *footer; + char *meta_author; + char *meta_description; + char *meta_keywords; + gboolean use_title_as_meta; + + int thumbnail_quality; + unsigned long thumbnail_landscape_width; + unsigned long thumbnail_landscape_height; + unsigned long thumbnail_portrait_width; + unsigned long thumbnail_portrait_height; + + int preview_quality; + unsigned long preview_landscape_width; + unsigned long preview_landscape_height; + unsigned long preview_portrait_width; + unsigned long preview_portrait_height; + + char *border_style; + gboolean nofullsize; + + gboolean preload; + gboolean use_iptc_exif; + gboolean erase_exif_thumbnail; + + char *site_title; + char *add_copyright; + gboolean use_inpage_links; +} TGallerySetup; + + + +/* + * find_setup_xml: try to find setup.xml in standard paths + */ +gboolean find_setup_xml (TGallerySetup *setup); + +/* + * parse_setup_xml: XML parser for setup.xml file + */ +gboolean parse_setup_xml (const char *filename, TGallerySetup *setup); + +/* + * free_setup_data: free allocated setup data + */ +void free_setup_data (TGallerySetup *setup); + +/* + * find_templates_directory: absolute/relative path checks, trying to find templates directory + * - returned string should be freed + */ +char *find_templates_directory (TGallerySetup *setup); + + +#endif /* __SETUP_H__ */ diff --git a/src/xml-parser.c b/src/xml-parser.c new file mode 100644 index 0000000..eb6c86f --- /dev/null +++ b/src/xml-parser.c @@ -0,0 +1,261 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "xml-parser.h" + + + +/* + * xml_parser_load: initialize and load the XML document + */ +TXMLFile * +xml_parser_load (const char *filename) +{ + TXMLFile *file; + + file = malloc (sizeof (TXMLFile)); + memset (file, 0, sizeof (TXMLFile)); + + /* Load XML document */ + file->doc = xmlParseFile (filename); + if (file->doc == NULL) { + fprintf (stderr, "Error: unable to parse file \"%s\"\n", filename); + free (file); + return NULL; + } + + /* Create xpath evaluation context */ + file->xpathCtx = xmlXPathNewContext (file->doc); + if (file->xpathCtx == NULL) { + fprintf (stderr, "Error: unable to create new XPath context\n"); + xmlFreeDoc (file->doc); + free (file); + return FALSE; + } + + return file; +} + + +/* + * xml_parser_close: close the XML document parser + */ +void +xml_parser_close (TXMLFile *file) +{ + if (file) + { + xmlXPathFreeContext (file->xpathCtx); + xmlFreeDoc (file->doc); + free (file); + file = NULL; + } +} + +/* + * xml_file_get_node_name: retrieve name of the XPath node + */ +char * +xml_file_get_node_name (TXMLFile *file, const char *x_path) +{ + xmlXPathObjectPtr xpathObj; + xmlNodePtr cur; + char *attrv; + + if ((! file) || (! x_path)) + return NULL; + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); + if (xpathObj == NULL) { + fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); + return NULL; + } + + attrv = NULL; + if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { + cur = xpathObj->nodesetval->nodeTab[0]; + if (cur->name) + attrv = strdup ((const char *) cur->name); + } + + xmlXPathFreeObject (xpathObj); + return attrv; +} + + +/* + * xml_file_get_node_value: retrieve string value from XPath node + * - multiple matched nodes will be concatenated into one string + * - otherwise please use [0], [1] etc. quantificators + */ +char * +xml_file_get_node_value (TXMLFile *file, const char *x_path) +{ + xmlXPathObjectPtr xpathObj; + xmlNodePtr cur; + char *val, *valx; + int i; + + if ((! file) || (! x_path)) + return NULL; + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); + if (xpathObj == NULL) { + fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); + return NULL; + } + + val = NULL; + if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { + #ifdef __DEBUG_ALL__ + printf("Result (%d nodes):\n", xpathObj->nodesetval->nodeNr); + #endif + + for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) + { + cur = xpathObj->nodesetval->nodeTab[i]; + #ifdef __DEBUG_ALL__ + printf(" XPATH matched: element node \"%s[%d]\", value = '%s'\n", cur->name, i, cur->content); + #endif + + if (cur->content) + { + if (val == NULL) + { + val = g_strdup ((char *) cur->content); + } + else + { + valx = g_strconcat (val, (char *) cur->content, NULL); + g_free (val); + val = valx; + } + } + } + } + + xmlXPathFreeObject (xpathObj); + return val; +} + + +/* + * xml_file_get_node_attribute: retrieve attribute value from XPath node + */ +char * +xml_file_get_node_attribute (TXMLFile *file, const char *x_path, const char *attr) +{ + xmlXPathObjectPtr xpathObj; + xmlNodePtr cur; + xmlChar *attrvx; + char *attrv; + + if ((! file) || (! x_path)) + return NULL; + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); + if (xpathObj == NULL) { + fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); + return NULL; + } + + attrv = NULL; + if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { + cur = xpathObj->nodesetval->nodeTab[0]; + attrvx = xmlGetProp (cur, (const xmlChar *) attr); + if (attrvx) { + attrv = strdup ((char*) attrvx); + xmlFree (attrvx); + } + + #ifdef __DEBUG_ALL__ + printf("Result (%d nodes):\n", xpathObj->nodesetval->nodeNr); + printf(" XPATH matched: element node \"%s\", value = '%s', property value = '%s'\n", cur->name, cur->content, attrv); + #endif + } + + xmlXPathFreeObject (xpathObj); + return attrv; +} + +long +xml_file_get_node_attribute_long (TXMLFile *file, const char *x_path, const char *attr, const int _default) +{ + char *s; + long int i; + + s = xml_file_get_node_attribute (file, x_path, attr); + if (s == NULL) + return _default; + + i = atol (s); + free (s); + return i; +} + +/* + * xml_file_get_node_present: existency test of the XPath node + */ +gboolean +xml_file_get_node_present (TXMLFile *file, const char *x_path) +{ + return xml_file_node_get_children_count (file, x_path) > 0; +} + + +/* + * xml_file_node_get_children_count: retrieve number of children items of the specified XPath node + */ +int +xml_file_node_get_children_count (TXMLFile *file, const char *x_path) +{ + xmlXPathObjectPtr xpathObj; + int count; + + if ((! file) || (! x_path)) + return 0; + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); + if (xpathObj == NULL) { + fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); + return 0; + } + + count = 0; + if (xpathObj->nodesetval) + count = xpathObj->nodesetval->nodeNr; + + xmlXPathFreeObject (xpathObj); + return count; +} diff --git a/src/xml-parser.h b/src/xml-parser.h new file mode 100644 index 0000000..02be628 --- /dev/null +++ b/src/xml-parser.h @@ -0,0 +1,67 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2008 Tomas Bzatek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#include +#include + + +typedef struct { + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; +} TXMLFile; + + + +/* + * xml_parser_load: initialize and load the XML document + */ +TXMLFile * xml_parser_load (const char *filename); + +/* + * xml_parser_close: close the XML document parser + */ +void xml_parser_close (TXMLFile *file); + +/* + * xml_file_get_node_name: retrieve name of the XPath node + */ +char * xml_file_get_node_name (TXMLFile *file, const char *x_path); + +/* + * xml_file_get_node_value: retrieve string value from XPath node + * - multiple matched nodes will be concatenated into one string + * - otherwise please use [0], [1] etc. quantificators + */ +char * xml_file_get_node_value (TXMLFile *file, const char *x_path); + +/* + * xml_file_get_node_attribute: retrieve attribute value from XPath node + */ +char * xml_file_get_node_attribute (TXMLFile *file, const char *x_path, const char *attr); +long xml_file_get_node_attribute_long (TXMLFile *file, const char *x_path, const char *attr, const int _default); + +/* + * xml_file_get_node_present: existency test of the XPath node + */ +gboolean xml_file_get_node_present (TXMLFile *file, const char *x_path); + +/* + * xml_file_node_get_children_count: retrieve number of children items of the specified XPath node + */ +int xml_file_node_get_children_count (TXMLFile *file, const char *x_path); diff --git a/xml-parser.c b/xml-parser.c deleted file mode 100644 index eb6c86f..0000000 --- a/xml-parser.c +++ /dev/null @@ -1,261 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "xml-parser.h" - - - -/* - * xml_parser_load: initialize and load the XML document - */ -TXMLFile * -xml_parser_load (const char *filename) -{ - TXMLFile *file; - - file = malloc (sizeof (TXMLFile)); - memset (file, 0, sizeof (TXMLFile)); - - /* Load XML document */ - file->doc = xmlParseFile (filename); - if (file->doc == NULL) { - fprintf (stderr, "Error: unable to parse file \"%s\"\n", filename); - free (file); - return NULL; - } - - /* Create xpath evaluation context */ - file->xpathCtx = xmlXPathNewContext (file->doc); - if (file->xpathCtx == NULL) { - fprintf (stderr, "Error: unable to create new XPath context\n"); - xmlFreeDoc (file->doc); - free (file); - return FALSE; - } - - return file; -} - - -/* - * xml_parser_close: close the XML document parser - */ -void -xml_parser_close (TXMLFile *file) -{ - if (file) - { - xmlXPathFreeContext (file->xpathCtx); - xmlFreeDoc (file->doc); - free (file); - file = NULL; - } -} - -/* - * xml_file_get_node_name: retrieve name of the XPath node - */ -char * -xml_file_get_node_name (TXMLFile *file, const char *x_path) -{ - xmlXPathObjectPtr xpathObj; - xmlNodePtr cur; - char *attrv; - - if ((! file) || (! x_path)) - return NULL; - - /* Evaluate xpath expression */ - xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); - if (xpathObj == NULL) { - fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); - return NULL; - } - - attrv = NULL; - if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { - cur = xpathObj->nodesetval->nodeTab[0]; - if (cur->name) - attrv = strdup ((const char *) cur->name); - } - - xmlXPathFreeObject (xpathObj); - return attrv; -} - - -/* - * xml_file_get_node_value: retrieve string value from XPath node - * - multiple matched nodes will be concatenated into one string - * - otherwise please use [0], [1] etc. quantificators - */ -char * -xml_file_get_node_value (TXMLFile *file, const char *x_path) -{ - xmlXPathObjectPtr xpathObj; - xmlNodePtr cur; - char *val, *valx; - int i; - - if ((! file) || (! x_path)) - return NULL; - - /* Evaluate xpath expression */ - xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); - if (xpathObj == NULL) { - fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); - return NULL; - } - - val = NULL; - if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { - #ifdef __DEBUG_ALL__ - printf("Result (%d nodes):\n", xpathObj->nodesetval->nodeNr); - #endif - - for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) - { - cur = xpathObj->nodesetval->nodeTab[i]; - #ifdef __DEBUG_ALL__ - printf(" XPATH matched: element node \"%s[%d]\", value = '%s'\n", cur->name, i, cur->content); - #endif - - if (cur->content) - { - if (val == NULL) - { - val = g_strdup ((char *) cur->content); - } - else - { - valx = g_strconcat (val, (char *) cur->content, NULL); - g_free (val); - val = valx; - } - } - } - } - - xmlXPathFreeObject (xpathObj); - return val; -} - - -/* - * xml_file_get_node_attribute: retrieve attribute value from XPath node - */ -char * -xml_file_get_node_attribute (TXMLFile *file, const char *x_path, const char *attr) -{ - xmlXPathObjectPtr xpathObj; - xmlNodePtr cur; - xmlChar *attrvx; - char *attrv; - - if ((! file) || (! x_path)) - return NULL; - - /* Evaluate xpath expression */ - xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); - if (xpathObj == NULL) { - fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); - return NULL; - } - - attrv = NULL; - if ((xpathObj->nodesetval) && (xpathObj->nodesetval->nodeNr > 0)) { - cur = xpathObj->nodesetval->nodeTab[0]; - attrvx = xmlGetProp (cur, (const xmlChar *) attr); - if (attrvx) { - attrv = strdup ((char*) attrvx); - xmlFree (attrvx); - } - - #ifdef __DEBUG_ALL__ - printf("Result (%d nodes):\n", xpathObj->nodesetval->nodeNr); - printf(" XPATH matched: element node \"%s\", value = '%s', property value = '%s'\n", cur->name, cur->content, attrv); - #endif - } - - xmlXPathFreeObject (xpathObj); - return attrv; -} - -long -xml_file_get_node_attribute_long (TXMLFile *file, const char *x_path, const char *attr, const int _default) -{ - char *s; - long int i; - - s = xml_file_get_node_attribute (file, x_path, attr); - if (s == NULL) - return _default; - - i = atol (s); - free (s); - return i; -} - -/* - * xml_file_get_node_present: existency test of the XPath node - */ -gboolean -xml_file_get_node_present (TXMLFile *file, const char *x_path) -{ - return xml_file_node_get_children_count (file, x_path) > 0; -} - - -/* - * xml_file_node_get_children_count: retrieve number of children items of the specified XPath node - */ -int -xml_file_node_get_children_count (TXMLFile *file, const char *x_path) -{ - xmlXPathObjectPtr xpathObj; - int count; - - if ((! file) || (! x_path)) - return 0; - - /* Evaluate xpath expression */ - xpathObj = xmlXPathEvalExpression ((const xmlChar *) x_path, file->xpathCtx); - if (xpathObj == NULL) { - fprintf (stderr, "Error: unable to evaluate xpath expression \"%s\"\n", x_path); - return 0; - } - - count = 0; - if (xpathObj->nodesetval) - count = xpathObj->nodesetval->nodeNr; - - xmlXPathFreeObject (xpathObj); - return count; -} diff --git a/xml-parser.h b/xml-parser.h deleted file mode 100644 index 02be628..0000000 --- a/xml-parser.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Cataract - Static web photo gallery generator - * Copyright (C) 2008 Tomas Bzatek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include - -#include -#include - - -typedef struct { - xmlDocPtr doc; - xmlXPathContextPtr xpathCtx; -} TXMLFile; - - - -/* - * xml_parser_load: initialize and load the XML document - */ -TXMLFile * xml_parser_load (const char *filename); - -/* - * xml_parser_close: close the XML document parser - */ -void xml_parser_close (TXMLFile *file); - -/* - * xml_file_get_node_name: retrieve name of the XPath node - */ -char * xml_file_get_node_name (TXMLFile *file, const char *x_path); - -/* - * xml_file_get_node_value: retrieve string value from XPath node - * - multiple matched nodes will be concatenated into one string - * - otherwise please use [0], [1] etc. quantificators - */ -char * xml_file_get_node_value (TXMLFile *file, const char *x_path); - -/* - * xml_file_get_node_attribute: retrieve attribute value from XPath node - */ -char * xml_file_get_node_attribute (TXMLFile *file, const char *x_path, const char *attr); -long xml_file_get_node_attribute_long (TXMLFile *file, const char *x_path, const char *attr, const int _default); - -/* - * xml_file_get_node_present: existency test of the XPath node - */ -gboolean xml_file_get_node_present (TXMLFile *file, const char *x_path); - -/* - * xml_file_node_get_children_count: retrieve number of children items of the specified XPath node - */ -int xml_file_node_get_children_count (TXMLFile *file, const char *x_path); -- cgit v1.2.3