"Fossies" - the Fresh Open Source Software Archive

Member "xcdroast-1.19/src/tools.c" (3 Nov 2018, 34125 Bytes) of package /linux/misc/xcdroast-1.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tools.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.18_vs_1.19.

    1 /*
    2  *  tools.c
    3  *  27.3.99 tn
    4  *
    5  *
    6  *  Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
    7  *
    8  *  This file is part of xcdroast.
    9  *
   10  *  This program is free software; you can redistribute it and/or modify
   11  *  it under the terms of the GNU General Public License as published by
   12  *  the Free Software Foundation; either version 2 of the License, or
   13  *  (at your option) any later version.
   14  *
   15  *  This program is distributed in the hope that it will be useful,
   16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18  *  GNU General Public License for more details.
   19  *
   20  *  You should have received a copy of the GNU General Public License
   21  *  along with this program; if not, write to the Free Software
   22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   23  */
   24 
   25 #ifdef HAVE_CONFIG_H
   26 # include <config.h>
   27 #endif
   28 
   29 #include <locale.h>
   30 #include "gettext.h"
   31 
   32 #include <stdio.h>
   33 #include <sys/stat.h>
   34 #include <unistd.h>
   35 #include <string.h>
   36 #include <strings.h>
   37 #include <dirent.h>
   38 #include <fcntl.h>
   39 #include <sys/types.h>
   40 #include <sys/time.h>
   41 #include <errno.h>
   42 #include <ctype.h>
   43 #include <pwd.h>
   44 
   45 #if ENABLE_NLS
   46 # define _(String) gettext (String)
   47 # define N_(String) gettext_noop (String)
   48 #else
   49 # define _(String) (String)
   50 # define N_(String) (String)
   51 #endif
   52 
   53 #include <gtk/gtk.h>
   54 #include <gdk/gdk.h>
   55 #include "xcdrdata.h"
   56 #include "xcdroast.h"
   57 #include "main.h"
   58 
   59 
   60 /*
   61  * return 1 if path is a directory and 0 if not or invalid path
   62  */
   63 gint is_directory(gchar *path) {
   64 struct stat buf;
   65 
   66     if (stat(path,&buf) != 0) {
   67         return 0;
   68     }
   69 
   70     if (S_ISDIR(buf.st_mode) == 1) {
   71         return 1;
   72     } else {
   73         return 0;
   74     }
   75 }
   76 
   77 /*
   78  * return 1 if path is not a directory and 0 if or invalid path
   79  */
   80 gint is_not_directory(gchar *path) {
   81 struct stat buf;
   82 
   83     if (stat(path,&buf) != 0) {
   84         return 0;
   85     }
   86 
   87     if (S_ISDIR(buf.st_mode) == 0) {
   88         return 1;
   89     } else {
   90         return 0;
   91     }
   92 }
   93 
   94 
   95 /*
   96  * return 1 if path is a file or directory and 0 if not or invalid path
   97  */
   98 gint is_file(gchar *path) {
   99 struct stat buf;
  100 
  101     if (stat(path,&buf) != 0) {
  102         return 0;
  103     }
  104     return 1;
  105 }
  106 
  107 
  108 /*
  109  * return the base directory of a given path, or NULL when invalid
  110  * warning..overwrites original str
  111  */
  112 gchar *get_basedir(gchar *dir) {
  113 gchar *p;
  114 
  115     /* nothing to do if this is already a directory */
  116     if (is_directory(dir)) {
  117         return dir;
  118     }
  119 
  120     /* look for last slash */
  121     p = rindex(dir,'/');
  122     if (p) {
  123         *p = '\0';
  124         if (strcmp(dir,"") == 0) {
  125             strcpy(dir,"/");
  126         }
  127         return dir;
  128     }
  129     return NULL;
  130 }
  131 
  132 
  133 /*
  134  * return the pure filename of a given path
  135  */
  136 gchar *get_purefile(gchar *dir, gchar *out) {
  137 gchar *p;
  138 
  139     /* look for last slash */
  140     p = rindex(dir,'/');
  141     if (p) {
  142         strncpy(out, p+1, MAXLINE);
  143     } else {
  144         strncpy(out, dir, MAXLINE);
  145     }
  146     
  147     return out;
  148 }
  149 
  150 
  151 /*
  152  * return 1 when path contains a subdir, else 0
  153  * skip . and ..-directories
  154  */
  155 gint is_subdirs(gchar *path) {
  156 struct dirent *ent;
  157 DIR *dir;         
  158 gchar tmp[MAXLINE];
  159 
  160     dir = opendir(path);
  161     
  162     /* invalid directory */
  163     if (dir == NULL) 
  164         return 0;
  165 
  166     while ( (ent = readdir(dir)) ) {
  167         strcpy(tmp,path);
  168         /* add slash when not there */
  169         if (tmp[strlen(tmp)-1] != '/')  
  170             strcat(tmp,"/");
  171         strcat(tmp,ent->d_name);
  172 
  173         if (strcmp(ent->d_name,".") == 0 || 
  174             strcmp(ent->d_name,"..") == 0) 
  175             continue;
  176 
  177         if (is_directory(tmp)) {
  178             closedir(dir);
  179             return 1;
  180         }
  181     }
  182     closedir(dir);
  183     return 0;
  184 }
  185 
  186 
  187 /*
  188  * return 1 when path contains files, else 0
  189  * skip . and ..-directories
  190  */
  191 gint is_subfiles(gchar *path) {
  192 struct dirent *ent;
  193 DIR *dir;         
  194 gchar tmp[MAXLINE];
  195 
  196     dir = opendir(path);
  197     
  198     /* invalid directory */
  199     if (dir == NULL) 
  200         return 0;
  201 
  202     while ( (ent = readdir(dir)) ) {
  203         strcpy(tmp,path);
  204         /* add slash when not there */
  205         if (tmp[strlen(tmp)-1] != '/')  
  206             strcat(tmp,"/");
  207         strcat(tmp,ent->d_name);
  208 
  209         if (strcmp(ent->d_name,".") == 0 || 
  210             strcmp(ent->d_name,"..") == 0) 
  211             continue;
  212 
  213         closedir(dir);
  214         return 1;
  215     }
  216     closedir(dir);
  217     return 0;
  218 }
  219 
  220 
  221 /*
  222  * strip off a string of leading and trailing whitespace
  223  */
  224 gchar *strip_string(gchar *str) {
  225 gint i,j;
  226 gint c1;
  227 
  228         if ( str == NULL) return (NULL);
  229 
  230         /* count how many leading chars to be whitespace */
  231         for(i=0; i<strlen(str); i++) {
  232                 if (str[i] != ' ' && str[i] != '\t' && str[i] != '\r') 
  233                         break;
  234         }
  235 
  236         /* count how many trailing chars to be whitespace */
  237         for(j=strlen(str)-1; j >= 0; j--) {
  238                 if (str[j] != ' ' && str[j] != '\t' && str[j] != '\n' && str[j] != '\r')
  239                         break;
  240         }
  241 
  242     /* string contains only whitespace? */
  243     if (j<i) {
  244         str[0] = '\0';
  245         return(str);
  246     }
  247 
  248         /* now move the chars to the front */
  249         for(c1=i; c1 <= j; c1++) {
  250                 str[c1-i] = str[c1]; 
  251         }
  252         str[j+1-i] = '\0';      
  253 
  254         return(str);
  255 }
  256 
  257 
  258 /*
  259  * parse escape-chars in string -> e.g. translate \n to newline
  260  */
  261 gchar *escape_parse(gchar *str) {
  262 gchar tmp[MAXLINE];
  263 gchar c;
  264 guint i,j;
  265 
  266         if ( str == NULL) return (NULL);
  267 
  268     j = 0;
  269         for(i=0; i<strlen(str); i++) {
  270         c = str[i];
  271         if (c == '\\') {
  272             i++;
  273             switch(str[i]) {
  274 
  275             case 'n':
  276                 c = '\n';
  277                 break;
  278             
  279             case 't':
  280                 c = '\t';
  281                 break;
  282     
  283             case 'b':
  284                 c = '\b';
  285                 break;
  286 
  287             default:
  288                 c = str[i];
  289             }
  290         }   
  291 
  292         tmp[j]=c;
  293         j++;
  294         }
  295 
  296     tmp[j] = '\0';
  297 
  298     strcpy(str,tmp);
  299         return(str);
  300 }
  301 
  302 
  303 /*
  304  * convert escape-chars in string -> e.g. newline to \n
  305  */
  306 gchar *convert_escape(gchar *str) {
  307 gchar tmp[MAXLINE*2];
  308 gchar c,d;
  309 guint i,j;
  310 
  311     if (str == NULL) return (NULL);
  312 
  313     j = 0;
  314     for (i = 0; i < strlen(str); i++) {
  315         c = str[i];
  316         d = '\0';
  317 
  318         switch (c) {
  319         case '\n':
  320             d = 'n';
  321             break;
  322         case '\t':
  323             d = 't';
  324             break;
  325         case '\b':
  326             d = 'b';
  327             break;
  328         case '\\':
  329             d = '\\';
  330             break;
  331         case '\"':
  332             d = '\"';
  333             break;
  334         case '=':
  335             d = '=';
  336             break;
  337         }
  338         if (d != '\0') {
  339             /* generate escaped char */
  340             tmp[j] = '\\'; j++;
  341             tmp[j] = d; j++;
  342         } else {
  343             tmp[j] = c; j++;
  344         }
  345     }
  346 
  347     tmp[j] = '\0';
  348 
  349     /* check if new string is not getting too long */
  350     if (strlen(tmp) < MAXLINE) {
  351         strcpy(str,tmp);
  352     } else {
  353         /* over MAXLINE chars - should never happen */
  354         /* cut off string */
  355         strncpy(str,tmp,MAXLINE-1);
  356         str[MAXLINE-1] = '\0';
  357     }
  358 
  359     return(str);
  360 }
  361 
  362 
  363 /*
  364  * another variant of escaping. Just required to escape = on the command
  365  * line of mkisofs directly
  366  */
  367 gchar *convert_escape3(gchar *str) {
  368 gchar tmp[MAXLINE*2];
  369 gchar c,d;
  370 guint i,j;
  371 
  372     if (str == NULL) return (NULL);
  373 
  374     j = 0;
  375     for (i = 0; i < strlen(str); i++) {
  376         c = str[i];
  377         d = '\0';
  378 
  379         switch (c) {
  380         case '\n':
  381             d = 'n';
  382             break;
  383         case '\t':
  384             d = 't';
  385             break;
  386         case '\b':
  387             d = 'b';
  388             break;
  389         case '\\':
  390             d = '\\';
  391             break;
  392         case '\"':
  393             d = '\"';
  394             break;
  395         case '=':
  396             d = '=';
  397             break;
  398         }
  399         if (d != '\0') {
  400             /* generate escaped char */
  401             tmp[j] = '\\'; j++;
  402             /* escape the =-sign double! */
  403             if (d == '=') {
  404                 tmp[j] = '\\'; j++;
  405             }
  406             tmp[j] = d; j++;
  407         } else {
  408             tmp[j] = c; j++;
  409         }
  410     }
  411 
  412     tmp[j] = '\0';
  413 
  414     /* check if new string is not getting too long */
  415     if (strlen(tmp) < MAXLINE) {
  416         strcpy(str,tmp);
  417     } else {
  418         /* over MAXLINE chars - should never happen */
  419         /* cut off string */
  420         strncpy(str,tmp,MAXLINE-1);
  421         str[MAXLINE-1] = '\0';
  422     }
  423     return(str);
  424 }
  425 
  426 
  427 /*
  428  * convert escape-chars in string -> e.g. newline to \n
  429  * this versions will not escape quotes..required for master-path-lists
  430  */
  431 gchar *convert_escape2(gchar *str) {
  432 gchar tmp[MAXLINE*2];
  433 gchar c,d;
  434 guint i,j;
  435 
  436     if (str == NULL) return (NULL);
  437 
  438     j = 0;
  439     for (i = 0; i < strlen(str); i++) {
  440         c = str[i];
  441         d = '\0';
  442 
  443         switch (c) {
  444         case '\n':
  445             d = 'n';
  446             break;
  447         case '\t':
  448             d = 't';
  449             break;
  450         case '\b':
  451             d = 'b';
  452             break;
  453         case '\\':
  454             d = '\\';
  455             break;
  456         case '=':
  457             d = '=';
  458             break;
  459         }
  460         if (d != '\0') {
  461             /* generate escaped char */
  462             tmp[j] = '\\'; j++;
  463             tmp[j] = d; j++;
  464         } else {
  465             tmp[j] = c; j++;
  466         }
  467     }
  468 
  469     tmp[j] = '\0';
  470 
  471     /* check if new string is not getting too long */
  472     if (strlen(tmp) < MAXLINE) {
  473         strcpy(str,tmp);
  474     } else {
  475         /* over MAXLINE chars - should never happen */
  476         /* cut off string */
  477         strncpy(str,tmp,MAXLINE-1);
  478         str[MAXLINE-1] = '\0';
  479     }
  480     return(str);
  481 }
  482 
  483 
  484 /*
  485  * check if there are illegal chars in our string and replace them with _
  486  * return 0 if all ok, and 1 if any chars changed/removed
  487  */
  488 gint remove_illegal_chars(gchar *str) {
  489 guint i,j;
  490 
  491     if (str == NULL) return 0;
  492 
  493     j = 0;
  494     for (i = 0; i < strlen(str); i++) {
  495         switch (str[i]) {
  496         case '/':
  497         case '\\':
  498         case '\b':
  499         case '\t':
  500             str[i] = '_';
  501             j = 1;
  502             break;
  503         }
  504     }
  505 
  506     return(j);
  507 }
  508 
  509 
  510 /*
  511  * check if there are illegal chars in our iconv charset string and remove them quietly
  512  * for safety reasons, only letters, numbers and . : - _ / ( ) are allowed
  513  * mkisofs warns itself if the entered customer i/o-charset doesn't match
  514  */
  515 void remove_illegal_chars_iconv(gchar *str) {
  516 guint i, j, len;
  517 gchar tmp[MAXLINE];
  518 
  519     j = 0;
  520     len = strlen(str); 
  521 
  522     if (len >= MAXLINE-1)
  523         len = MAXLINE-1;
  524  
  525     if (str != NULL) {
  526         for (i = 0; i < len; i++) {
  527             if ( ( str[i] >= 'A' && str[i] <= 'Z' )
  528               || ( str[i] >= 'a' && str[i] <= 'z' )
  529               || ( str[i] >= '0' && str[i] <= '9' )
  530               || str[i] == '.' 
  531               || str[i] == ':' 
  532               || str[i] == '-' 
  533               || str[i] == '_' 
  534               || str[i] == '/' 
  535               || str[i] == '(' 
  536               || str[i] == ')' ) {
  537                 tmp[j] = str[i];
  538                 j++;
  539             }
  540         }
  541         tmp[j] = '\0';
  542         strcpy(str, tmp);
  543     }
  544 }
  545 
  546 
  547 /*
  548  * get a string of the form "'xxx' from 'xxx'" and extract the strings xxx
  549  * to artist and title. remove any escape characters.
  550  * Return 0 if all ok, 1 on problems
  551  */
  552 gint decode_title_artist(gchar *str, gchar *title, gchar *artist) {
  553 gchar tmp[MAXLINE];
  554 gchar tmp2[MAXLINE];
  555 gchar convtmp[MAXLINE];
  556 gchar c, oldc;
  557 guint i;
  558 
  559     if (str == NULL) {
  560         return 1;
  561     }
  562 
  563     oldc = '\0';
  564 
  565     /* check first char */
  566     if (str[0] != '\'') {
  567         /* not right - abort */
  568         return 1;
  569     }
  570     strcpy(tmp,str+1);
  571 
  572     if (charset_convert_to_utf8(tmp, convtmp))
  573         strncpy(tmp, convtmp, MAXLINE);
  574 
  575     /* look for next unescaped quote */
  576     for (i = 0; i < strlen(tmp); i++) {
  577         c = tmp[i];
  578 
  579         /* if current char ' and previous not \ we are done */
  580         if ((c == '\'') && (oldc != '\\')) {
  581             break;
  582         }
  583         oldc = c;
  584     }
  585 
  586     if (i == strlen(tmp)) {
  587         /* no quote found at all */
  588         return 1;
  589     }
  590 
  591     /* done extracting the title */
  592     strncpy(title,tmp,i);
  593     title[i] = '\0';
  594     /* now parse all other escaped chars */
  595     escape_parse(title);
  596 
  597     /* now the artist-field */
  598     strcpy(tmp2, tmp+i);
  599     if (strncmp(tmp2,"' from '",8) != 0) {
  600         /* look for middle string */
  601         /* not fitting - abort */ 
  602         return 1;
  603     }
  604     strcpy(tmp,tmp2+8);
  605 
  606     /* look for next unescaped quote */
  607     for (i = 0; i < strlen(tmp); i++) {
  608         c = tmp[i];
  609 
  610         /* if current char ' and previous not \ we are done */
  611         if ((c == '\'') && (oldc != '\\')) {
  612             break;
  613         }
  614         oldc = c;
  615     }
  616 
  617     if (i == strlen(tmp)) {
  618         /* no quote found at all */
  619         return 1;
  620     }
  621 
  622     /* done extracting the artist */
  623     strncpy(artist,tmp,i);
  624     artist[i] = '\0';
  625     /* now parse all other escaped chars */
  626     escape_parse(artist);
  627 
  628     return 0;
  629 }
  630 
  631 
  632 /*
  633  * read a single char from a file descriptor;
  634  * If the descriptor says that it is not available,
  635  * then try again up to 5 times before giving up.
  636  * This was required for Mac OS X 10.3 but is obsolete now.
  637  */
  638 static gint read_char(gint fd, gchar *c) {
  639 gint rc;
  640 gint retries;
  641 
  642         retries = 5;
  643 
  644         while (retries) {
  645                 rc = read(fd, c, 1);
  646 
  647                 /* all ok, read one char or EOF */
  648                 if (rc != -1) {
  649                         return rc;
  650                 }
  651 
  652                 /* error code, try again after a little while */
  653                 usleep(100);
  654                 retries--;
  655         }
  656         return rc;
  657 }
  658 
  659 
  660 /*
  661  * Read a line from a descriptor.  Read the line one byte at a time,
  662  * looking for the newline. Works fine in nonblocking mode..here
  663  * we return when no more data can be read. 
  664  * We overwrite the newline with a null.
  665  * We return the number of characters up to, but not including,
  666  * the null (the same as strlen(3)).
  667  */
  668 gint read_line(gint fd, gchar *ptr, gint maxlen) {
  669 gint n, rc;
  670 gchar c;
  671 gchar *str;
  672 
  673     str = ptr;
  674  
  675         for (n = 1; n < maxlen; n++) {
  676                 if ( (rc = read_char(fd, &c)) == 1) {
  677                         *ptr++ = c;
  678                         if (c == '\n') {
  679                                 break;
  680                         }
  681 
  682                 } else if (rc == 0) {
  683             /* EOF */
  684                         if (n == 1)
  685                                 return(0);      /* EOF, no data read */
  686                         else
  687                                 break;          /* EOF, some data was read */
  688                 } else if (rc == -2) {
  689             /* timeout while reading string */
  690             return(-2);
  691         } else {
  692             /* nonblocking mode an nothing to read? */
  693             if (rc == -1 && errno == EAGAIN) {
  694                 if (n == 1) 
  695                     return(-1);
  696                 else
  697                     break;
  698             }   
  699                         return(-1);     /* error */
  700         }
  701         }
  702 
  703     /* terminate the string */
  704     *ptr = 0;
  705  
  706         /*
  707      * strip off some trailing chars
  708      * yes, we need both levels
  709      */
  710     if (strlen(str) > 0) {
  711             ptr--;
  712             if ((*ptr == '\n') || (*ptr == '\r') ) {
  713                     *ptr = 0;
  714             }
  715     }
  716     if (strlen(str) > 0) {
  717             ptr--;
  718             if ((*ptr == '\n') || (*ptr == '\r') ) {
  719                     *ptr = 0;
  720             }
  721     }
  722  
  723     if (strlen(str) == 0) {
  724         /* if we read an empty string, but are NOT at EOF return 1 */
  725         return 1;
  726     } else {
  727             return(strlen(str));
  728     }
  729 }
  730 
  731 
  732 /*
  733  * Read all available output from GIOChannel, remove the training newline.
  734  * We return the number of characters up to, but not including,
  735  * the null (the same as strlen(3)).
  736  */
  737 gint read_io_channel_all(GIOChannel *channel, gchar *ptr, gint maxlen) {
  738 GError *err = NULL;
  739 GIOStatus ret;
  740 gsize len;
  741 gchar *str, *p;
  742 gchar buf[MAXLINE];
  743 
  744     /* remember start of return pointer */
  745     str = ptr;
  746     ret = g_io_channel_read_chars(channel, buf, MAXLINE, &len, &err);
  747     if (ret == G_IO_STATUS_ERROR) {
  748         g_error("Error reading from io channel: %s\n", err->message);
  749         strcpy(ptr, "");
  750         return 0;
  751     }
  752     if (len > 0) {
  753         /* find last newline and overwrite (to remove junk) */
  754         if ((p = strrchr(buf, '\n')) != NULL)
  755             *p = '\0';
  756         strncpy(ptr, buf, maxlen);
  757     } else {
  758         /* nothing read? (happens in non-block mode) */
  759         strcpy(ptr, "");
  760         return 0;
  761     }
  762 
  763     /* point to the end */
  764     ptr = ptr + strlen(str);
  765 
  766     /* terminate the string */
  767     *ptr = 0;
  768  
  769         /*
  770      * strip off some trailing chars
  771      * yes, we need both levels
  772      */
  773     if (strlen(str) > 0) {
  774             ptr--;
  775             if ((*ptr == '\n') || (*ptr == '\r') ) {
  776                     *ptr = 0;
  777             }
  778     }
  779     if (strlen(str) > 0) {
  780             ptr--;
  781             if ((*ptr == '\n') || (*ptr == '\r') ) {
  782                     *ptr = 0;
  783             }
  784     }
  785 
  786     return (strlen(str));
  787 }
  788 
  789 /*
  790  * Read a single line from GIOChannel, remove the training newline.
  791  * We return the number of characters up to, but not including,
  792  * the null (the same as strlen(3)).
  793  */
  794 gint read_io_channel(GIOChannel *channel, gchar *ptr, gint maxlen) {
  795 GError *err = NULL;
  796 GIOStatus ret;
  797 gsize len;
  798 gchar *msg;
  799 gchar *str;
  800 
  801     /* remember start of return pointer */
  802     str = ptr;
  803     ret = g_io_channel_read_line(channel, &msg, &len, NULL, &err);
  804     if (ret == G_IO_STATUS_ERROR) {
  805         g_error("Error reading from io channel: %s\n", err->message);
  806         strcpy(ptr, "");
  807         return 0;
  808     }
  809     if (len > 0) {
  810         strncpy(ptr, msg, maxlen);
  811     } else {
  812         /* nothing read? (happens in non-block mode) */
  813         strcpy(ptr, "");
  814         return 0;
  815     }
  816 
  817     /* point to the end */
  818     ptr = ptr + strlen(str);
  819     g_free(msg);
  820 
  821     /* terminate the string */
  822     *ptr = 0;
  823  
  824         /*
  825      * strip off some trailing chars
  826      * yes, we need both levels
  827      */
  828     if (strlen(str) > 0) {
  829             ptr--;
  830             if ((*ptr == '\n') || (*ptr == '\r') ) {
  831                     *ptr = 0;
  832             }
  833     }
  834     if (strlen(str) > 0) {
  835             ptr--;
  836             if ((*ptr == '\n') || (*ptr == '\r') ) {
  837                     *ptr = 0;
  838             }
  839     }
  840 
  841     return (strlen(str));
  842 }
  843 
  844 
  845 /*
  846  * Use this version to work around some of the critical races
  847  * such as by 127658. This issue should be solved on a case by case basis.
  848  * Expected side effects: GUI freezes (e.g. if called from read_write_out() in io.c).
  849  */
  850 /*** No longer used ***/
  851 
  852 gint read_line_wait(gint fd, gchar *ptr, gint maxlen) {
  853 gint n, rc;
  854 gchar c;
  855 gchar *str;
  856 
  857     str = ptr;
  858  
  859         for (n = 1; n < maxlen; n++) {
  860                 if ( (rc = read(fd, &c, 1)) == 1) {
  861                         *ptr++ = c;
  862                         if (c == '\n') {
  863                                 break;
  864                         }
  865 
  866                 } else if (rc == 0) {
  867             /* EOF */
  868                         if (n == 1)
  869                                 return(0);      /* EOF, no data read */
  870                         else
  871                                 break;          /* EOF, some data was read */
  872                 } else if (rc == -2) {
  873             /* timeout while reading string */
  874             return(-2);
  875         } else {
  876             /* nonblocking mode an nothing to read? */
  877             if (rc == -1 && errno == EAGAIN) {
  878                 if (n == 1) 
  879                     return(-1);
  880                 else {
  881                     /*
  882                      * Partial line read. Wait a bit longer
  883                      * in case there's more. This does not fix
  884                      * all the races in the parsing code,
  885                      * but works around them somewhat.
  886                      */
  887                     struct timeval t;
  888                     fd_set set;
  889                     FD_ZERO(&set);
  890                     FD_SET(fd,&set);
  891                     t.tv_sec = 1;
  892                     t.tv_usec = 0;
  893                     if (select (fd+1, &set, NULL,
  894                             NULL, &t) > 0)
  895                         continue;
  896 
  897                     break;
  898                 }   
  899             }   
  900                         return(-1);     /* error */
  901         }
  902         }
  903 
  904     /* terminate the string */
  905     *ptr = 0;
  906  
  907         /*
  908      * strip off some trailing chars
  909      * yes, we need both levels
  910      */
  911     if (strlen(str) > 0) {
  912             ptr--;
  913             if ((*ptr == '\n') || (*ptr == '\r') ) {
  914                     *ptr = 0;
  915             }
  916     }
  917     if (strlen(str) > 0) {
  918             ptr--;
  919             if ((*ptr == '\n') || (*ptr == '\r') ) {
  920                     *ptr = 0;
  921             }
  922     }
  923  
  924     if (strlen(str) == 0) {
  925         /* if we read an empty string, but are NOT at EOF return 1 */
  926         return 1;
  927     } else {
  928             return(strlen(str));
  929     }
  930 }
  931 
  932 
  933 /*
  934  * extract quotes-delimted string after first colon
  935  * e.g.: 03: "bla" -> bla
  936  */
  937 gint extract_quoted(gchar *str) {
  938 gchar *p, *p2;
  939 gchar tmp[MAXLINE];
  940 gchar tmp2[MAXLINE];
  941 
  942     strcpy(tmp,str);
  943 
  944     /* get string after first colon */
  945     p = strtok(tmp,":");
  946     if (p == NULL)
  947         return 1;
  948     p = strtok(NULL,"");
  949     if (p == NULL) 
  950         return 1;
  951 
  952     strcpy(tmp,p);
  953     strip_string(tmp);
  954 
  955     /* now strip off quotes */
  956     p = tmp;
  957     if (*p == '\"') {
  958         p2 = p+1;
  959     } else {
  960         p2 = p;
  961     }
  962     if (p[strlen(p)-1] == '\"') {
  963         p[strlen(p)-1] = '\0';
  964     }
  965     strcpy(tmp2,p2);
  966     escape_parse(tmp2);
  967 
  968     strcpy(str,tmp2);
  969 
  970     return 0;
  971 }
  972 
  973 
  974 /*
  975  * extract single quotes-delimted string
  976  * e.g.: 'bla' -> bla
  977  */
  978 gint extract_singlequoted(gchar *str) {
  979 gchar *p, *p2;
  980 gchar tmp[MAXLINE];
  981 
  982     strcpy(tmp,str);
  983     strip_string(tmp);
  984 
  985     /* now strip off quotes */
  986     p = tmp;
  987     if (*p == '\'') {
  988         p2 = p+1;
  989     } else {
  990         p2 = p;
  991     }
  992     if (p[strlen(p)-1] == '\'') {
  993         p[strlen(p)-1] = '\0';
  994     }
  995     strcpy(str,p2);
  996 
  997     return 0;
  998 }
  999 
 1000 
 1001 /*
 1002  * read one char from a file descriptor with timeout
 1003  * return 1 if char read ok, -1 on read error, -2 on timeout
 1004  */
 1005 gint get_char(gint fd, char *c) {
 1006 gint j;
 1007 struct timeval t;
 1008 fd_set set;
 1009 
 1010     FD_ZERO(&set);
 1011     FD_SET(fd,&set);
 1012     t.tv_sec = NETIOTIMEOUT;
 1013     t.tv_usec = 0;
 1014 
 1015     j = select(fd+1, &set, NULL, NULL, &t);
 1016     if (j > 0) {
 1017         return(read(fd, c, 1));
 1018     } else {    
 1019         /* timeout triggered */
 1020         return -2;
 1021     }
 1022 }
 1023 
 1024 
 1025 /*
 1026  * Read a line from a descriptor.  Read the line one byte at a time,
 1027  * looking for the newline.  
 1028  * We overwrite the newline with a null.
 1029  * We return the number of characters up to, but not including,
 1030  * the null (the same as strlen(3)).
 1031  */
 1032 gint read_line2(gint fd, gchar *ptr, gint maxlen, gint timeout) {
 1033 gint n, rc;
 1034 gchar c;
 1035  
 1036         for (n = 1; n < maxlen; n++) {
 1037         if (timeout) {
 1038             /* use timeout */
 1039             rc = get_char(fd,&c);
 1040         } else {
 1041             rc = read(fd, &c, 1);
 1042         }   
 1043         if ( rc == 1) {
 1044                         *ptr++ = c;
 1045                         if (c == '\n') {
 1046                                 break;
 1047                         }
 1048                 } else if (rc == 0) {
 1049                         if (n == 1)
 1050                                 return(0);      /* EOF, no data read */
 1051                         else
 1052                                 break;          /* EOF, some data was read */
 1053                 } else if (rc == -2) {
 1054             /* timeout while reading string */
 1055             return(-2);
 1056         } else {
 1057                         return(-1);     /* error */
 1058         }
 1059         }
 1060  
 1061         /*
 1062      * strip off some trailing chars
 1063      * yes, we need all three levels
 1064      */
 1065         if ((*ptr == '\n') || (*ptr == '\r') ) {
 1066                 *ptr = 0;
 1067         }
 1068         ptr--;
 1069         if ((*ptr == '\n') || (*ptr == '\r') ) {
 1070                 *ptr = 0;
 1071         }
 1072         ptr--;
 1073         if ((*ptr == '\n') || (*ptr == '\r') ) {
 1074                 *ptr = 0;
 1075         }
 1076  
 1077         return(n);
 1078 }
 1079 
 1080  
 1081 /*
 1082  * Write "n" bytes to a descriptor.
 1083  * Use in place of write() when fd is a stream socket.
 1084  */
 1085 gint writen(gint fd, gchar *ptr, gint nbytes, gint newline) {
 1086 gint nleft, nwritten;
 1087  
 1088         nleft = nbytes;
 1089         while (nleft > 0) {
 1090                 nwritten = write(fd, ptr, nleft);
 1091                 if (nwritten <= 0)
 1092                         return(nwritten);               /* error */
 1093  
 1094                 nleft -= nwritten;
 1095                 ptr   += nwritten;
 1096         }
 1097  
 1098         /* add a newline when requested */
 1099         if (newline) {
 1100                 nwritten = write(fd,"\n",1);
 1101         }
 1102  
 1103         return(nbytes - nleft);
 1104 }
 1105 
 1106 
 1107 /*
 1108  * replace ~/ in an entry field by the home-directory
 1109  * warning - in some cases $HOME is not correct when user root
 1110  */
 1111 gchar *check_tilde(gchar *str) {
 1112 gchar tmp[MAXLINE];
 1113 
 1114     if (str == NULL) 
 1115         return str;
 1116 
 1117     strip_string(str);
 1118 
 1119     /* too short, do nothing */
 1120     if (strlen(str) < 2) 
 1121         return str;
 1122 
 1123     /* ~/ found? */
 1124     if (str[0] == '~' && str[1] == '/') {
 1125         tmp[0] = '\0';
 1126         if (!isroot()) {
 1127             /* we are not root, trust $HOME */
 1128             if (g_get_home_dir()) {
 1129                 strcpy(tmp, g_get_home_dir());
 1130             }
 1131         } else {
 1132             /* as root $HOME is often wrong - override */
 1133             if (get_pw_home(0)) {
 1134                 strcpy(tmp, get_pw_home(0));
 1135             }
 1136         }
 1137         strcat(tmp,"/");
 1138         strcat(tmp,str+2);
 1139 
 1140         strcpy(str,tmp);
 1141     }
 1142 
 1143     return str;
 1144 }
 1145 
 1146 
 1147 /*
 1148  * parse config line and return id and value
 1149  * return 0 if ok, 1 on error
 1150  */
 1151 gint parse_config_line(gchar *iline, gchar *id, gchar *value) {
 1152 gchar *p,*p2;
 1153 gchar line[1024];
 1154 gchar tmp[1024];
 1155 
 1156     strncpy(line,iline, MAXLINE); 
 1157     strcpy(id,"");
 1158         p = strtok(line,"=");
 1159         if (p != NULL) {
 1160         /* got id */
 1161             strcpy(id,p);
 1162                 strip_string(id);
 1163         } else {
 1164         return 1;
 1165     }
 1166 
 1167     strcpy(tmp,"");
 1168         p = strtok(NULL,"");
 1169         if (p != NULL) {
 1170         /* string after = */
 1171             strcpy(tmp,p);
 1172                 strip_string(tmp);
 1173         } else { 
 1174         return 1;
 1175     }
 1176 
 1177         /* now strip off quotes from string */
 1178         p = tmp;
 1179         if (*p == '\"') {
 1180                 p2 = p+1;
 1181         } else {
 1182                 p2 = p;
 1183         }
 1184         if (p[strlen(p)-1] == '\"') {
 1185                 p[strlen(p)-1] = '\0';
 1186         }
 1187         strcpy(value,p2);
 1188 
 1189         /* now reconvert escape-chars */
 1190         escape_parse(value);
 1191 
 1192     /* all ok */
 1193     return 0;
 1194 }
 1195 
 1196 
 1197 /*
 1198  * parse config line and return id and value, value2
 1199  * form is  ID = "val1","val2"
 1200  * return 0 if ok, 1 on error
 1201  */
 1202 gint parse_config_line2(gchar *iline, gchar *id, gchar *value, gchar *value2) {
 1203 gchar *p,*p2;
 1204 gchar line[1024];
 1205 gchar tmp[1024];
 1206 
 1207     strncpy(line,iline,MAXLINE); 
 1208     strcpy(id,"");
 1209     strcpy(value,"");
 1210     strcpy(value2,"");
 1211         p = strtok(line,"=");
 1212         if (p != NULL) {
 1213         /* got id */
 1214             strcpy(id,p);
 1215                 strip_string(id);
 1216         } else {
 1217         return 1;
 1218     }
 1219 
 1220     strcpy(tmp,"");
 1221         p = strtok(NULL,"");
 1222         if (p != NULL) {
 1223         /* string after = */
 1224             strcpy(tmp,p);
 1225                 strip_string(tmp);
 1226         } else { 
 1227         return 1;
 1228     }
 1229 
 1230         /* now strip off quotes from string */
 1231         p = tmp;
 1232         if (*p == '\"') {
 1233                 p2 = p+1;
 1234         } else {
 1235                 p2 = p;
 1236         }
 1237         if (p[strlen(p)-1] == '\"') {
 1238                 p[strlen(p)-1] = '\0';
 1239         }
 1240         strcpy(line,p2);
 1241 
 1242     /* now in line is someling like xxx","yyy */
 1243     p = strstr(line,"\",\"");
 1244     if (p) {
 1245         *p = '\0';
 1246         strcpy(value,line);
 1247         strcpy(value2,p+3);
 1248     }
 1249 
 1250         /* now reconvert escape-chars */
 1251         escape_parse(value);
 1252         escape_parse(value2);
 1253 
 1254     /* all ok */
 1255     return 0;
 1256 }
 1257 
 1258 
 1259 /*
 1260  * check if we are root
 1261  */
 1262 gint isroot() {
 1263 
 1264     if (geteuid() == 0) {
 1265         return 1;
 1266     } else {
 1267         return 0;
 1268     }
 1269 }
 1270 
 1271 
 1272 /*
 1273  * check if user exists
 1274  */
 1275 gint check_pw_user(gchar *name) {
 1276 struct passwd *ent;
 1277 
 1278     ent = getpwnam(name);
 1279     if (ent) return 1;
 1280     return 0;
 1281 }
 1282 
 1283 
 1284 /*
 1285  * return the homedir (as in /etc/passwd) for a given user
 1286  */
 1287 gchar *get_pw_home(gint uid) {
 1288 struct passwd *ent;
 1289 
 1290     ent = getpwuid(uid);
 1291 
 1292     if (ent) 
 1293         return ent->pw_dir;
 1294     else
 1295         return NULL;
 1296 }
 1297 
 1298 
 1299 /*
 1300  * return the owner (uid) of a given file
 1301  */
 1302 gint get_file_owner(gchar *path) {
 1303 struct stat buf;
 1304 
 1305     if (stat(path,&buf) != 0) {
 1306         return -1;
 1307     }
 1308 
 1309     return (buf.st_uid);
 1310 }
 1311 
 1312 
 1313 /*
 1314  * does move a text file
 1315  */
 1316 gint move_textfile(gchar *src, gchar *target) {
 1317 FILE *fd, *fd2;
 1318 gchar line[MAXLINE];
 1319 
 1320     fd = fopen(src,"r");
 1321     if (!fd) {
 1322         /* src file failed to open */
 1323         return 1;
 1324     }
 1325 
 1326     fd2 = fopen(target,"w");
 1327     if (!fd2) {
 1328         /* target file failed to open */
 1329         fclose(fd);
 1330         return 1;
 1331     }
 1332 
 1333     /* copy file line by line */
 1334     for (;;) {
 1335         if (fgets(line,MAXLINE,fd) == NULL)
 1336             break;
 1337     
 1338         fputs(line,fd2);
 1339     }
 1340 
 1341     fclose(fd2);
 1342     fclose(fd);
 1343 
 1344     /* now delete the src file */
 1345     unlink(src);
 1346 
 1347     return 0;
 1348 }
 1349 
 1350 
 1351 /*
 1352  * checks if a given file is a link. If so return 1
 1353  * return the value of the link too, if requested
 1354  */
 1355 gint check_islink(gchar *file, gchar *link) {
 1356 struct stat buf;
 1357 
 1358     if (lstat(file, &buf) == 0) {
 1359         if (S_ISLNK(buf.st_mode)) {
 1360             if (link) {
 1361                 memset(link, 0, MAXLINE); 
 1362                 if (readlink(file, link, MAXLINE-1) <= 0) {
 1363                     strcpy(link, "?");
 1364                 }
 1365             }
 1366             return 1;
 1367         }
 1368     }
 1369 
 1370     return 0;
 1371 }
 1372 
 1373 
 1374 /*
 1375  * extract a readable string from a buffer
 1376  */
 1377 void get_subheader(gchar *buf, gchar *text, gint start, gint end) {
 1378 gchar tmp[MAXLINE];
 1379 gchar c;
 1380 gint i,count;
 1381 
 1382         count = 0;
 1383         for(i = start; i < end; i++) {
 1384                 c = buf[i];
 1385                 if (isprint((gint)c) || isspace((gint)c)) {
 1386                         tmp[count++] = c;
 1387                 }
 1388         }
 1389         tmp[count] = '\0';
 1390         
 1391         for(i = strlen(tmp)-1; i >= 0; i--) {
 1392                 if(tmp[i] != 0 && tmp[i] != ' ') {
 1393                         tmp[i+1] = '\0';
 1394                         break;
 1395                 }
 1396         }
 1397           
 1398     strip_string(tmp);
 1399         strcpy(text, tmp);
 1400 }
 1401 
 1402 
 1403 /*
 1404  * URL decoding - used because drag&drop names are often URL encoded
 1405  * borrowed from php4 source code (php4/ext/standard/url.c)
 1406  */
 1407 static gint url_htoi(gchar *s) {
 1408 gint value;
 1409 gint c;
 1410 
 1411         c = s[0];
 1412         if (isupper(c))
 1413                 c = tolower(c);
 1414         value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
 1415 
 1416         c = s[1];
 1417         if (isupper(c))
 1418                 c = tolower(c);
 1419         value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
 1420 
 1421         return (value);
 1422 }
 1423 
 1424 
 1425 gchar *url_decode(gchar *str, gint len) {
 1426 gchar *dest = str;
 1427 gchar *data = str;
 1428 
 1429     while (len--) {
 1430                 if (*data == '+')
 1431             *dest = ' ';
 1432         else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) {
 1433                         *dest = (gchar) url_htoi(data + 1);
 1434                         data += 2;
 1435                         len -= 2;
 1436                 } else
 1437                         *dest = *data;
 1438                 data++;
 1439                 dest++;
 1440     }
 1441         *dest = '\0';
 1442         return dest;
 1443 }   
 1444 
 1445 
 1446 /*
 1447  * URL encoding - used because drag&drop names are often URL encoded
 1448  * borrowed from php4 source code (php4/ext/standard/url.c)
 1449  */
 1450 static unsigned char hexchars[] = "0123456789ABCDEF";
 1451 
 1452 /*
 1453  * encode all special chars, but not / - and .
 1454  */
 1455 gchar *url_encode(gchar *s, gint len, gint *new_length) {
 1456 gint x, y;
 1457 guchar *str;
 1458 
 1459     str = (guchar *) g_new0(guchar *, 3 * len + 1);
 1460         for (x = 0, y = 0; len--; x++, y++) {
 1461                 str[y] = (guchar) s[x];
 1462                 if (str[y] == ' ') {
 1463                         str[y] = '+';
 1464                 } else if ((str[y] < '0' && str[y] != '-' && str[y] != '.' && str[y] != '/') ||
 1465                                    (str[y] < 'A' && str[y] > '9') ||
 1466                                    (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
 1467                                    (str[y] > 'z')) {
 1468                         str[y++] = '%';
 1469                         str[y++] = hexchars[(guchar) s[x] >> 4];
 1470                         str[y] = hexchars[(guchar) s[x] & 15];
 1471                 }
 1472         }
 1473         str[y] = '\0';
 1474         if (new_length) {
 1475                 *new_length = y;
 1476         }
 1477         return ((gchar *) str);
 1478 }
 1479 
 1480 
 1481 /*
 1482  * extract the first filename from a set of data received from a drag 
 1483  * operation - return 1 on success
 1484  */
 1485 gint extract_single_drag_filename(gchar *dragtext, gint draglen, gchar *rettext) {
 1486 gchar *p;
 1487 gchar tmp[MAXLINE];
 1488 gint len;
 1489 
 1490     /* if we got serveral filenames only use the first */
 1491     if (dragtext) {
 1492         p = index(dragtext,'\r');   
 1493         if (p) {
 1494             len = p - dragtext;
 1495             if (len < MAXLINE) {
 1496                 strncpy(tmp,dragtext,len);
 1497                 tmp[len] = '\0';
 1498             } else {
 1499                 return 0;
 1500             }
 1501         } else {
 1502             strncpy(tmp,dragtext, MAXLINE);
 1503         }
 1504 
 1505         /* extracted a single item */
 1506         strip_string(tmp);  
 1507 
 1508     
 1509         /* does it begin with file:? */
 1510         if (strncmp(tmp,"file:", 5) == 0) {
 1511             /* two slashes at front? */
 1512             if (strlen(tmp) > 7 && tmp[5] == '/' && tmp[6] == '/') {
 1513                 /* three slashes? */
 1514                 if (strlen(tmp) > 8 && tmp[7] == '/') {
 1515                     strncpy(rettext,tmp+7, MAXLINE);
 1516                     /* url_decode only this case */
 1517                     url_decode(rettext, strlen(rettext));
 1518                 } else {
 1519                     strncpy(rettext,tmp+6, MAXLINE);
 1520                 }
 1521             } else {    
 1522                 strncpy(rettext,tmp+5, MAXLINE);
 1523             }
 1524             return 1;
 1525         }
 1526     }
 1527 
 1528     return 0;
 1529 }
 1530 
 1531 
 1532 /*
 1533  * extract the a list of filename from a set of data received from a drag 
 1534  * operation - return 1 on success
 1535  */
 1536 gint extract_glist_drag_filenames(gchar *dragtext, gint draglen, gchar *match, GList **dst) {
 1537 gchar *p, *buf;
 1538 gchar tmp[MAXLINE], tmp2[MAXLINE];
 1539 gint count;
 1540 
 1541     count = 0;
 1542 
 1543     /* if we got serveral filenames only use the first */
 1544     if (dragtext) {
 1545         /* allocate a tmp buffer for the drag data */
 1546         buf = g_strdup(dragtext);
 1547 
 1548         p = strtok(buf,"\r\n"); 
 1549         while (p) {
 1550             strncpy(tmp, p, MAXLINE);
 1551             strip_string(tmp);  
 1552 
 1553             /* does it begin with file:? */
 1554             if (strncmp(tmp,match, 5) == 0) {
 1555                 /* two slashes at front? */
 1556                 if (strlen(tmp) > 7 && tmp[5] == '/' && tmp[6] == '/') {
 1557                     /* three slashes? */
 1558                     if (strlen(tmp) > 8 && tmp[7] == '/') {
 1559                         strncpy(tmp2,tmp+7, MAXLINE);
 1560                         /* url decode this case */
 1561                         url_decode(tmp2, strlen(tmp2));
 1562                     } else {
 1563                         strncpy(tmp2,tmp+6, MAXLINE);
 1564                     }
 1565                 } else {    
 1566                     strncpy(tmp2,tmp+5, MAXLINE);
 1567                 }
 1568                 *dst = g_list_append(*dst, g_strdup(tmp2));
 1569                 count++;
 1570             }
 1571             p = strtok(NULL,"\r\n");
 1572         }
 1573         g_free(buf);
 1574     }
 1575 
 1576     if (count > 0) {
 1577         return 1;
 1578     } else {
 1579         return 0;
 1580     }
 1581 }
 1582 
 1583 
 1584 /*
 1585  * return 1 when invalid MCN number
 1586  * code from cdrtools  auinfo.c
 1587  */
 1588 gint verify_mcn(gchar *mcn) {
 1589 gchar *p;
 1590 
 1591     /* wrong length? */
 1592     if (strlen(mcn) != 13) {
 1593         return 1;
 1594     }
 1595 
 1596     for (p = mcn; *p; p++) {
 1597         /* illegal chars in string? */
 1598         if (*p < '0' || *p > '9') {
 1599             return 1;
 1600         }
 1601     }
 1602     return 0;
 1603 }
 1604 
 1605 
 1606 /*
 1607  * return 1 when invalid ISRC number
 1608  * code from cdrtools  auinfo.c
 1609  */
 1610 gint verify_isrc(gchar *isrc) {
 1611 gchar upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 1612 gchar ibuf[13];
 1613 gchar *ip, *p;
 1614 gint i, len;
 1615 
 1616     if ((len = strlen(isrc)) != 12) {
 1617         for (p = isrc, i = 0; *p; p++) {
 1618             if (*p == '-')
 1619                 i++;
 1620         }
 1621         if (((len - i) != 12) || i > 3) {
 1622             /* illegal length */
 1623             return 1;
 1624         }
 1625     }
 1626         
 1627     /* check country code */
 1628         for (p = isrc, ip = ibuf, i = 0; i < 2; p++, i++) {
 1629                 *ip++ = *p;
 1630                 if (!strchr(upper, *p)) {
 1631             /* allow numbers even when not expected */
 1632                         if (*p >= '0' && *p <= '9')
 1633                                 continue;
 1634             return 1;
 1635                 }
 1636         }
 1637         if (*p == '-')
 1638                 p++;
 1639     
 1640         /* owner code */
 1641         for (i = 0; i < 3; p++, i++) {
 1642                 *ip++ = *p;
 1643                 if (strchr(upper, *p))
 1644                         continue;
 1645                 if (*p >= '0' && *p <= '9')
 1646                         continue;
 1647         return 1;
 1648         }
 1649         if (*p == '-')
 1650                 p++;
 1651 
 1652     /* year and recording number */
 1653         for (i = 0; i < 7; p++, i++) {
 1654                 *ip++ = *p;
 1655                 if (*p >= '0' && *p <= '9')
 1656                         continue;
 1657                 if (*p == '-' && i == 2) {
 1658                         ip--;
 1659                         i--;
 1660                         continue;
 1661                 }
 1662         return 1;
 1663         }
 1664 
 1665     return 0;
 1666 }
 1667 
 1668 
 1669 /*
 1670  * remove one path level from a given path
 1671  * if we are already at root level return emtpy string
 1672  */
 1673 gchar *get_reducedpath(gchar *dir, gchar *out) {
 1674 gchar *p;
 1675 gchar tmp[MAXLINE];
 1676 
 1677     /* trailing slash? remove it first */
 1678     strncpy(tmp, dir, MAXLINE);
 1679     if (tmp[strlen(tmp)-1] == '/') {
 1680         tmp[strlen(tmp)-1] = '\0';
 1681     }
 1682 
 1683     /* look for last slash */
 1684     p = rindex(tmp,'/');
 1685     if (p) {
 1686         /* cut it  */
 1687         *p = '\0';
 1688     }
 1689     strncpy(out, tmp, MAXLINE);
 1690 
 1691     return out;
 1692 }
 1693 
 1694 
 1695 /*
 1696  * convert latin1 charset to UTF8
 1697  * if convert fails, return FALSE
 1698  */
 1699 gint charset_convert_to_utf8(gchar *str, gchar *out) {
 1700 gchar *convtmp;
 1701 
 1702     /* hardcode latin -> utf-8 conversation */
 1703     convtmp = g_convert(str, -1, "utf-8", CHARSET_CONVERT_FROM, NULL, NULL, NULL);
 1704     if (convtmp) {
 1705         strncpy(out, convtmp, MAXLINE);
 1706         g_free(convtmp);
 1707         return(TRUE);
 1708     }
 1709     return(FALSE);
 1710 }
 1711 
 1712 
 1713 /*
 1714  * convert UTF8 charset to latin1
 1715  * if convert fails, return FALSE
 1716  */
 1717 gint charset_convert_to_latin1(gchar *str, gchar *out) {
 1718 gchar *convtmp;
 1719 
 1720     /* hardcode latin -> utf-8 conversation */
 1721     convtmp = g_convert(str, -1, CHARSET_CONVERT_FROM, "utf-8", NULL, NULL, NULL);
 1722     if (convtmp) {
 1723         strncpy(out, convtmp, MAXLINE);
 1724         g_free(convtmp);
 1725         return(TRUE);
 1726     }
 1727     return(FALSE);
 1728 }
 1729