Logo Search packages:      
Sourcecode: kazehakase version File versions

utils.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003-2004 Hiroyuki Ikezoe
 *
 *  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, or (at your option)
 *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "utils.h"
#include "glib-utils.h"
#include "gtk-utils.h"
#include "config.h"
#include "kazehakase.h"
#include "egg-pixbuf-thumbnail.h"

#define BUFFER_SIZE 1024

void make_dir (const gchar *dirname)
{
      gint  i = 0, ii = 0, ret;
      gchar *temp, *temp2;

      temp = g_build_filename(g_get_home_dir(), "."PACKAGE, dirname, NULL);
      temp2 = g_alloca(strlen(temp) + 1);

      while (temp[i])
      {
            temp2[ii++] = temp[i];
            temp2[ii] = '\0';
            if ((temp[i + 1] == '/' || !temp[i + 1]) &&
                !g_file_test(temp2, G_FILE_TEST_IS_DIR))
            {
                  ret = mkdir(temp2, 0711);

#if 0 /* show dialog? */
                  if (ret != 0)
                  {
                        perror("Faild to create directory");;
                  }
#endif
            }
            i++;
      }

      g_free(temp);     
}


void make_thumbnails_dir (void)
{
      gchar *temp;
      temp = g_strdup_printf("%s/.thumbnails", g_get_home_dir());
      if (!g_file_test(temp, G_FILE_TEST_IS_DIR))
      {
            mkdir(temp, 0711);
      }
      g_free(temp);     
      
      temp = g_strdup_printf("%s/.thumbnails/large", g_get_home_dir());
      if (!g_file_test(temp, G_FILE_TEST_IS_DIR))
      {
            mkdir(temp, 0711);
      }
      g_free(temp);     
}


gboolean
key_seems_sequential (const gchar *key, const gchar *prefix)
{
      gint len = strlen(prefix);
      const gchar *tail = key + len;
      gint i;
      gboolean valid;

      g_return_val_if_fail(key && *key, FALSE);
      g_return_val_if_fail(prefix && *prefix, FALSE);

      len = strlen(prefix);
      tail = key + len;

      if (strncmp(key, prefix, len)) return FALSE;

      len = strlen(tail);
      if (len <= 0) return FALSE;

      valid = TRUE;
      for (i = 0; i < len; i++)
      {
            if (!isdigit(tail[i]))
            {
                  valid = FALSE;
                  break;
            }
      }

      return valid;
}


gchar *
remove_tag (const gchar *string, gsize len)
{
      GString *work_string;
      gchar *begin_pos;
      guint i = 0;
      
      work_string = g_string_new(NULL);
      begin_pos = strstr(string, "<");
      while (string[i] != '\0' && i < len)
      {
            if (string[i] == '<')
            {
                  while (string[i] != '>' && string[i] != '\0' && i < len)
                  {
                        i++;
                  }
            }
            else
                  g_string_append_c(work_string, string[i]);
            i++;
      }
      
      return g_string_free(work_string, FALSE);
}


gchar *
create_filename_from_uri (const gchar *uri)
{
      gchar *filename;
      gint len, i = 0;
      
      filename = g_strdup(uri);
      len = strlen(filename);

      while (filename[i] != '\0' && i < len)
      {
            if (filename[i] == '/')
                  filename[i] = '_';
            i++;
      }

      return filename;
}


gchar *
create_filename_with_path_from_uri (const gchar *uri)
{
      gchar *filename;
      gchar *pos;
      gchar *scheme;
      
      pos = strstr(uri, "://");
      
      if (!pos)
      {
            pos = (gchar*)uri;
            scheme = g_strdup("");
      }
      else
      {
            scheme = g_strndup(uri, pos - uri);
            pos += 3;
      }

      if (g_str_has_suffix(uri, "/"))
      {
            filename = g_strconcat(scheme, "/", pos, "_", NULL);
      }
      else
      {
            gchar *pos2 = strchr(uri, '?');
            if (pos2)
            {
                  gchar *string = g_strndup(pos, pos2 - pos);
                  filename = g_strconcat(scheme,
                                     "/",
                                     string, 
                                     "_/",
                                     pos2 + 1,
                                     NULL);
                  g_free(string);
            }
            else
            {
                  filename = g_strconcat(scheme,
                                    "/",
                                    pos,
                                    NULL);
            }
      }

      g_free(scheme);
      
      return filename;
}


