/************************************************************************
qDecoder - Web Application Interface for C/C++ http://www.qDecoder.org
Copyright (C) 2001 The qDecoder Project.
Copyright (C) 1999,2000 Hongik Internet, Inc.
Copyright (C) 1998 Nobreak Technologies, Inc.
Copyright (C) 1996,1997 Seung-young Kim.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright Disclaimer:
Hongik Internet, Inc., hereby disclaims all copyright interest.
President, Christopher Roh, 6 April 2000
Nobreak Technologies, Inc., hereby disclaims all copyright interest.
President, Yoon Cho, 6 April 2000
Seung-young Kim, hereby disclaims all copyright interest.
Author, Seung-young Kim, 6 April 2000
************************************************************************/
#include "qDecoder.h"
#include "qInternal.h"
/**********************************************
** Usage : qPrintf(mode, format, arg);
** Return: Sucess number of output bytes, Fail EOF.
** Do : Print message like printf.
** Mode : see qPuts()
**********************************************/
int qPrintf(int mode, char *format, ...) {
char buf[1024*10];
int status;
va_list arglist;
va_start(arglist, format);
if((status = vsprintf(buf, format, arglist)) == EOF) return status;
if(strlen(buf) + 1 > sizeof(buf))qError("qPrintf(): Message is too long or invalid.");
qPuts(mode, buf);
return status;
}
/**********************************************
** Usage : qPuts(mode, string pointer);
** Do : print HTML link as multi mode.
** Mode 0 : Same as printf()
** Mode 1 : Print HTML TAG
** Mode 2 : Mode 1 + Auto Link
** Mode 3 : Mode 2 + Auto Link to _top frame
** Mode 4 : Waste HTML TAG
** Mode 5 : Mode 4 + Auto Link
** Mode 6 : Mode 5 + Auto Link to _top frame
**
** Mode 10 :Mode 0 + Convert
** Mode 11 : Print HTML TAG + Convert
** Mode 12 : Mode 11 + Auto Link
** Mode 13 : Mode 12 + Auto Link to _top frame
** Mode 14 : Waste HTML TAG + Convert
** Mode 15 : Mode 14 + Auto Link
** Mode 16 : Mode 15 + Auto Link to _top frame
**
** Convert : " " -> " "
** " " -> " "
** " " -> " "
** "\n" -> "
\n"
** "\r\n" -> "
\n"
**
** You can use 1x mode, to wrap long lines with no
tag.
** Note) It modify argument string.
**********************************************/
void qPuts(int mode, char *buf) {
if(buf == NULL) return;
if(mode == 0) printf("%s", buf);
else if(mode == 10) {
int i;
for(i = 0; buf[i] != '\0'; i++) {
switch(buf[i]) {
case ' ' : {
if((i > 0) && (buf[i - 1] == ' ')) printf(" ");
else printf(" ");
break;
}
case '\r' : {
break;
}
case '\n' : {
printf("
\n");
break;
}
default : {
printf("%c", buf[i]);
break;
}
}
}
}
else {
char *ptr, retstop, lastretstop, *target, *token;
int printhtml, autolink, convert, linkflag, ignoreflag;
/* set defaults, mode 2*/
printhtml = 1;
autolink = 1;
target = "_top";
convert = 0;
switch(mode) {
case 1 : {printhtml = 1, autolink = 0, target = ""; convert = 0; break;}
case 2 : {printhtml = 1, autolink = 1, target = ""; convert = 0; break;}
case 3 : {printhtml = 1, autolink = 1, target = "_top"; convert = 0; break;}
case 4 : {printhtml = 0, autolink = 0, target = ""; convert = 0; break;}
case 5 : {printhtml = 0, autolink = 1, target = ""; convert = 0; break;}
case 6 : {printhtml = 0, autolink = 1, target = "_top"; convert = 0; break;}
case 11 : {printhtml = 1, autolink = 0, target = ""; convert = 1; break;}
case 12 : {printhtml = 1, autolink = 1, target = ""; convert = 1; break;}
case 13 : {printhtml = 1, autolink = 1, target = "_top"; convert = 1; break;}
case 14 : {printhtml = 0, autolink = 0, target = ""; convert = 1; break;}
case 15 : {printhtml = 0, autolink = 1, target = ""; convert = 1; break;}
case 16 : {printhtml = 0, autolink = 1, target = "_top"; convert = 1; break;}
default: {qError("_autolink(): Invalid Mode (%d).", mode); break;}
}
token = " `(){}[]<>\"',\r\n";
lastretstop = '0'; /* any character except space */
ptr = _strtok2(buf, token, &retstop);
for(linkflag = ignoreflag = 0; ptr != NULL;) {
/* auto link */
if(ignoreflag == 0) {
if(autolink == 1) {
if(!strncmp(ptr, "http://", 7)) linkflag = 1;
else if(!strncmp(ptr, "https://", 8)) linkflag = 1;
else if(!strncmp(ptr, "ftp://", 6)) linkflag = 1;
else if(!strncmp(ptr, "telnet://", 9)) linkflag = 1;
else if(!strncmp(ptr, "news:", 5)) linkflag = 1;
else if(!strncmp(ptr, "mailto:", 7)) linkflag = 1;
else if(qCheckEmail(ptr) == 1) linkflag = 2;
else linkflag = 0;
}
if(linkflag == 1) printf("%s", ptr, target, ptr);
else if(linkflag == 2) printf("%s", ptr, ptr);
else printf("%s", ptr);
}
/* print */
if(printhtml == 1) {
if (retstop == '<') printf("<");
else if(retstop == '>') printf(">");
else if(retstop == '\"') printf(""");
else if(retstop == '&') printf("&");
else if(retstop == ' ' && convert == 1) {
if(lastretstop == ' ' && strlen(ptr) == 0) printf(" ");
else printf(" ");
}
else if(retstop == '\r' && convert == 1); /* skip when convert == 1 */
else if(retstop == '\n' && convert == 1) printf("
\n");
else if(retstop != '\0') printf("%c", retstop);
}
else {
if (retstop == '<') ignoreflag = 1;
else if(retstop == '>') ignoreflag = 0;
else if(retstop == '\"' && ignoreflag == 0) printf(""");
else if(retstop == '&' && ignoreflag == 0) printf("&");
else if(retstop == ' ' && ignoreflag == 0 && convert == 1) {
if(lastretstop == ' ' && strlen(ptr) == 0) printf(" ");
else printf(" ");
}
else if(retstop == '\r' && ignoreflag == 0 && convert == 1); /* skip when convert == 1 */
else if(retstop == '\n' && ignoreflag == 0 && convert == 1) printf("
\n");
else if(retstop != '\0' && ignoreflag == 0) printf("%c", retstop);
}
lastretstop = retstop;
ptr = _strtok2(NULL, token, &retstop);
}
}
}
/**********************************************
** Usage : qRemoveSpace(string);
** Return: Pointer of string.
** Do : Remove space(including CR, LF) from head & tail.
**********************************************/
char *qRemoveSpace(char *str) {
int i, j;
if(!str)return NULL;
for(j = 0; str[j] == ' ' || str[j] == 9 || str[j] == '\r' || str[j] == '\n'; j++);
for(i = 0; str[j] != '\0'; i++, j++) str[i] = str[j];
for(i--; (i >= 0) && (str[i] == ' ' || str[i] == 9 || str[i] == '\r' || str[i] == '\n'); i--);
str[i+1] = '\0';
return str;
}
/**********************************************
** Usage : qStr09AZaz(string);
** Return: Valid 1, Invalid 0.
** Do : Check characters of string is in 0-9, A-Z, a-z.
**********************************************/
int qStr09AZaz(char *str) {
for(; *str; str++) {
if((*str >= '0') && (*str <= '9')) continue;
else if((*str >= 'A') && (*str <= 'Z')) continue;
else if((*str >= 'a') && (*str <= 'z')) continue;
else return 0;
}
return 1;
}
/**********************************************
** Usage : qStrupr(string);
** Return: Pointer of converted string.
** Do : Convert small character to big character.
**********************************************/
char *qStrupr(char *str) {
char *cp;
if(!str) return NULL;
for(cp = str; *cp; cp++) if(*cp >= 'a' && *cp <= 'z') *cp -= 32;
return str;
}
/**********************************************
** Usage : qStrlwr(string);
** Return: Pointer of converted string.
** Do : Convert big character to small character.
**********************************************/
char *qStrlwr(char *str) {
char *cp;
if(!str) return NULL;
for(cp = str; *cp; cp++) if(*cp >= 'A' && *cp <= 'Z') *cp += 32;
return str;
}
/**********************************************
** Usage : qStristr(big, small);
** Return: Pointer of token string located in original string, Fail NULL.
** Do : Find token with no case-censitive.
**********************************************/
char *qStristr(char *big, char *small) {
char *bigp, *smallp, *retp;
if(big == NULL || small == NULL) return 0;
if((bigp = strdup(big)) == NULL) return 0;
if((smallp = strdup(small)) == NULL) { free(bigp); return 0; }
qStrupr(bigp), qStrupr(smallp);
retp = strstr(bigp, smallp);
if(retp != NULL) retp = big + (retp - bigp);
free(bigp), free(smallp);
return retp;
}
/**********************************************
** Usage : qStricmp(char *orgstr, char *tokstr);
** Return: s1 < s2 less than 0, s1 = s2 0, s1 > s2 greater than 0.
** Do : qDecoder implementation of stricmp() because
** some systems do not support this function.
**********************************************/
int qStricmp(char *s1, char *s2) {
char *bs1, *bs2;
int result;
if(s1 == NULL || s2 == NULL) return 0;
if((bs1 = strdup(s1)) == NULL) return 0;
if((bs2 = strdup(s2)) == NULL) { free(bs1); return 0; }
qStrupr(bs1), qStrupr(bs2);
result = strcmp(bs1, bs2);
free(bs1), free(bs2);
return result;
}
/**********************************************
** Usage : qStrnicmp(s1, s2, length);
** Return: Same as strncmp().
** Do : Compare n-byte strings with no case-censitive.
**********************************************/
int qStrincmp(char *s1, char *s2, size_t len) {
char *s1p, *s2p;
int result;
if(s1 == NULL || s2 == NULL) return 0;
if((s1p = strdup(s1)) == NULL) return 0;
if((s2p = strdup(s2)) == NULL) { free(s1p); return 0; }
qStrupr(s1p), qStrupr(s2p);
result = strncmp(s1p, s2p, len);
free(s1p), free(s2p);
return result;
}
/**********************************************
** Usage : qitocomma(value);
** Return: String pointer.
** Do : Convert integer to comma string.
**
** ex) printf("Output: %s", qitocomma(1234567));
** Output: -1,234,567,000
**********************************************/
char *qitocomma(int value) {
static char str[14+1];
char buf[10+1], *strp = str, *bufp;
if(value < 0) *strp++ = '-';
sprintf(buf, "%d", abs(value));
for(bufp = buf; *bufp != '\0'; strp++, bufp++) {
*strp = *bufp;
if((strlen(bufp)) % 3 == 1 && *(bufp + 1) != '\0') *(++strp) = ',';
}
*strp = '\0';
return str;
}
/**********************************************
** Usage : qStrReplace(mode, source string, token string to replace, word);
** Return: String pointer which is new or replaced.
** Do : Replace string or tokens as word from source string
** with given mode.
**
** The mode argument has two separated character. First character
** is used to decide replacing method and can be 't' or 's'.
** The character 't' and 's' stand on [t]oken and [s]tring.
**
** When 't' is given each character of the token string(third argument)
** will be compared with source string individually. If matched one
** is found. the character will be replaced with given work.
**
** If 's' is given instead of 't'. Token string will be analyzed
** only one chunk word. So the replacement will be occured when
** the case of whole word matched.
**
** Second character is used to decide returning memory type and
** can be 'n' or 'r' which are stand on [n]ew and [r]eplace.
**
** When 'n' is given the result will be placed into new array so
** you should free the return string after using. Instead of this,
** you can also use 'r' character to modify source string directly.
** In this case, given source string should have enough space. Be
** sure that untouchable value can not be used for source string.
**
** So there are four associatable modes such like below.
**
** Mode "tn" : [t]oken replacing & putting the result into [n]ew array.
** Mode "tr" : [t]oken replacing & [r]eplace source string directly.
** Mode "sn" : [s]tring replacing & putting the result into [n]ew array.
** Mode "sr" : [s]tring replacing & [r]eplace source string directly.
**
** ex) int i;
** char srcstr[256], *retstr;
** char mode[4][2+1] = {"tn", "tr", "sn", "sr"};
**
** for(i = 0; i < 4; i++) {
** strcpy(srcstr, "Welcome to the qDecoder project.");
** printf("before %s : srcstr = %s\n", mode[i], srcstr);
**
** retstr = qStrReplace(mode[i], srcstr, "the", "_");
** printf("after %s : srcstr = %s\n", mode[i], srcstr);
** printf(" retstr = %s\n\n", retstr);
** if(mode[i][1] == 'n') free(retstr);
** }
** --[Result]--
** before tn : srcstr = Welcome to the qDecoder project.
** after tn : srcstr = Welcome to the qDecoder project.
** retstr = W_lcom_ _o ___ qD_cod_r proj_c_.
**
** before tr : srcstr = Welcome to the qDecoder project.
** after tr : srcstr = W_lcom_ _o ___ qD_cod_r proj_c_.
** retstr = W_lcom_ _o ___ qD_cod_r proj_c_.
**
** before sn : srcstr = Welcome to the qDecoder project.
** after sn : srcstr = Welcome to the qDecoder project.
** retstr = Welcome to _ qDecoder project.
**
** before sr : srcstr = Welcome to the qDecoder project.
** after sr : srcstr = Welcome to _ qDecoder project.
** retstr = Welcome to _ qDecoder project.
**********************************************/
char *qStrReplace(char *mode, char *srcstr, char *tokstr, char *word) {
char method, memuse;
int maxstrlen, tokstrlen;
char *newstr, *newp, *srcp, *tokenp, *retp;
/* initialize pointers to avoid compile warnings */
newstr = newp = srcp = tokenp = retp = NULL;
if(strlen(mode) != 2) qError("qStrReplace(): Unknown mode \"%s\".", mode);
method = mode[0], memuse = mode[1];
/* Put replaced string into malloced 'newstr' */
if(method == 't') { /* Token replace */
maxstrlen = strlen(srcstr) * strlen(word);
newstr = (char *)malloc(maxstrlen + 1);
for(srcp = srcstr, newp = newstr; *srcp; srcp++) {
for(tokenp = tokstr; *tokenp; tokenp++) {
if(*srcp == *tokenp) {
char *wordp;
for(wordp = word; *wordp; wordp++) *newp++ = *wordp;
break;
}
}
if(!*tokenp) *newp++ = *srcp;
}
*newp = '\0';
}
else if(method == 's') { /* String replace */
if(strlen(word) > strlen(tokstr))
maxstrlen
= ((strlen(srcstr) / strlen(tokstr)) * strlen(word))
+ (strlen(srcstr)
% strlen(tokstr));
else maxstrlen = strlen(srcstr);
newstr = (char *)malloc(maxstrlen + 1);
tokstrlen = strlen(tokstr);
for(srcp = srcstr, newp = newstr; *srcp; srcp++) {
if(!strncmp(srcp, tokstr, tokstrlen)) {
char *wordp;
for(wordp = word; *wordp; wordp++) *newp++ = *wordp;
srcp += tokstrlen - 1;
}
else *newp++ = *srcp;
}
*newp = '\0';
}
else qError("qStrReplace(): Unknown mode \"%s\".", mode);
/* Decide whether newing the memory or replacing into exist one */
if(memuse == 'n') retp = newstr;
else if(memuse == 'r') {
strcpy(srcstr, newstr);
free(newstr);
retp = srcstr;
}
else qError("qReplaceToken(): Unknown mode \"%s\".", mode);
return retp;
}