744 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: indep.c,v 1.32 2003/02/05 16:45:08 ukai Exp $ */
 | 
						|
#include "fm.h"
 | 
						|
#include <stdio.h>
 | 
						|
#include <pwd.h>
 | 
						|
#include <sys/param.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include "indep.h"
 | 
						|
#include "Str.h"
 | 
						|
#include "gc.h"
 | 
						|
#include "myctype.h"
 | 
						|
#include "entity.h"
 | 
						|
 | 
						|
unsigned char QUOTE_MAP[0x100] = {
 | 
						|
    /* NUL SOH STX ETX EOT ENQ ACK BEL  BS  HT  LF  VT  FF  CR  SO  SI */
 | 
						|
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
 | 
						|
    /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN  EM SUB ESC  FS  GS  RS  US */
 | 
						|
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
 | 
						|
    /* SPC   !   "   #   $   %   &   '   (   )   *   +   ,   -   .   / */
 | 
						|
    24, 72, 76, 40, 8, 40, 41, 72, 72, 72, 72, 40, 72, 8, 0, 64,
 | 
						|
    /*   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ? */
 | 
						|
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 72, 74, 72, 75, 40,
 | 
						|
    /*   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O */
 | 
						|
    72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
    /*   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _ */
 | 
						|
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 72, 72, 72, 0,
 | 
						|
    /*   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o */
 | 
						|
    72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
    /*   p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ DEL */
 | 
						|
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 72, 72, 72, 24,
 | 
						|
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
 | 
						|
};
 | 
						|
 | 
						|
