/* -*- c -*-
* File: pstring.h
* Author: Igor Vlasenko <vlasenko@imath.kiev.ua>
* Created: Fri Jul 1 20:11:51 2005
*
* $Id$
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "pbuffer.h"
#include "pstring.h"
static
PSTRING
lowercase_pstring (pbuffer* pBuffer ,PSTRING pstring) {
const size_t size=pstring.endnext-pstring.begin;
char* buf=pbuffer_resize(pBuffer, size+1);
char* inbuf=buf;
const char* i=pstring.begin;
PSTRING retval;
while (i<pstring.endnext) {
*inbuf++=tolower((unsigned char) *i++);
}
*inbuf=0;
retval.begin=buf;
retval.endnext=buf+size;
return retval;
}
/*
static
void
lowercase_pstring_inplace (PSTRING pstring) {
char* i=pstring.begin;
while (i<pstring.endnext) {
*i=tolower(*i);
i++;
}
}
*/
static
PSTRING
uppercase_pstring (pbuffer* pBuffer ,PSTRING pstring) {
const size_t size=pstring.endnext-pstring.begin;
char* buf=pbuffer_resize(pBuffer, size+1);
char* inbuf=buf;
const char* i=pstring.begin;
PSTRING retval;
while (i<pstring.endnext) {
*inbuf++=toupper((unsigned char) *i++);
}
*inbuf=0;
retval.begin=buf;
retval.endnext=buf+size;
return retval;
}
static
int
is_pstring_true (PSTRING s) {
const size_t len = s.endnext-s.begin;
if (s.begin == NULL || 0==len) return 0;
if (1==len) {
if (*(s.begin)=='0') return 0; else return 1;
} else if (3==len) {
if ('0'==*(s.begin) && '.'==*(s.begin+1) && '0'==*(s.begin+2)) return 0; else return 1;
} else return 1;
}
#define MAX_ESCAPE_SEQ sizeof(""")
static
PSTRING
htmlencode_pstring (pbuffer* StrBuffer, PSTRING pstring) {
char* buf=pbuffer_resize(StrBuffer, pstring.endnext-pstring.begin+1+MAX_ESCAPE_SEQ);
const char* curpos=pstring.begin;
size_t offset=0;
size_t buflen=pbuffer_size(StrBuffer);
PSTRING retval;
while (curpos<pstring.endnext) {
unsigned char curchar=*curpos++;
int bufdelta=1;
if (offset>=buflen-MAX_ESCAPE_SEQ) {
buf=pbuffer_resize(StrBuffer, 2*(offset+MAX_ESCAPE_SEQ));
buflen=pbuffer_size(StrBuffer);
}
switch (curchar) {
/* straight from the CGI.pm bible. (HTML::Template) */
case '&' : bufdelta=5; strncpy(buf+offset, "&", bufdelta);break;
case '"' : bufdelta=6; strncpy(buf+offset, """,bufdelta);break;
case '>' : bufdelta=4; strncpy(buf+offset, ">", bufdelta);break;
case '<' : bufdelta=4; strncpy(buf+offset, "<", bufdelta);break;
case '\'': bufdelta=5; strncpy(buf+offset, "'", bufdelta);break;
default: *(buf+offset)=curchar;
}
offset+=bufdelta;
}
retval.begin=buf;
retval.endnext=buf+offset;
return retval;
}
static
PSTRING
jsencode_pstring (pbuffer* StrBuffer, PSTRING pstring) {
char* buf=pbuffer_resize(StrBuffer, pstring.endnext-pstring.begin+1+MAX_ESCAPE_SEQ);
const char* curpos=pstring.begin;
size_t offset=0;
size_t buflen=pbuffer_size(StrBuffer);
PSTRING retval;
while (curpos<pstring.endnext) {
unsigned char curchar=*curpos++;
int bufdelta=1;
if (offset>=buflen-MAX_ESCAPE_SEQ) {
buf=pbuffer_resize(StrBuffer, 2*(offset+MAX_ESCAPE_SEQ));
buflen=pbuffer_size(StrBuffer);
}
switch (curchar) {
case '\\' : bufdelta=6; strncpy(buf+offset, "\\u005c", bufdelta);break;
case '"' : bufdelta=6; strncpy(buf+offset, "\\u0022",bufdelta);break;
case '\'' : bufdelta=6; strncpy(buf+offset, "\\u0027",bufdelta);break;
case '\n' : bufdelta=6; strncpy(buf+offset, "\\u000a",bufdelta);break;
case '\r' : bufdelta=6; strncpy(buf+offset, "\\u000d",bufdelta);break;
case '>' : bufdelta=6; strncpy(buf+offset, "\\u003e;", bufdelta);break;
case '<' : bufdelta=6; strncpy(buf+offset, "\\u003c;", bufdelta);break;
case '&' : bufdelta=6; strncpy(buf+offset, "\\u0026;", bufdelta);break;
case '=' : bufdelta=6; strncpy(buf+offset, "\\u003d;", bufdelta);break;
case '-' : bufdelta=6; strncpy(buf+offset, "\\u002d;", bufdelta);break;
case ';' : bufdelta=6; strncpy(buf+offset, "\\u003b;", bufdelta);break;
case '+' : bufdelta=6; strncpy(buf+offset, "\\u002b;", bufdelta);break;
default: *(buf+offset)=curchar;
}
offset+=bufdelta;
}
retval.begin=buf;
retval.endnext=buf+offset;
return retval;
}
static
PSTRING
urlencode_pstring (pbuffer* StrBuffer, PSTRING pstring) {
char* buf=pbuffer_resize(StrBuffer, pstring.endnext-pstring.begin+1+MAX_ESCAPE_SEQ);
const char* curpos=pstring.begin;
size_t offset=0;
size_t buflen=pbuffer_size(StrBuffer);
PSTRING retval;
while (curpos<pstring.endnext) {
unsigned char curchar=*curpos++;
int bufdelta=1;
if (offset>=buflen-MAX_ESCAPE_SEQ) {
buf=pbuffer_resize(StrBuffer, 2*(offset+MAX_ESCAPE_SEQ));
buflen=pbuffer_size(StrBuffer);
}
/*
* # do the translation (RFC 2396 ^uric)
* s!([^a-zA-Z0-9_.\-])!sprintf('%%%02X', $_)
* note that \- above means -, not '\\' + '-', and '\\' should not be urlencoded.
* https://rt.cpan.org/Ticket/Display.html?id=109255
*/
if ((curchar>='a' && curchar<='z') ||
(curchar>='A' && curchar<='Z') ||
(curchar>='0' && curchar<='9') ||
curchar=='_' || curchar=='.' || curchar=='-'
)
*(buf+offset)=curchar;
else {
bufdelta=3; sprintf(buf+offset,"%%%.2X",(int) curchar);
}
offset+=bufdelta;
}
retval.begin=buf;
retval.endnext=buf+offset;
return retval;
}
static
PSTRING
escape_pstring (pbuffer* strBuffer, PSTRING pstring, const int escapeopt) {
switch (escapeopt) {
case HTML_TEMPLATE_OPT_ESCAPE_HTML:
return htmlencode_pstring(strBuffer, pstring);
case HTML_TEMPLATE_OPT_ESCAPE_JS:
return jsencode_pstring(strBuffer, pstring);
case HTML_TEMPLATE_OPT_ESCAPE_URL:
return urlencode_pstring(strBuffer, pstring);
default : return pstring;
}
}