gchar *
create_uri_from_filename (const gchar *filename)
{
      gchar *uri;
      gchar *pos;
      gchar *scheme;
      gchar *path;
      
      pos = strstr(filename, "/");
      
      if (!pos)
            return NULL;

      scheme = g_strndup(filename, pos - filename);

      if (g_str_has_suffix(filename, "/_"))
      {
            path = g_strndup(pos + 1, strlen(pos) - 2); 
      }
      else
      {
            gchar *pos2 = g_strrstr(filename, "_/");
            if (pos2)
            {
                  gchar *string = g_strndup(pos + 1, pos2 - pos - 1);
                  path = g_strconcat(string, 
                                 "?",
                                 pos2 + 2,
                                 NULL);
                  
                  g_free(string);
            }
            else
            {
                  path = g_strdup(pos + 1);
            }
      }

      if (!strcmp(scheme, "file"))
      {
            uri = g_strconcat(scheme, ":///", path, NULL);
      }
      else
      {
            uri = g_strconcat(scheme, "://", path, NULL);
      }
      
      g_free(scheme);
      g_free(path);

      return uri;
}


gchar *
url_decode(const gchar *src)
{
      GString *dest;
      gint len, i=0;

      if (!src) return NULL;
      len = strlen(src);
      dest = g_string_sized_new(len);

      while (src[i] != '\0' && i < len)
      {
            if (src[i] == '%')
            {
                  if (i + 2 <= len &&
                      g_ascii_isxdigit(src[i+1]) && 
                      g_ascii_isxdigit(src[i+2]))
                  {                       
                        g_string_append_c(dest,
                                      g_ascii_xdigit_value(src[i+1]) * 16 + 
                                      g_ascii_xdigit_value(src[i+2]));
                        i+=2;
                  }
            }
            else
            {
                  g_string_append_c(dest, src[i]);
            }
            i++;
      }

      /* Free gstring and reserve its data.*/
      return g_string_free(dest, FALSE);
}


gchar *
create_profile_key_from_uri (const gchar *string)
{
      gchar *key, *pos;
      gint len, i = 0;
      
      if (!string)
            return NULL;
      pos = strchr(string, '?');
      len = strlen(string);
      if (pos)
            len = pos - string;
      key = g_strndup(string, len);

      while (key[i] != '\0' && i < len)
      {
            if (key[i] == '=')
                  key[i] = '_';
            i++;
      }

      return key;
}

/* return hex-encoded UTF-8 data
 * please free returned gchar* if unnecessary
 */
gchar *
url_encode(const gchar* utf8src)
{
      GString *dest;
      const gchar *ch = utf8src;
      unsigned char buf;

      if (!utf8src) return "";

      dest = g_string_sized_new(strlen(utf8src));

      while(*ch != '\0')
      {
            if (((*ch >= 'A') && (*ch <= 'Z')) ||
                ((*ch >= 'a') && (*ch <= 'z')) ||
                ((*ch >= '0') && (*ch <= '9')))
            {
                  g_string_append_c(dest, *ch);
            }
            else if (*ch == ' ')
            {
                  g_string_append_c(dest, '+');

            }
            else
            {
                  g_string_append_c(dest, '%');
                  buf = (*ch >> 4) & 0x0f;
                  g_string_append_c(dest,
                              ( (buf < 10) ? buf + '0' : buf + ('A' - 10)) );
                  buf = *ch & 0x0f;
                  g_string_append_c(dest,
                              ( (buf < 10) ? buf + '0' : buf + ('A' - 10)) );
            }
            ch++;
      }
      
      /* Free gstring and reserve its data.*/
      return g_string_free(dest, FALSE);
}


gchar *
complement_scheme (const gchar* url)
{
      gchar *file;

      if (g_file_test(url, G_FILE_TEST_EXISTS))
      {
            if (!g_path_is_absolute(url))
            {
                  gchar *current= g_get_current_dir();
                  file = g_strdup_printf("file://%s/%s",
                                     current,
                                     url);
                  g_free(current);
            }
            else
            {
                  file = g_strdup_printf("file://%s",
                                     url);
            }
            return file;
      }
      else
            return g_strdup(url);
}

gchar *
xml_get_content (const gchar *buffer)
{
      gchar *pos1, *pos2, *pos3;
      gchar *name;
      gchar *content = NULL;
      
      pos1 = strchr(buffer, '>');
      pos3 = strchr(buffer, ' ');
      if (pos1)
      {
            gchar *string;
            guint len;
            if (pos3 && pos1 > pos3)
                  len = pos3 - buffer - 1;
            else
                  len = pos1 - buffer - 1;
            name = g_strndup(buffer + 1, len); 
            string = g_strconcat("</", name, NULL);
            pos2 = strstr(pos1, string);
            if (pos2)
                  content = g_strndup(pos1 +1 , pos2 - pos1 - 1);
            g_free(string);
            g_free(name);
      }
      return content;
}

