From e9e9684117719204929821028ba9dbb7915ea119 Mon Sep 17 00:00:00 2001 From: kraxel Date: Sun, 28 Mar 2004 11:31:57 +0000 Subject: Initial revision --- desktop.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 desktop.c (limited to 'desktop.c') diff --git a/desktop.c b/desktop.c new file mode 100644 index 0000000..d30d3c7 --- /dev/null +++ b/desktop.c @@ -0,0 +1,276 @@ +/* + * some code to handle desktop files + * http://www.freedesktop.org/Standards/desktop-entry-spec + * + * This is really very simple and basic: next to no locale handling, + * no caching, no other clever tricks ... + * ida + fbi only use the Comment= entry of .directory files. + * + * (c) 2004 Gerd Knorr + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "list.h" +#include "desktop.h" + +extern int debug; + +/* ------------------------------------------------------------------------- */ +/* desktop files are in utf-8 */ + +static int iconv_string(char *to, char *from, + char *src, char *dst, size_t max) +{ + size_t ilen = strlen(src); + size_t olen = max-1; + iconv_t ic; + + ic = iconv_open(to,from); + if (NULL == ic) + return 0; + + while (ilen > 0) { + if (-1 == iconv(ic,&src,&ilen,&dst,&olen)) { + /* skip + quote broken byte unless we are out of space */ + if (E2BIG == errno) + break; + if (olen < 4) + break; + sprintf(dst,"\\x%02x",(int)(unsigned char)src[0]); + src += 1; + dst += 4; + ilen -= 1; + olen -= 4; + } + } + dst[0] = 0; + iconv_close(ic); + return max-1 - olen; +} + +int utf8_to_locale(char *src, char *dst, size_t max) +{ + char *codeset = nl_langinfo(CODESET); + return iconv_string(codeset, "UTF-8", src, dst, max); +} + +int locale_to_utf8(char *src, char *dst, size_t max) +{ + char *codeset = nl_langinfo(CODESET); + return iconv_string("UTF-8", codeset, src, dst, max); +} + +/* ------------------------------------------------------------------------- */ +/* read/write desktop files */ + +struct desktop_line { + struct list_head next; + char line[1024]; +}; + +static int read_file(char *filename, struct list_head *file) +{ + struct desktop_line *l; + int len,count = 0; + FILE *fp; + + INIT_LIST_HEAD(file); + fp = fopen(filename,"r"); + if (NULL == fp) { + if (debug) + fprintf(stderr,"open %s: %s\n",filename,strerror(errno)); + return 0; + } + for (;;) { + l = malloc(sizeof(*l)); + memset(l,0,sizeof(*l)); + if (NULL == fgets(l->line,sizeof(l->line),fp)) { + free(l); + break; + } + len = strlen(l->line); + if (l->line[len-1] == '\n') + l->line[len-1] = 0; + list_add_tail(&l->next,file); + count++; + } + fclose(fp); + return count; +} + +static int write_file(char *filename, struct list_head *file) +{ + struct desktop_line *l; + struct list_head *item; + FILE *fp; + + fp = fopen(filename,"w"); + if (NULL == fp) { + fprintf(stderr,"open %s: %s\n",filename,strerror(errno)); + return 0; + } + list_for_each(item,file) { + l = list_entry(item, struct desktop_line, next); + fprintf(fp,"%s\n",l->line); + } + fclose(fp); + return 0; +} + +static int dump_file(struct list_head *file) +{ + struct desktop_line *l; + struct list_head *item; + + fprintf(stderr,"\n"); + fprintf(stderr,"+--------------------\n"); + list_for_each(item,file) { + l = list_entry(item, struct desktop_line, next); + fprintf(stderr,"| %s\n",l->line); + } + return 0; +} + +static int free_file(struct list_head *file) +{ + struct desktop_line *l; + + while (!list_empty(file)) { + l = list_entry(file->next, struct desktop_line, next); + list_del(&l->next); + free(l); + } + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static char* get_entry(struct list_head *file, char *entry) +{ + struct desktop_line *l; + struct list_head *item; + int in_desktop_entry = 0; + int len = strlen(entry); + + list_for_each(item,file) { + l = list_entry(item, struct desktop_line, next); + if (0 == strcmp(l->line,"[Desktop Entry]")) { + in_desktop_entry = 1; + continue; + } + if (0 == strncmp(l->line,"[",1)) { + in_desktop_entry = 0; + continue; + } + if (!in_desktop_entry) + continue; + if (0 == strncmp(l->line,entry,len)) + return l->line+len; + } + return NULL; +} + +/* ------------------------------------------------------------------------- */ + +static int add_line(struct list_head *file, char *line) +{ + struct desktop_line *add; + + add = malloc(sizeof(*add)); + memset(add,0,sizeof(*add)); + snprintf(add->line,sizeof(add->line),"%s",line); + list_add_tail(&add->next,file); + return 0; +} + +static int add_entry(struct list_head *file, char *entry, char *value) +{ + struct desktop_line *l,*add; + struct list_head *item; + + list_for_each(item,file) { + l = list_entry(item, struct desktop_line, next); + if (0 != strcmp(l->line,"[Desktop Entry]")) + continue; + add = malloc(sizeof(*add)); + memset(add,0,sizeof(*add)); + snprintf(add->line,sizeof(add->line),"%s%s",entry,value); + list_add(&add->next,item); + return 0; + } + return -1; +} + +static int set_entry(struct list_head *file, char *type, char *entry, char *value) +{ + struct desktop_line *l; + struct list_head *item; + int in_desktop_entry = 0; + int len = strlen(entry); + + list_for_each(item,file) { + l = list_entry(item, struct desktop_line, next); + if (0 == strcmp(l->line,"[Desktop Entry]")) { + in_desktop_entry = 1; + continue; + } + if (0 == strncmp(l->line,"[",1)) { + in_desktop_entry = 0; + continue; + } + if (!in_desktop_entry) + continue; + if (0 == strncmp(l->line,entry,len)) { + snprintf(l->line,sizeof(l->line),"%s%s",entry,value); + return 0; + } + } + if (0 != add_entry(file,entry,value)) { + add_line(file,"[Desktop Entry]"); + add_entry(file,"Type=",type); + add_entry(file,entry,value); + } + return 0; +} + +/* ------------------------------------------------------------------------- */ +/* public interface */ + +int desktop_read_entry(char *filename, char *entry, char *dest, size_t max) +{ + struct list_head file; + char *value; + int rc = 0; + + read_file(filename,&file); + if (debug) + dump_file(&file); + value = get_entry(&file,entry); + if (NULL != value) { + rc = utf8_to_locale(value,dest,max); + if (rc && debug) + fprintf(stderr,"# %s\n",dest); + }; + free_file(&file); + return rc; +} + +int desktop_write_entry(char *filename, char *type, char *entry, char *value) +{ + struct list_head file; + char utf8[1024]; + + read_file(filename,&file); + locale_to_utf8(value,utf8,sizeof(utf8)); + set_entry(&file,"Directory",entry,utf8); + write_file(filename,&file); + free_file(&file); + return 0; +} -- cgit