/* 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; size_t written; 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); written = fwrite (buffer, 1, size_r, fout); if (written < size_r) { fprintf (stderr, "copy_file: error writing to file \"%s\": %s\n", dst, strerror (errno)); break; } } 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, int count) { int i; char *s; if (count < 0) count = 0; 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; } /* * count_dir_levels: returns number of path elements */ int count_dir_levels (const char *path) { int i; int level; if (path == NULL || strlen (path) == 0) return 0; level = 1; for (i = strlen (path) - 1; i > 0; i--) { if (G_IS_DIR_SEPARATOR (*(path + i)) && i > 0 && i < strlen (path)) level++; } return level; } /* * extract_file_ext: returns pointer to filename extension */ const char * extract_file_ext (const char *filename) { g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (strlen (filename) > 0, NULL); return strrchr (filename, '.') + 1; }