gchar *
xml_get_attr (const gchar *buffer, const gchar *attr_name)
{
      gchar *pos1, *pos2;
      gchar *string1, *string2;
      gchar *attr = NULL;
      guint len;

      pos1 = strchr(buffer, '>');
      if (pos1)
            string1 = g_strndup(buffer, pos1 - buffer);
      else 
            return NULL;
      
      string2 = g_strdup_printf("%s=\"", attr_name);
      len = strlen(string2);
      pos1 = strstr(string1, string2); 
      if (pos1)
      {
            pos2 = strchr(pos1 + len, '"'); 
            if (pos2)
                  attr = g_strndup(pos1 + len, pos2 - pos1 -len); 
      }
      g_free(string1);
      g_free(string2);
      
      return attr;

}


GSList *
purge_history_file(const gchar *path, time_t limit_seconds)
{
      GDir *gdir;
      const gchar *dir;
      GSList *purge_files = NULL;

      gdir = g_dir_open(path, 0, NULL);

      if (!gdir) return NULL;

      while((dir = g_dir_read_name(gdir)))
      {
            gchar *dirname;
            dirname = g_strconcat(path, dir, NULL);
            if (g_file_test(dirname, G_FILE_TEST_IS_DIR))
            {
                  GSList *files_in_dir;
                  files_in_dir = purge_history_file(dirname,
                                            limit_seconds);
                  purge_files = g_slist_concat(purge_files,
                                         files_in_dir);
            }
            else
            {
                  struct stat st;
                  time_t t;
                  GTimeVal now;
      
                  g_get_current_time(&now);
                  t = (time_t)now.tv_sec;
            
                  if (stat(dirname, &st) == 0)
                  {
                        if (st.st_mtime < t - limit_seconds)
                        {
                              unlink(dirname);
                              g_slist_prepend(purge_files,
                                          g_strdup(dirname));
                        }
                  }
            }
            g_free(dirname);
      }
      g_dir_close(gdir);

      return purge_files;
}

gchar *
ensure_encode_string(const gchar *text, 
                 const gchar *encode,
                 gboolean urlencode)
{
      GError *e = NULL;
      gchar *encode_string = NULL, *url_string = NULL;

      if (!text) 
      {
            encode_string = g_strdup("");
            return encode_string;
      }

      if (encode)
      {
            encode_string = 
                  g_convert(text,
                          strlen(text),
                          encode, "UTF-8",
                          NULL, NULL,
                          &e);
      }

      if (e || !encode)
      {
            encode_string =
                g_strdup(text);
            if (e)
                  g_error_free(e);
      }

      if (urlencode)    
      {
            url_string = url_encode(encode_string);
      }
      else
      {
            url_string = g_strdup(encode_string);
      }

      g_free(encode_string);
      
      return url_string;
}

GTime 
thumbnail_get_last_modified (const gchar *uri)
{
      gchar *thumb_filename;
      struct stat st;
      int ret;
      
      thumb_filename = egg_pixbuf_get_thumb_filename(uri,
                                           EGG_PIXBUF_THUMB_LARGE);
      
      ret = stat(thumb_filename, &st);
      g_free(thumb_filename);

      if (ret == 0)
            return st.st_mtime;
      else
            return 0;
}

GTime 
history_get_last_modified (const gchar *uri)
{
      gchar *history_filename, *filename;
      struct stat st;
      int ret;
      
      filename = create_filename_with_path_from_uri(uri);
      history_filename = g_strconcat(g_get_home_dir(),
                               HISTORY_DIR,
                               filename,
                               NULL);
      
      ret = stat(history_filename, &st);
      g_free(history_filename);
      g_free(filename);

      if (ret == 0)
            return st.st_mtime;
      else
            return 0;
}

typedef struct _KzPixbufConverter
{
      GdkPixbufLoader *loader;
      gchar *filename;
} KzPixbufConverter;


static gboolean
idle_dispose_converter(gpointer data)
{
      KzPixbufConverter *converter = data;

      g_free(converter->filename);
      g_free(converter);

      return FALSE;
}

