+/*
+ * Copyright (c) 1987-2011 by the citadel.org team
+ *
+ * This program is open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
#include "sysdep.h"
#include <ctype.h>
#include <errno.h>
const char *aptr, *eiptr;
char *bptr, *eptr;
long len;
+ int IsUtf8Sequence;
if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
return -1;
return -1;
bptr = Target->buf + Target->BufUsed;
- eptr = Target->buf + Target->BufSize - 3; /* our biggest unit to put in... */
+ eptr = Target->buf + Target->BufSize - 7; /* our biggest unit to put in... */
while (aptr < eiptr){
if(bptr >= eptr) {
IncreaseBuf(Target, 1, -1);
- eptr = Target->buf + Target->BufSize - 3;
+ eptr = Target->buf + Target->BufSize - 7; /* our biggest unit to put in... */
bptr = Target->buf + Target->BufUsed;
}
- if (*aptr == '"') {
+ switch (*aptr) {
+ case '\n':
+ memcpy(bptr, HKEY("\\n"));
+ bptr += 2;
+ Target->BufUsed += 2;
+ break;
+ case '\r':
+ memcpy(bptr, HKEY("\\r"));
+ bptr += 2;
+ Target->BufUsed += 2;
+ break;
+ case '"':
*bptr = '\\';
bptr ++;
*bptr = '"';
bptr ++;
Target->BufUsed += 2;
- } else if (*aptr == '\\') {
+ break;
+ case '\\':
+ if ((*(aptr + 1) == 'u') &&
+ isxdigit(*(aptr + 2)) &&
+ isxdigit(*(aptr + 3)) &&
+ isxdigit(*(aptr + 4)) &&
+ isxdigit(*(aptr + 5)))
+ { /* oh, a unicode escaper. let it pass through. */
+ memcpy(bptr, aptr, 6);
+ aptr += 5;
+ bptr +=6;
+ Target->BufUsed += 6;
+ }
+ else
+ {
+ *bptr = '\\';
+ bptr ++;
+ *bptr = '\\';
+ bptr ++;
+ Target->BufUsed += 2;
+ }
+ break;
+ case '\b':
*bptr = '\\';
bptr ++;
+ *bptr = 'b';
+ bptr ++;
+ Target->BufUsed += 2;
+ break;
+ case '\f':
*bptr = '\\';
bptr ++;
+ *bptr = 'f';
+ bptr ++;
Target->BufUsed += 2;
- }
- else{
- *bptr = *aptr;
- bptr++;
- Target->BufUsed ++;
+ break;
+ case '\t':
+ *bptr = '\\';
+ bptr ++;
+ *bptr = 't';
+ bptr ++;
+ Target->BufUsed += 2;
+ break;
+ default:
+ IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(aptr, eiptr);
+ while (IsUtf8Sequence > 0){
+ *bptr = *aptr;
+ Target->BufUsed ++;
+ if (--IsUtf8Sequence)
+ aptr++;
+ bptr++;
+ }
}
aptr ++;
}
bptr ++;
Target->BufUsed ++;
break;
- case 32:
-//) && (nbsp == 1)) {
- memcpy(bptr, HKEY(" "));
- bptr += 6;
- Target->BufUsed += 6;
- break;
case '\n':
switch (nolinebreaks) {
case 1:
bptr ++;
Target->BufUsed += 2;
break;
+ case 32:
+ if (nbsp == 1) {
+ memcpy(bptr, HKEY(" "));
+ bptr += 6;
+ Target->BufUsed += 6;
+ break;
+ }
default:
IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(aptr, eiptr);
while (IsUtf8Sequence > 0){
(ch > 126) ||
(ch == 61) ||
(ch == '=') ||
+ (ch == '?') ||
+ (ch == '_') ||
(ch == '[') ||
(ch == ']') )
{
(*target)->BufUsed += 3;
}
else {
- (*target)->buf[(*target)->BufUsed] = ch;
+ if (ch == ' ')
+ (*target)->buf[(*target)->BufUsed] = '_';
+ else
+ (*target)->buf[(*target)->BufUsed] = ch;
(*target)->BufUsed++;
}
}
*/
static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *CharE)
{
- int n = 1;
- char test = (1<<7);
+ int n = 0;
+ unsigned char test = (1<<7);
- if ((*CharS & 0xC0) == 0)
+ if ((*CharS & 0xC0) != 0xC0)
return 1;
- while ((n < 8) && ((test & *CharS) != 0)) {
- test = test << 1;
+ while ((n < 8) &&
+ ((test & ((unsigned char)*CharS)) != 0))
+ {
+ test = test >> 1;
n ++;
}
if ((n > 6) || ((CharE - CharS) < n))
static inline int Ctdl_IsUtf8SequenceStart(const char Char)
{
/** 11??.???? indicates an UTF8 Sequence. */
- return ((Char & 0xC0) != 0);
+ return ((Char & 0xC0) == 0xC0);
}
/**
optr --;
if ((*(ptr - 1) != '\r') && (*(ptr - 1) != '\n')) {
LineBuf->BufUsed = optr - LineBuf->buf;
- *optr = '\0';
+ *optr = '\0';
+ if ((FB->ReadWritePointer != NULL) &&
+ (FB->ReadWritePointer != FB->Buf->buf))
+ {
+ /* Ok, the client application read all the data
+ it was interested in so far. Since there is more to read,
+ we now shrink the buffer, and move the rest over.
+ */
+ StrBufCutLeft(FB->Buf,
+ FB->ReadWritePointer - FB->Buf->buf);
+ FB->ReadWritePointer = FB->Buf->buf;
+ }
return eMustReadMore;
}
}
return eReadSuccess;
}
+long IOBufferStrLength(IOBuffer *FB)
+{
+ if (FB->ReadWritePointer == NULL)
+ return StrLength(FB->Buf);
+
+ return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf);
+}
+
/*******************************************************************************
* File I/O; Prefer buffered read since its faster! *
*******************************************************************************/