char *HTML_QUOTE_MAP[] = {
 | 
						|
    NULL,
 | 
						|
    "&",
 | 
						|
    "<",
 | 
						|
    ">",
 | 
						|
    """,
 | 
						|
    NULL,
 | 
						|
    NULL,
 | 
						|
    NULL,
 | 
						|
};
 | 
						|
 | 
						|
clen_t
 | 
						|
strtoclen(const char *s)
 | 
						|
{
 | 
						|
#ifdef HAVE_STRTOLL
 | 
						|
    return strtoll(s, NULL, 10);
 | 
						|
#elif defined(HAVE_STRTOQ)
 | 
						|
    return strtoq(s, NULL, 10);
 | 
						|
#elif defined(HAVE_ATOLL)
 | 
						|
    return atoll(s);
 | 
						|
#elif defined(HAVE_ATOQ)
 | 
						|
    return atoq(s);
 | 
						|
#else
 | 
						|
    return atoi(s);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef HAVE_BCOPY
 | 
						|
void
 | 
						|
bcopy(const void *src, void *dest, int len)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    if (src == dest)
 | 
						|
	return;
 | 
						|
    if (src < dest) {
 | 
						|
	for (i = len - 1; i >= 0; i--)
 | 
						|
	    ((char *)dest)[i] = ((const char *)src)[i];
 | 
						|
    }
 | 
						|
    else {			/* src > dest */
 | 
						|
	for (i = 0; i < len; i++)
 | 
						|
	    ((char *)dest)[i] = ((const char *)src)[i];
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
bzero(void *ptr, int len)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char *p = ptr;
 | 
						|
    for (i = 0; i < len; i++)
 | 
						|
	*(p++) = 0;
 | 
						|
}
 | 
						|
#endif				/* not HAVE_BCOPY */
 | 
						|
 | 
						|
char *
 | 
						|
allocStr(const char *s, int len)
 | 
						|
{
 | 
						|
    char *ptr;
 | 
						|
 | 
						|
    if (s == NULL)
 | 
						|
	return NULL;
 | 
						|
    if (len < 0)
 | 
						|
	len = strlen(s);
 | 
						|
    ptr = NewAtom_N(char, len + 1);
 | 
						|
    if (ptr == NULL) {
 | 
						|
	fprintf(stderr, "fm: Can't allocate string. Give me more memory!\n");
 | 
						|
	exit(-1);
 | 
						|
    }
 | 
						|
    bcopy(s, ptr, len);
 | 
						|
    ptr[len] = '\0';
 | 
						|
    return ptr;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
strCmp(const void *s1, const void *s2)
 | 
						|
{
 | 
						|
    return strcmp(*(const char **)s1, *(const char **)s2);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
currentdir()
 | 
						|
{
 | 
						|
    char *path;
 | 
						|
#ifdef HAVE_GETCWD
 | 
						|
#ifdef MAXPATHLEN
 | 
						|
    path = NewAtom_N(char, MAXPATHLEN);
 | 
						|
    getcwd(path, MAXPATHLEN);
 | 
						|
#else
 | 
						|
    path = getcwd(NULL, 0);
 | 
						|
#endif
 | 
						|
#else				/* not HAVE_GETCWD */
 | 
						|
#ifdef HAVE_GETWD
 | 
						|
    path = NewAtom_N(char, 1024);
 | 
						|
    getwd(path);
 | 
						|
#else				/* not HAVE_GETWD */
 | 
						|
    FILE *f;
 | 
						|
    char *p;
 | 
						|
    path = NewAtom_N(char, 1024);
 | 
						|
    f = popen("pwd", "r");
 | 
						|
    fgets(path, 1024, f);
 | 
						|
    pclose(f);
 | 
						|
    for (p = path; *p; p++)
 | 
						|
	if (*p == '\n') {
 | 
						|
	    *p = '\0';
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
#endif				/* not HAVE_GETWD */
 | 
						|
#endif				/* not HAVE_GETCWD */
 | 
						|
    return path;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
cleanupName(char *name)
 | 
						|
{
 | 
						|
    char *buf, *p, *q;
 | 
						|
 | 
						|
    buf = allocStr(name, -1);
 | 
						|
    p = buf;
 | 
						|
    q = name;
 | 
						|
    while (*q != '\0') {
 | 
						|
	if (strncmp(p, "/../", 4) == 0) {	/* foo/bar/../FOO */
 | 
						|
	    if (p - 2 == buf && strncmp(p - 2, "..", 2) == 0) {
 | 
						|
		/* ../../       */
 | 
						|
		p += 3;
 | 
						|
		q += 3;
 | 
						|
	    }
 | 
						|
	    else if (p - 3 >= buf && strncmp(p - 3, "/..", 3) == 0) {
 | 
						|
		/* ../../../    */
 | 
						|
		p += 3;
 | 
						|
		q += 3;
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		while (p != buf && *--p != '/') ;	/* ->foo/FOO */
 | 
						|
		*p = '\0';
 | 
						|
		q += 3;
 | 
						|
		strcat(buf, q);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else if (strcmp(p, "/..") == 0) {	/* foo/bar/..   */
 | 
						|
	    if (p - 2 == buf && strncmp(p - 2, "..", 2) == 0) {
 | 
						|
		/* ../..        */
 | 
						|
	    }
 | 
						|
	    else if (p - 3 >= buf && strncmp(p - 3, "/..", 3) == 0) {
 | 
						|
		/* ../../..     */
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		while (p != buf && *--p != '/') ;	/* ->foo/ */
 | 
						|
		*++p = '\0';
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	else if (strncmp(p, "/./", 3) == 0) {	/* foo/./bar */
 | 
						|
	    *p = '\0';		/* -> foo/bar           */
 | 
						|
	    q += 2;
 | 
						|
	    strcat(buf, q);
 | 
						|
	}
 | 
						|
	else if (strcmp(p, "/.") == 0) {	/* foo/. */
 | 
						|
	    *++p = '\0';	/* -> foo/              */
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	else if (strncmp(p, "//", 2) == 0) {	/* foo//bar */
 | 
						|
	    /* -> foo/bar           */
 | 
						|
	    *p = '\0';
 | 
						|
	    q++;
 | 
						|
	    strcat(buf, q);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    p++;
 | 
						|
	    q++;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return buf;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
expandPath(char *name)
 | 
						|
{
 | 
						|
    char *p;
 | 
						|
    struct passwd *passent, *getpwnam(const char *);
 | 
						|
    Str extpath = NULL;
 | 
						|
 | 
						|
    if (name == NULL)
 | 
						|
	return NULL;
 | 
						|
    p = name;
 | 
						|
    if (*p == '~') {
 | 
						|
	p++;
 | 
						|
	if (IS_ALPHA(*p)) {
 | 
						|
	    char *q = strchr(p, '/');
 | 
						|
	    if (q) {		/* ~user/dir... */
 | 
						|
		passent = getpwnam(allocStr(p, q - p));
 | 
						|
		p = q;
 | 
						|
	    }
 | 
						|
	    else {		/* ~user */
 | 
						|
		passent = getpwnam(p);
 | 
						|
		p = "";
 | 
						|
	    }
 | 
						|
	    if (!passent)
 | 
						|
		goto rest;
 | 
						|
	    extpath = Strnew_charp(passent->pw_dir);
 | 
						|
	}
 | 
						|
	else if (*p == '/' || *p == '\0') {	/* ~/dir... or ~ */
 | 
						|
	    extpath = Strnew_charp(getenv("HOME"));
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    goto rest;
 | 
						|
	if (Strcmp_charp(extpath, "/") == 0 && *p == '/')
 | 
						|
	    p++;
 | 
						|
	Strcat_charp(extpath, p);
 | 
						|
	return extpath->ptr;
 | 
						|
    }
 | 
						|
  rest:
 | 
						|
    return name;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef HAVE_STRCHR
 | 
						|
char *
 | 
						|
strchr(const char *s, int c)
 | 
						|
{
 | 
						|
    while (*s) {
 | 
						|
	if ((unsigned char)*s == c)
 | 
						|
	    return (char *)s;
 | 
						|
	s++;
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
#endif				/* not HAVE_STRCHR */
 | 
						|
 | 
						|
#ifndef HAVE_STRCASECMP
 | 
						|
int
 | 
						|
strcasecmp(const char *s1, const char *s2)
 | 
						|
{
 | 
						|
    int x;
 | 
						|
    while (*s1) {
 | 
						|
	x = TOLOWER(*s1) - TOLOWER(*s2);
 | 
						|
	if (x != 0)
 | 
						|
	    return x;
 | 
						|
	s1++;
 | 
						|
	s2++;
 | 
						|
    }
 | 
						|
    return -TOLOWER(*s2);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
strncasecmp(const char *s1, const char *s2, size_t n)
 | 
						|
{
 | 
						|
    int x;
 | 
						|
    while (*s1 && n) {
 | 
						|
	x = TOLOWER(*s1) - TOLOWER(*s2);
 | 
						|
	if (x != 0)
 | 
						|
	    return x;
 | 
						|
	s1++;
 | 
						|
	s2++;
 | 
						|
	n--;
 | 
						|
    }
 | 
						|
    return n ? -TOLOWER(*s2) : 0;
 | 
						|
}
 | 
						|
#endif				/* not HAVE_STRCASECMP */
 | 
						|
 | 
						|
#ifndef HAVE_STRCASESTR
 | 
						|
/* string search using the simplest algorithm */
 | 
						|
char *
 | 
						|
strcasestr(const char *s1, const char *s2)
 | 
						|
{
 | 
						|
    int len1, len2;
 | 
						|
    if (s2 == NULL)
 | 
						|
	return (char *)s1;
 | 
						|
    if (*s2 == '\0')
 | 
						|
	return (char *)s1;
 | 
						|
    len1 = strlen(s1);
 | 
						|
    len2 = strlen(s2);
 | 
						|
    while (*s1 && len1 >= len2) {
 | 
						|
	if (strncasecmp(s1, s2, len2) == 0)
 | 
						|
	    return (char *)s1;
 | 
						|
	s1++;
 | 
						|
	len1--;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
strcasematch(char *s1, char *s2)
 | 
						|
{
 | 
						|
    int x;
 | 
						|
    while (*s1) {
 | 
						|
	if (*s2 == '\0')
 | 
						|
	    return 1;
 | 
						|
	x = TOLOWER(*s1) - TOLOWER(*s2);
 | 
						|
	if (x != 0)
 | 
						|
	    break;
 | 
						|
	s1++;
 | 
						|
	s2++;
 | 
						|
    }
 | 
						|
    return (*s2 == '\0');
 | 
						|
}
 | 
						|
 | 
						|
/* search multiple strings */
 | 
						|
int
 | 
						|
strcasemstr(char *str, char *srch[], char **ret_ptr)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    while (*str) {
 | 
						|
	for (i = 0; srch[i]; i++) {
 | 
						|
	    if (strcasematch(str, srch[i])) {
 | 
						|
		if (ret_ptr)
 | 
						|
		    *ret_ptr = str;
 | 
						|
		return i;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	str++;
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
remove_space(char *str)
 | 
						|
{
 | 
						|
    char *p, *q;
 | 
						|
 | 
						|
    for (p = str; *p && IS_SPACE(*p); p++) ;
 | 
						|
    for (q = p; *q; q++) ;
 | 
						|
    for (; q > p && IS_SPACE(*(q - 1)); q--) ;
 | 
						|
    if (*q != '\0')
 | 
						|
	return Strnew_charp_n(p, q - p)->ptr;
 | 
						|
    return p;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
non_null(char *s)
 | 
						|
{
 | 
						|
    if (s == NULL)
 | 
						|
	return FALSE;
 | 
						|
    while (*s) {
 | 
						|
	if (!IS_SPACE(*s))
 | 
						|
	    return TRUE;
 | 
						|
	s++;
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
cleanup_line(Str s, int mode)
 | 
						|
{
 | 
						|
    if (s->length >= 2 &&
 | 
						|
	s->ptr[s->length - 2] == '\r' && s->ptr[s->length - 1] == '\n') {
 | 
						|
	Strshrink(s, 2);
 | 
						|
	Strcat_char(s, '\n');
 | 
						|
    }
 | 
						|
    else if (Strlastchar(s) == '\r')
 | 
						|
	s->ptr[s->length - 1] = '\n';
 | 
						|
    else if (Strlastchar(s) != '\n')
 | 
						|
	Strcat_char(s, '\n');
 | 
						|
    if (mode != PAGER_MODE) {
 | 
						|
	int i;
 | 
						|
	for (i = 0; i < s->length; i++) {
 | 
						|
	    if (s->ptr[i] == '\0')
 | 
						|
		s->ptr[i] = ' ';
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
getescapechar(char **str)
 | 
						|
{
 | 
						|
    int dummy = -1;
 | 
						|
    char *p = *str, *q;
 | 
						|
    int strict_entity = TRUE;
 | 
						|
 | 
						|
    if (*p == '&')
 | 
						|
	p++;
 | 
						|
    if (*p == '#') {
 | 
						|
	p++;
 | 
						|
	if (*p == 'x' || *p == 'X') {
 | 
						|
	    p++;
 | 
						|
	    if (!IS_XDIGIT(*p)) {
 | 
						|
		*str = p;
 | 
						|
		return -1;
 | 
						|
	    }
 | 
						|
	    for (dummy = GET_MYCDIGIT(*p), p++; IS_XDIGIT(*p); p++)
 | 
						|
		dummy = dummy * 0x10 + GET_MYCDIGIT(*p);
 | 
						|
	    if (*p == ';')
 | 
						|
		p++;
 | 
						|
	    *str = p;
 | 
						|
	    return dummy;
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (!IS_DIGIT(*p)) {
 | 
						|
		*str = p;
 | 
						|
		return -1;
 | 
						|
	    }
 | 
						|
	    for (dummy = GET_MYCDIGIT(*p), p++; IS_DIGIT(*p); p++)
 | 
						|
		dummy = dummy * 10 + GET_MYCDIGIT(*p);
 | 
						|
	    if (*p == ';')
 | 
						|
		p++;
 | 
						|
	    *str = p;
 | 
						|
	    return dummy;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (!IS_ALPHA(*p)) {
 | 
						|
	*str = p;
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    q = p;
 | 
						|
    for (p++; IS_ALNUM(*p); p++) ;
 | 
						|
    q = allocStr(q, p - q);
 | 
						|
    if (strcasestr("lt gt amp quot nbsp", q) && *p != '=') {
 | 
						|
	/* a character entity MUST be terminated with ";". However,
 | 
						|
	 * there's MANY web pages which uses < , > or something
 | 
						|
	 * like them as <, >, etc. Therefore, we treat the most
 | 
						|
	 * popular character entities (including &#xxxx;) without
 | 
						|
	 * the last ";" as character entities. If the trailing character
 | 
						|
	 * is "=", it must be a part of query in an URL. So <=, >=, etc.
 | 
						|
	 * are not regarded as character entities.
 | 
						|
	 */
 | 
						|
	strict_entity = FALSE;
 | 
						|
    }
 | 
						|
    if (*p == ';')
 | 
						|
	p++;
 | 
						|
    else if (strict_entity) {
 | 
						|
	*str = p;
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    *str = p;
 | 
						|
    return getHash_si(&entity, q, -1);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
getescapecmd(char **s)
 | 
						|
{
 | 
						|
    char *save = *s;
 | 
						|
    Str tmp;
 | 
						|
    int ch = getescapechar(s);
 | 
						|
 | 
						|
    if (ch >= 0)
 | 
						|
	return conv_entity(ch);
 | 
						|
 | 
						|
    if (*save != '&')
 | 
						|
	tmp = Strnew_charp("&");
 | 
						|
    else
 | 
						|
	tmp = Strnew();
 | 
						|
    Strcat_charp_n(tmp, save, *s - save);
 | 
						|
    return tmp->ptr;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
html_quote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p, *q;
 | 
						|
 | 
						|
    for (p = str; *p; p++) {
 | 
						|
	q = html_quote_char(*p);
 | 
						|
	if (q) {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
	    Strcat_charp(tmp, q);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
html_unquote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p, *q;
 | 
						|
 | 
						|
    for (p = str; *p;) {
 | 
						|
	if (*p == '&') {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
	    q = getescapecmd(&p);
 | 
						|
	    Strcat_charp(tmp, q);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	    p++;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
static char xdigit[0x10] = "0123456789ABCDEF";
 | 
						|
 | 
						|
#define url_unquote_char(pstr) \
 | 
						|
  ((IS_XDIGIT((*(pstr))[1]) && IS_XDIGIT((*(pstr))[2])) ? \
 | 
						|
    (*(pstr) += 3, (GET_MYCDIGIT((*(pstr))[-2]) << 4) | GET_MYCDIGIT((*(pstr))[-1])) : \
 | 
						|
   -1)
 | 
						|
 | 
						|
char *
 | 
						|
url_quote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p;
 | 
						|
 | 
						|
    for (p = str; *p; p++) {
 | 
						|
	if (is_url_quote(*p)) {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
	    Strcat_char(tmp, '%');
 | 
						|
	    Strcat_char(tmp, xdigit[((unsigned char)*p >> 4) & 0xF]);
 | 
						|
	    Strcat_char(tmp, xdigit[(unsigned char)*p & 0xF]);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
file_quote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p;
 | 
						|
    char buf[4];
 | 
						|
 | 
						|
    for (p = str; *p; p++) {
 | 
						|
	if (is_file_quote(*p)) {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
	    sprintf(buf, "%%%02X", (unsigned char)*p);
 | 
						|
	    Strcat_charp(tmp, buf);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
file_unquote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p, *q;
 | 
						|
    int c;
 | 
						|
 | 
						|
    for (p = str; *p;) {
 | 
						|
	if (*p == '%') {
 | 
						|
	    q = p;
 | 
						|
	    c = url_unquote_char(&q);
 | 
						|
	    if (c >= 0) {
 | 
						|
		if (tmp == NULL)
 | 
						|
		    tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
		if (c != '\0' && c != '\n' && c != '\r')
 | 
						|
		    Strcat_char(tmp, (char)c);
 | 
						|
		p = q;
 | 
						|
		continue;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (tmp)
 | 
						|
	    Strcat_char(tmp, *p);
 | 
						|
	p++;
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
Str
 | 
						|
Str_form_quote(Str x)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p = x->ptr, *ep = x->ptr + x->length;
 | 
						|
    char buf[4];
 | 
						|
 | 
						|
    for (; p < ep; p++) {
 | 
						|
	if (*p == ' ') {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | 
						|
	    Strcat_char(tmp, '+');
 | 
						|
	}
 | 
						|
	else if (is_url_unsafe(*p)) {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | 
						|
	    sprintf(buf, "%%%02X", (unsigned char)*p);
 | 
						|
	    Strcat_charp(tmp, buf);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp;
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Str
 | 
						|
Str_url_unquote(Str x, int is_form, int safe)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p = x->ptr, *ep = x->ptr + x->length, *q;
 | 
						|
    int c;
 | 
						|
 | 
						|
    for (; p < ep;) {
 | 
						|
	if (is_form && *p == '+') {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | 
						|
	    Strcat_char(tmp, ' ');
 | 
						|
	    p++;
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	else if (*p == '%') {
 | 
						|
	    q = p;
 | 
						|
	    c = url_unquote_char(&q);
 | 
						|
	    if (c >= 0 && (!safe || !IS_ASCII(c) || !is_file_quote(c))) {
 | 
						|
		if (tmp == NULL)
 | 
						|
		    tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | 
						|
		Strcat_char(tmp, (char)c);
 | 
						|
		p = q;
 | 
						|
		continue;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (tmp)
 | 
						|
	    Strcat_char(tmp, *p);
 | 
						|
	p++;
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp;
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
shell_quote(char *str)
 | 
						|
{
 | 
						|
    Str tmp = NULL;
 | 
						|
    char *p;
 | 
						|
 | 
						|
    for (p = str; *p; p++) {
 | 
						|
	if (is_shell_unsafe(*p)) {
 | 
						|
	    if (tmp == NULL)
 | 
						|
		tmp = Strnew_charp_n(str, (int)(p - str));
 | 
						|
	    Strcat_char(tmp, '\\');
 | 
						|
	    Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tmp)
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (tmp)
 | 
						|
	return tmp->ptr;
 | 
						|
    return str;
 | 
						|
}
 | 
						|
 | 
						|
static char *
 | 
						|
w3m_dir(const char *name, char *dft)
 | 
						|
{
 | 
						|
#ifdef USE_PATH_ENVVAR
 | 
						|
    char *value = getenv(name);
 | 
						|
    return value ? value : dft;
 | 
						|
#else
 | 
						|
    return dft;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
w3m_auxbin_dir()
 | 
						|
{
 | 
						|
    return w3m_dir("W3M_AUXBIN_DIR", AUXBIN_DIR);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
w3m_lib_dir()
 | 
						|
{
 | 
						|
    return w3m_dir("W3M_LIB_DIR", LIB_DIR);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
w3m_etc_dir()
 | 
						|
{
 | 
						|
    return w3m_dir("W3M_ETC_DIR", ETC_DIR);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
w3m_help_dir()
 | 
						|
{
 | 
						|
    return w3m_dir("W3M_HELP_DIR", HELP_DIR);
 | 
						|
}
 | 
						|
/* Local Variables:    */
 | 
						|
/* c-basic-offset: 4   */
 | 
						|
/* tab-width: 8        */
 | 
						|
/* End:                */
 |