static gboolean
cb_io_in(GIOChannel *iochannel, GIOCondition condition,
       gpointer data)
{
      GIOStatus iostatus;
      gsize bytes_read;
      gchar buffer[BUFFER_SIZE];
      KzPixbufConverter *converter = data;
      
      if (condition & G_IO_ERR)
      {
            g_idle_add(idle_dispose_converter, converter);
            return FALSE;
      }

      /* Read the data into our buffer */
      iostatus = g_io_channel_read_chars(iochannel, buffer, 
                                 sizeof(buffer),
                                 &bytes_read,
                                 NULL);

      if (bytes_read)
      {
            gdk_pixbuf_loader_write(converter->loader,
                              (const guchar*)buffer, bytes_read,
                              NULL);
      }

      switch (iostatus)
      {
       case G_IO_STATUS_EOF:
       {    
            GdkPixbuf *pixbuf;
            pixbuf = gdk_pixbuf_loader_get_pixbuf(converter->loader);
            if (pixbuf)
            {
                  GdkPixbuf *rotate, *scale;
            
                  /* scale */
                  scale = gdk_pixbuf_scale_simple(pixbuf, 
                                            200, 256,
                                            GDK_INTERP_HYPER);
            
                  /* rotate image */
                  rotate = gdk_pixbuf_rotate_simple(scale,
                                            GDK_PIXBUF_ROTATE_CLOCKWISE);
                  g_object_unref(scale);
                  /* save image */
                  if (rotate)
                  {
                        gchar *png_file;
                        png_file = g_strndup(converter->filename,
                                         strlen(converter->filename) - 3);
                        gdk_pixbuf_save(rotate, 
                                    png_file, "png", NULL, NULL);
                        g_object_unref(rotate);
                        g_free(png_file);
                  }
            }
            gdk_pixbuf_loader_close(converter->loader, NULL);     
            unlink(converter->filename);
            g_idle_add(idle_dispose_converter, converter);
            
            return FALSE;
       }
       case G_IO_STATUS_NORMAL:
            return TRUE;
       default:
            g_idle_add(idle_dispose_converter, converter);
            return FALSE;
      }
}


void
convert_image (const gchar *ps_file, const gchar *png_file)
{
      const gchar *gs = "gs -q -dNOPAUSE -dBATCH -r24 -sDEVICE=ppmraw -sOutputFile=-  %s";
      gchar *command;
      gint argc, out;
      gchar **argv = NULL;
      GSpawnFlags flags;
      GPid pid;
      GIOChannel *io;
      GdkPixbufLoader *loader;
      KzPixbufConverter *converter;

      command = g_strdup_printf(gs, ps_file);   

      g_shell_parse_argv(command,
                     &argc,
                     &argv,
                     NULL);

      flags = G_SPAWN_SEARCH_PATH;
      g_spawn_async_with_pipes(NULL,
                               argv,
                         NULL,
                         flags,
                               NULL,
                               NULL,
                               &pid,
                         NULL,
                         &out,
                         NULL,
                               NULL);
      g_strfreev(argv);
      g_free(command);

      io = g_io_channel_unix_new(out);
      g_io_channel_set_encoding(io, NULL, NULL);

      loader = gdk_pixbuf_loader_new_with_type("pnm", NULL);
      converter = g_new0(KzPixbufConverter, 1);
      converter->loader = loader;
      converter->filename = g_strdup(ps_file);
      
      g_io_add_watch(io,
                   G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
                   cb_io_in, converter);
}

gboolean
str_isdigit (const gchar *str)
{
      int i;
      size_t len;
      gboolean is_digit = TRUE;

      if (!str) return FALSE;

      len = strlen(str);
      for (i = 0; i < len; i++)
      {
            if (!isdigit(str[i]))
            {
                  is_digit = FALSE;
                  break;
            }
      }
      return is_digit;
}

/* the following tow functions are picked from utils/gul-general.c in galeon-1.3.18 */
static void
find_file_recursive (const gchar *path,
                 const gchar *fname,
                 GSList **l,
                 gint depth,
                 gint maxdepth)
{
      GDir *d = g_dir_open (path, 0, NULL);
      const gchar *f;
      if (d)
      {
            while ((f = g_dir_read_name (d)))
            {
                  gchar *new_path = g_build_filename (path, f, NULL);
                  if (depth < maxdepth)
                  {
                        find_file_recursive (new_path, fname, l,
                                           depth + 1, maxdepth);
                  }
                  if (!strcmp (f, fname))
                  {
                        *l = g_slist_prepend (*l, new_path);
                  }
                  else
                  {
                        g_free (new_path);
                  }
            }
            g_dir_close (d);
      }
}

/*
 * Looks for a file in a directory, recursively.
 */
GSList *
find_file (const gchar *path, 
         const gchar *fname,
         gint maxdepth)
{
      GSList *ret = NULL;
      find_file_recursive (path, fname, &ret, 0, maxdepth);
      return ret;
}

Generated by  Doxygen 1.6.0   Back to index