gwenhywfar
4.3.3
|
00001 /*************************************************************************** 00002 begin : Sat Jun 28 2003 00003 copyright : (C) 2003 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Lesser General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public * 00019 * License along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 * * 00023 ***************************************************************************/ 00024 00025 #ifdef HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #define DISABLE_DEBUGLOG 00030 00031 00032 #include "text.h" 00033 #include <stdlib.h> 00034 #include <assert.h> 00035 #include <string.h> 00036 #include <errno.h> 00037 #include <ctype.h> 00038 #ifdef HAVE_LOCALE_H 00039 # include <locale.h> 00040 #endif 00041 00042 #ifndef ICONV_CONST 00043 # define ICONV_CONST 00044 #endif 00045 00046 #ifdef HAVE_ICONV_H 00047 # include <iconv.h> 00048 #endif 00049 00050 00051 #include <gwenhywfar/gwenhywfarapi.h> 00052 #include <gwenhywfar/debug.h> 00053 #include <gwenhywfar/stringlist.h> 00054 00055 00056 00057 typedef struct { 00058 int character; 00059 const char *replace; 00060 } GWEN_TEXT_ESCAPE_ENTRY; 00061 00062 static const GWEN_TEXT_ESCAPE_ENTRY gwen_text__xml_escape_chars[]= { 00063 {'&', "&"}, 00064 {'<', "<"}, 00065 {'>', ">"}, 00066 {'\'', "'"}, 00067 {'\"', """}, 00068 {0, 0} 00069 }; 00070 00071 00072 00073 char *GWEN_Text_GetWord(const char *src, 00074 const char *delims, 00075 char *buffer, 00076 unsigned int maxsize, 00077 uint32_t flags, 00078 const char **next){ 00079 unsigned int size; 00080 int lastWasBlank; 00081 int lastBlankPos; 00082 int insideQuotes; 00083 int lastWasEscape; 00084 00085 assert(maxsize); 00086 00087 /* skip leading blanks, if wanted */ 00088 if (flags & GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS) { 00089 while(*src && (unsigned char)(*src)<33) 00090 src++; 00091 } 00092 00093 /* get word */ 00094 size=0; 00095 lastWasBlank=0; 00096 lastBlankPos=-1; 00097 lastWasEscape=0; 00098 insideQuotes=0; 00099 00100 if (*src=='"') { 00101 insideQuotes=1; 00102 if (flags & GWEN_TEXT_FLAGS_DEL_QUOTES) 00103 src++; 00104 } 00105 00106 while(*src && size<(maxsize-1)) { 00107 if (lastWasEscape) { 00108 buffer[size]=*src; 00109 size++; 00110 lastWasEscape=0; 00111 lastWasBlank=0; 00112 lastBlankPos=-1; 00113 } 00114 else { 00115 if (*src=='\\' && (flags & GWEN_TEXT_FLAGS_CHECK_BACKSLASH)) { 00116 lastWasEscape=1; 00117 lastWasBlank=0; 00118 lastBlankPos=-1; 00119 } 00120 else { 00121 if (!insideQuotes && strchr(delims, *src)!=0) 00122 break; 00123 if (*src=='"') { 00124 if (insideQuotes) { 00125 insideQuotes=0; 00126 src++; 00127 break; 00128 } 00129 else { 00130 DBG_DEBUG(GWEN_LOGDOMAIN, 00131 "Found a closing \" without an opening one " 00132 "(consider using a backslash to escape)"); 00133 return 0; 00134 } 00135 } 00136 00137 00138 if (insideQuotes || 00139 !lastWasBlank || 00140 (lastWasBlank && 00141 !(flags & GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS))) { 00142 /* only copy if last char was NOT blank or 00143 * last was blank but the caller does not want to have multiple 00144 * blanks removed */ 00145 buffer[size]=*src; 00146 size++; 00147 } 00148 /* remember next loop whether this char was a blank */ 00149 if (isspace((int)((unsigned char)*src)) && !lastWasEscape) { 00150 lastWasBlank=1; 00151 lastBlankPos=size; 00152 } 00153 else { 00154 lastWasBlank=0; 00155 lastBlankPos=-1; 00156 } 00157 } /* if this is not a backslash */ 00158 } /* !lastWasEscape */ 00159 /* advance source pointer */ 00160 src++; 00161 } /* while */ 00162 00163 /* add trailing null to correctly terminate the buffer */ 00164 buffer[size]=0; 00165 00166 if (insideQuotes) { 00167 DBG_DEBUG(GWEN_LOGDOMAIN, "Missing \" after word"); 00168 return 0; 00169 } 00170 /* check whether the source string was correctly terminated */ 00171 if (flags & GWEN_TEXT_FLAGS_NEED_DELIMITER) { 00172 if (*src) { 00173 if (strchr(delims, *src)==0) { 00174 DBG_ERROR(GWEN_LOGDOMAIN, "No delimiter found within specified length"); 00175 return 0; 00176 } 00177 } 00178 else { 00179 if (!(flags & GWEN_TEXT_FLAGS_NULL_IS_DELIMITER)) { 00180 DBG_ERROR(GWEN_LOGDOMAIN, "String ends without delimiter"); 00181 return 0; 00182 } 00183 } 00184 } 00185 00186 /* remove trailing blanks, if wanted */ 00187 if (flags & GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS) { 00188 if (lastBlankPos!=-1) 00189 buffer[lastBlankPos]=0; 00190 } 00191 00192 *next=src; 00193 return buffer; 00194 } 00195 00196 00197 00198 int GWEN_Text_GetWordToBuffer(const char *src, 00199 const char *delims, 00200 GWEN_BUFFER *buf, 00201 uint32_t flags, 00202 const char **next){ 00203 const char *savedSrc=src; 00204 int lastWasBlank; 00205 int lastBlankPos; 00206 int insideQuotes; 00207 int lastWasEscape; 00208 00209 /* skip leading blanks, if wanted */ 00210 if (flags & GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS) { 00211 while(*src && (unsigned char)(*src)<33) { 00212 if (strchr(delims, *src)) { 00213 *next=src; 00214 return 0; 00215 } 00216 src++; 00217 } 00218 } 00219 00220 /* get word */ 00221 lastWasBlank=0; 00222 lastBlankPos=-1; 00223 lastWasEscape=0; 00224 insideQuotes=0; 00225 00226 if (*src=='"') { 00227 insideQuotes=1; 00228 if (flags & GWEN_TEXT_FLAGS_DEL_QUOTES) 00229 src++; 00230 } 00231 00232 while(*src) { 00233 if (lastWasEscape) { 00234 GWEN_Buffer_AppendByte(buf, *src); 00235 lastWasEscape=0; 00236 lastWasBlank=0; 00237 lastBlankPos=-1; 00238 } 00239 else { 00240 if (*src=='\\' && (flags & GWEN_TEXT_FLAGS_CHECK_BACKSLASH)) { 00241 lastWasEscape=1; 00242 lastWasBlank=0; 00243 lastBlankPos=-1; 00244 } 00245 else { 00246 if (!insideQuotes && strchr(delims, *src)!=0) 00247 break; 00248 if (*src=='"') { 00249 if (insideQuotes) { 00250 insideQuotes=0; 00251 src++; 00252 break; 00253 } 00254 else { 00255 DBG_ERROR(GWEN_LOGDOMAIN, 00256 "Found a closing \" without an opening one " 00257 "(consider using a backslash to escape)"); 00258 return -1; 00259 } 00260 } 00261 00262 00263 if (insideQuotes || 00264 !lastWasBlank || 00265 (lastWasBlank && 00266 !(flags & GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS))) { 00267 /* only copy if last char was NOT blank or 00268 * last was blank but the caller does not want to have multiple 00269 * blanks removed */ 00270 GWEN_Buffer_AppendByte(buf, *src); 00271 } 00272 /* remember next loop whether this char was a blank */ 00273 00274 if (!lastWasEscape && *((unsigned char*)src)<33) { 00275 lastWasBlank=1; 00276 lastBlankPos=GWEN_Buffer_GetPos(buf); 00277 } 00278 else { 00279 lastWasBlank=0; 00280 lastBlankPos=-1; 00281 } 00282 } /* if this is not a backslash */ 00283 } /* !lastWasEscape */ 00284 /* advance source pointer */ 00285 src++; 00286 } /* while */ 00287 00288 if (insideQuotes) { 00289 DBG_ERROR(GWEN_LOGDOMAIN, "Missing \" after word (at %d: [%s])", (int)(src-savedSrc), savedSrc); 00290 return -1; 00291 } 00292 /* check whether the source string was correctly terminated */ 00293 if (flags & GWEN_TEXT_FLAGS_NEED_DELIMITER) { 00294 if (*src) { 00295 if (strchr(delims, *src)==0) { 00296 DBG_ERROR(GWEN_LOGDOMAIN, "No delimiter found within specified length"); 00297 return -1; 00298 } 00299 } 00300 else { 00301 if (!(flags & GWEN_TEXT_FLAGS_NULL_IS_DELIMITER)) { 00302 DBG_ERROR(GWEN_LOGDOMAIN, "String ends without delimiter"); 00303 return -1; 00304 } 00305 } 00306 } 00307 00308 /* remove trailing blanks, if wanted */ 00309 if (flags & GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS) { 00310 if (lastBlankPos!=-1) 00311 GWEN_Buffer_Crop(buf, 0, lastBlankPos); 00312 } 00313 00314 *next=src; 00315 return 0; 00316 } 00317 00318 00319 00320 char *GWEN_Text_Escape(const char *src, 00321 char *buffer, 00322 unsigned int maxsize) { 00323 unsigned int size; 00324 00325 size=0; 00326 while(*src) { 00327 unsigned char x; 00328 00329 x=(unsigned char)*src; 00330 if (!( 00331 (x>='A' && x<='Z') || 00332 (x>='a' && x<='z') || 00333 (x>='0' && x<='9'))) { 00334 unsigned char c; 00335 00336 if ((maxsize-1)<size+3) { 00337 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00338 return 0; 00339 } 00340 buffer[size++]='%'; 00341 c=(((unsigned char)(*src))>>4)&0xf; 00342 if (c>9) 00343 c+=7; 00344 c+='0'; 00345 buffer[size++]=c; 00346 c=((unsigned char)(*src))&0xf; 00347 if (c>9) 00348 c+=7; 00349 c+='0'; 00350 buffer[size++]=c; 00351 } 00352 else { 00353 if (size<(maxsize-1)) 00354 buffer[size++]=*src; 00355 else { 00356 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00357 return 0; 00358 } 00359 } 00360 00361 src++; 00362 } /* while */ 00363 00364 buffer[size]=0; 00365 return buffer; 00366 } 00367 00368 00369 00370 char *GWEN_Text_EscapeTolerant(const char *src, 00371 char *buffer, 00372 unsigned int maxsize) { 00373 unsigned int size; 00374 00375 size=0; 00376 while(*src) { 00377 unsigned char x; 00378 00379 x=(unsigned char)*src; 00380 if (!( 00381 (x>='A' && x<='Z') || 00382 (x>='a' && x<='z') || 00383 (x>='0' && x<='9') || 00384 x==' ' || 00385 x=='.' || 00386 x==',' || 00387 x=='.' || 00388 x=='*' || 00389 x=='?' 00390 )) { 00391 unsigned char c; 00392 00393 if ((maxsize-1)<size+3) { 00394 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00395 return 0; 00396 } 00397 buffer[size++]='%'; 00398 c=(((unsigned char)(*src))>>4)&0xf; 00399 if (c>9) 00400 c+=7; 00401 c+='0'; 00402 buffer[size++]=c; 00403 c=((unsigned char)(*src))&0xf; 00404 if (c>9) 00405 c+=7; 00406 c+='0'; 00407 buffer[size++]=c; 00408 } 00409 else { 00410 if (size<(maxsize-1)) 00411 buffer[size++]=*src; 00412 else { 00413 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00414 return 0; 00415 } 00416 } 00417 00418 src++; 00419 } /* while */ 00420 00421 buffer[size]=0; 00422 return buffer; 00423 } 00424 00425 00426 00427 char *GWEN_Text_UnescapeN(const char *src, 00428 unsigned int srclen, 00429 char *buffer, 00430 unsigned int maxsize){ 00431 unsigned int size; 00432 00433 size=0; 00434 00435 while(*src && srclen>0) { 00436 unsigned char x; 00437 00438 x=(unsigned char)*src; 00439 if ( 00440 (x>='A' && x<='Z') || 00441 (x>='a' && x<='z') || 00442 (x>='0' && x<='9')) { 00443 if (size<(maxsize-1)) 00444 buffer[size++]=*src; 00445 else { 00446 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00447 return 0; 00448 } 00449 } 00450 else { 00451 if (*src=='%') { 00452 unsigned char d1, d2; 00453 unsigned char c; 00454 00455 if (srclen<3) { 00456 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (EOLN met)"); 00457 return 0; 00458 } 00459 /* skip '%' */ 00460 src++; 00461 if (!(*src) || !isxdigit((int)*src)) { 00462 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)"); 00463 return 0; 00464 } 00465 /* read first digit */ 00466 d1=(unsigned char)(toupper(*src)); 00467 00468 /* get second digit */ 00469 src++; 00470 if (!(*src) || !isxdigit((int)*src)) { 00471 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)"); 00472 return 0; 00473 } 00474 d2=(unsigned char)(toupper(*src)); 00475 /* compute character */ 00476 d1-='0'; 00477 if (d1>9) 00478 d1-=7; 00479 c=(d1<<4)&0xf0; 00480 d2-='0'; 00481 if (d2>9) 00482 d2-=7; 00483 c+=(d2&0xf); 00484 /* store character */ 00485 if (size<(maxsize-1)) 00486 buffer[size++]=(char)c; 00487 else { 00488 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00489 return 0; 00490 } 00491 srclen-=2; 00492 } 00493 else { 00494 DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum " 00495 "characters in escaped string (\"%s\")", 00496 src); 00497 return 0; 00498 } 00499 } 00500 srclen--; 00501 src++; 00502 } /* while */ 00503 00504 buffer[size]=0; 00505 return buffer; 00506 } 00507 00508 00509 00510 char *GWEN_Text_Unescape(const char *src, 00511 char *buffer, 00512 unsigned int maxsize){ 00513 unsigned int srclen; 00514 00515 srclen=strlen(src); 00516 return GWEN_Text_UnescapeN(src, srclen, buffer, maxsize); 00517 } 00518 00519 00520 00521 char *GWEN_Text_UnescapeTolerantN(const char *src, 00522 unsigned int srclen, 00523 char *buffer, 00524 unsigned int maxsize){ 00525 unsigned int size; 00526 00527 size=0; 00528 00529 while(*src && srclen>0) { 00530 unsigned char x; 00531 00532 x=(unsigned char)*src; 00533 if ( 00534 (x>='A' && x<='Z') || 00535 (x>='a' && x<='z') || 00536 (x>='0' && x<='9') || 00537 x==' ' || 00538 x=='.' || 00539 x==',' || 00540 x=='.' || 00541 x=='*' || 00542 x=='?' 00543 ) { 00544 if (size<(maxsize-1)) 00545 buffer[size++]=*src; 00546 else { 00547 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00548 return 0; 00549 } 00550 } 00551 else { 00552 if (*src=='%') { 00553 unsigned char d1, d2; 00554 unsigned char c; 00555 00556 if (srclen<3) { 00557 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (EOLN met)"); 00558 return 0; 00559 } 00560 /* skip '%' */ 00561 src++; 00562 if (!(*src) || !isxdigit((int)*src)) { 00563 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)"); 00564 return 0; 00565 } 00566 /* read first digit */ 00567 d1=(unsigned char)(toupper(*src)); 00568 00569 /* get second digit */ 00570 src++; 00571 if (!(*src) || !isxdigit((int)*src)) { 00572 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)"); 00573 return 0; 00574 } 00575 d2=(unsigned char)(toupper(*src)); 00576 /* compute character */ 00577 d1-='0'; 00578 if (d1>9) 00579 d1-=7; 00580 c=(d1<<4)&0xf0; 00581 d2-='0'; 00582 if (d2>9) 00583 d2-=7; 00584 c+=(d2&0xf); 00585 /* store character */ 00586 if (size<(maxsize-1)) 00587 buffer[size++]=(char)c; 00588 else { 00589 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00590 return 0; 00591 } 00592 srclen-=2; 00593 } 00594 else { 00595 DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum " 00596 "characters in escaped string (\"%s\")", 00597 src); 00598 return 0; 00599 } 00600 } 00601 srclen--; 00602 src++; 00603 } /* while */ 00604 00605 buffer[size]=0; 00606 return buffer; 00607 } 00608 00609 00610 00611 char *GWEN_Text_UnescapeTolerant(const char *src, 00612 char *buffer, 00613 unsigned int maxsize){ 00614 unsigned int srclen; 00615 00616 srclen=strlen(src); 00617 return GWEN_Text_UnescapeTolerantN(src, srclen, buffer, maxsize); 00618 } 00619 00620 00621 00622 char *GWEN_Text_ToHex(const char *src, unsigned l, 00623 char *buffer, unsigned int maxsize) { 00624 unsigned int pos; 00625 unsigned int size; 00626 00627 if ((l*2)+1 > maxsize) { 00628 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00629 return 0; 00630 } 00631 00632 pos=0; 00633 size=0; 00634 while(pos<l) { 00635 unsigned char c; 00636 00637 c=(((unsigned char)(src[pos]))>>4)&0xf; 00638 if (c>9) 00639 c+=7; 00640 c+='0'; 00641 buffer[size++]=c; 00642 c=((unsigned char)(src[pos]))&0xf; 00643 if (c>9) 00644 c+=7; 00645 c+='0'; 00646 buffer[size++]=c; 00647 pos++; 00648 } 00649 buffer[size]=0; 00650 return buffer; 00651 } 00652 00653 00654 00655 char *GWEN_Text_ToHexGrouped(const char *src, 00656 unsigned l, 00657 char *buffer, 00658 unsigned maxsize, 00659 unsigned int groupsize, 00660 char delimiter, 00661 int skipLeadingZeroes) { 00662 unsigned int pos; 00663 unsigned int size; 00664 unsigned int j; 00665 00666 j=0; 00667 00668 pos=0; 00669 size=0; 00670 j=0; 00671 while(pos<l) { 00672 unsigned char c; 00673 int skipThis; 00674 00675 skipThis=0; 00676 c=(((unsigned char)(src[pos]))>>4)&0xf; 00677 if (skipLeadingZeroes) { 00678 if (c==0) 00679 skipThis=1; 00680 else 00681 skipLeadingZeroes=0; 00682 } 00683 if (c>9) 00684 c+=7; 00685 c+='0'; 00686 if (!skipThis) { 00687 if (size+1>=maxsize) { 00688 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00689 return 0; 00690 } 00691 buffer[size++]=c; 00692 j++; 00693 if (j==groupsize) { 00694 if (size+1>=maxsize) { 00695 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00696 return 0; 00697 } 00698 buffer[size++]=delimiter; 00699 j=0; 00700 } 00701 } 00702 00703 skipThis=0; 00704 c=((unsigned char)(src[pos]))&0xf; 00705 if (skipLeadingZeroes) { 00706 if (c==0 && pos+1<l) 00707 skipThis=1; 00708 else 00709 skipLeadingZeroes=0; 00710 } 00711 if (c>9) 00712 c+=7; 00713 c+='0'; 00714 if (size+1>=maxsize) { 00715 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00716 return 0; 00717 } 00718 if (!skipThis) { 00719 buffer[size++]=c; 00720 j++; 00721 if (j==groupsize) { 00722 if (pos+1<l) { 00723 if (size+1>=maxsize) { 00724 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00725 return 0; 00726 } 00727 buffer[size++]=delimiter; 00728 } 00729 j=0; 00730 } 00731 } 00732 pos++; 00733 } 00734 buffer[size]=0; 00735 return buffer; 00736 } 00737 00738 00739 00740 int GWEN_Text_ToHexBuffer(const char *src, unsigned l, 00741 GWEN_BUFFER *buf, 00742 unsigned int groupsize, 00743 char delimiter, 00744 int skipLeadingZeroes){ 00745 unsigned int pos; 00746 unsigned int size; 00747 unsigned int j; 00748 00749 j=0; 00750 00751 pos=0; 00752 size=0; 00753 j=0; 00754 while(pos<l) { 00755 unsigned char c; 00756 int skipThis; 00757 00758 skipThis=0; 00759 c=(((unsigned char)(src[pos]))>>4)&0xf; 00760 if (skipLeadingZeroes) { 00761 if (c==0) 00762 skipThis=1; 00763 else 00764 skipLeadingZeroes=0; 00765 } 00766 if (c>9) 00767 c+=7; 00768 c+='0'; 00769 if (!skipThis) { 00770 if (GWEN_Buffer_AppendByte(buf, c)) { 00771 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00772 return -1; 00773 } 00774 j++; 00775 if (groupsize && j==groupsize) { 00776 if (GWEN_Buffer_AppendByte(buf, delimiter)) { 00777 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00778 return -1; 00779 } 00780 j=0; 00781 } 00782 } 00783 00784 skipThis=0; 00785 c=((unsigned char)(src[pos]))&0xf; 00786 if (skipLeadingZeroes) { 00787 if (c==0 && pos+1<l) 00788 skipThis=1; 00789 else 00790 skipLeadingZeroes=0; 00791 } 00792 if (c>9) 00793 c+=7; 00794 c+='0'; 00795 if (!skipThis) { 00796 if (GWEN_Buffer_AppendByte(buf, c)) { 00797 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00798 return -1; 00799 } 00800 j++; 00801 if (groupsize && j==groupsize) { 00802 if (pos+1<l) { 00803 if (GWEN_Buffer_AppendByte(buf, delimiter)) { 00804 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00805 return -1; 00806 } 00807 } 00808 j=0; 00809 } 00810 } 00811 pos++; 00812 } 00813 return 0; 00814 } 00815 00816 00817 00818 int GWEN_Text_FromHex(const char *src, char *buffer, unsigned maxsize){ 00819 unsigned int pos; 00820 unsigned int size; 00821 00822 pos=0; 00823 size=0; 00824 while(*src) { 00825 unsigned char d1, d2; 00826 unsigned char c; 00827 00828 /* read first digit */ 00829 if (!isxdigit((int)*src)) { 00830 DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in hex string"); 00831 return -1; 00832 } 00833 d1=(unsigned char)(toupper(*src)); 00834 00835 /* get second digit */ 00836 src++; 00837 if (!(*src) || !isxdigit((int)*src)) { 00838 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete hex byte (only 1 digit)"); 00839 return -1; 00840 } 00841 d2=(unsigned char)(toupper(*src)); 00842 src++; 00843 00844 /* compute character */ 00845 d1-='0'; 00846 if (d1>9) 00847 d1-=7; 00848 c=(d1<<4)&0xf0; 00849 d2-='0'; 00850 if (d2>9) 00851 d2-=7; 00852 c+=(d2&0xf); 00853 /* store character */ 00854 if (size<(maxsize)) 00855 buffer[size++]=(char)c; 00856 else { 00857 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (maxsize=%d)", maxsize); 00858 return -1; 00859 } 00860 } /* while */ 00861 00862 return size; 00863 } 00864 00865 00866 00867 int GWEN_Text_FromHexBuffer(const char *src, GWEN_BUFFER *buf) { 00868 while(*src) { 00869 unsigned char d1, d2; 00870 unsigned char c; 00871 00872 /* read first digit */ 00873 if (isspace((int)*src)) { 00874 src++; 00875 } 00876 else { 00877 if (!isxdigit((int)*src)) { 00878 DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in hex string"); 00879 return -1; 00880 } 00881 d1=(unsigned char)(toupper(*src)); 00882 00883 /* get second digit */ 00884 src++; 00885 if (!(*src) || !isxdigit((int)*src)) { 00886 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete hex byte (only 1 digit)"); 00887 return -1; 00888 } 00889 d2=(unsigned char)(toupper(*src)); 00890 src++; 00891 00892 /* compute character */ 00893 d1-='0'; 00894 if (d1>9) 00895 d1-=7; 00896 c=(d1<<4)&0xf0; 00897 d2-='0'; 00898 if (d2>9) 00899 d2-=7; 00900 c+=(d2&0xf); 00901 /* store character */ 00902 GWEN_Buffer_AppendByte(buf, (char)c); 00903 } 00904 } /* while */ 00905 00906 return 0; 00907 } 00908 00909 00910 00911 int GWEN_Text_FromBcdBuffer(const char *src, GWEN_BUFFER *buf) { 00912 unsigned int l; 00913 int fakeByte; 00914 00915 l=strlen(src); 00916 fakeByte=(l%2); 00917 while(*src) { 00918 unsigned char d1, d2; 00919 unsigned char c; 00920 00921 if (fakeByte) { 00922 d1=0; 00923 fakeByte=0; 00924 } 00925 else { 00926 /* read first digit */ 00927 if (!isdigit((int)*src)) { 00928 DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in bcd string"); 00929 return -1; 00930 } 00931 d1=(unsigned char)(*src); 00932 src++; 00933 } 00934 /* get second digit */ 00935 if (!(*src) || !isxdigit((int)*src)) { 00936 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete BCD byte (only 1 digit)"); 00937 return -1; 00938 } 00939 d2=(unsigned char)(*src); 00940 src++; 00941 00942 /* compute character */ 00943 d1-='0'; 00944 c=(d1<<4)&0xf0; 00945 d2-='0'; 00946 c+=(d2&0xf); 00947 /* store character */ 00948 GWEN_Buffer_AppendByte(buf, (char)c); 00949 } /* while */ 00950 00951 return 0; 00952 } 00953 00954 00955 00956 int GWEN_Text_ToBcdBuffer(const char *src, unsigned l, 00957 GWEN_BUFFER *buf, 00958 unsigned int groupsize, 00959 char delimiter, 00960 int skipLeadingZeroes){ 00961 unsigned int pos; 00962 unsigned int size; 00963 unsigned int j; 00964 00965 j=0; 00966 00967 pos=0; 00968 size=0; 00969 j=0; 00970 while(pos<l) { 00971 unsigned char c; 00972 int skipThis; 00973 00974 skipThis=0; 00975 c=(((unsigned char)(src[pos]))>>4)&0xf; 00976 if (skipLeadingZeroes) { 00977 if (c==0) 00978 skipThis=1; 00979 else 00980 skipLeadingZeroes=0; 00981 } 00982 c+='0'; 00983 if (!skipThis) { 00984 if (GWEN_Buffer_AppendByte(buf, c)) { 00985 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00986 return -1; 00987 } 00988 j++; 00989 if (groupsize && j==groupsize) { 00990 if (GWEN_Buffer_AppendByte(buf, delimiter)) { 00991 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00992 return -1; 00993 } 00994 j=0; 00995 } 00996 } 00997 00998 skipThis=0; 00999 c=((unsigned char)(src[pos]))&0xf; 01000 if (skipLeadingZeroes) { 01001 if (c==0 && pos+1<l) 01002 skipThis=1; 01003 else 01004 skipLeadingZeroes=0; 01005 } 01006 c+='0'; 01007 if (!skipThis) { 01008 if (GWEN_Buffer_AppendByte(buf, c)) { 01009 DBG_INFO(GWEN_LOGDOMAIN, "here"); 01010 return -1; 01011 } 01012 j++; 01013 if (groupsize && j==groupsize) { 01014 if (pos+1<l) { 01015 if (GWEN_Buffer_AppendByte(buf, delimiter)) { 01016 DBG_INFO(GWEN_LOGDOMAIN, "here"); 01017 return -1; 01018 } 01019 } 01020 j=0; 01021 } 01022 } 01023 pos++; 01024 } 01025 return 0; 01026 } 01027 01028 01029 01030 int GWEN_Text_Compare(const char *s1, const char *s2, int ign) { 01031 if (s1) 01032 if (*s1==0) 01033 s1=0; 01034 if (s2) 01035 if (*s2==0) 01036 s2=0; 01037 if (!s1 && !s2) 01038 return 0; 01039 if (!s1 && s2) 01040 return 1; 01041 if (s1 && !s2) 01042 return -1; 01043 if (ign) 01044 return strcasecmp(s1, s2); 01045 else 01046 return strcmp(s1, s2); 01047 } 01048 01049 01050 01051 const char *GWEN_Text_StrCaseStr(const char *haystack, const char *needle) { 01052 while(*haystack) { 01053 while(*haystack && tolower(*haystack)!=tolower(*needle)) 01054 haystack++; 01055 if (*haystack) { 01056 const char *t; 01057 const char *s; 01058 01059 /* now haystack points to an area which begins with *needle */ 01060 t=haystack; 01061 s=needle; 01062 t++; 01063 s++; 01064 while(*t && *s && (tolower(*t)==tolower(*s))) { 01065 t++; 01066 s++; 01067 } 01068 if (*s==0) 01069 return haystack; 01070 } 01071 else 01072 /* not found */ 01073 break; 01074 /* no match here, advance haystack */ 01075 haystack++; 01076 } 01077 01078 /* not found */ 01079 return NULL; 01080 } 01081 01082 01083 01084 01085 int GWEN_Text__cmpSegment(const char *w, unsigned int *wpos, 01086 const char *p, unsigned int *ppos, 01087 int sensecase, 01088 unsigned int *matches) { 01089 char a; 01090 char b; 01091 unsigned wlength; 01092 unsigned plength; 01093 01094 unsigned int _wpos = *wpos, _ppos = *ppos, _matches = *matches; 01095 01096 a=0; 01097 b=0; 01098 wlength=strlen(w); 01099 plength=strlen(p); 01100 01101 while (_wpos<wlength && _ppos<plength) { 01102 a=w[_wpos]; 01103 b=p[_ppos]; 01104 if (b=='*') { 01105 *wpos = _wpos; 01106 *ppos = _ppos; 01107 *matches = _matches; 01108 return 1; 01109 } 01110 if (!sensecase) { 01111 a=toupper(a); 01112 b=toupper(b); 01113 } 01114 /* count matches */ 01115 if (a==b) 01116 ++_matches; 01117 if (a!=b && b!='?') { 01118 *wpos = _wpos; 01119 *ppos = _ppos; 01120 *matches = _matches; 01121 return 0; 01122 } 01123 ++_wpos; 01124 ++_ppos; 01125 } 01126 /* both at end, would be ok */ 01127 if (_wpos==wlength && _ppos==plength) { 01128 *wpos = _wpos; 01129 *ppos = _ppos; 01130 *matches = _matches; 01131 return 1; 01132 } 01133 /* word ends, pattern doesnt, would be ok if pattern is '*' here */ 01134 if (_wpos>=wlength && _ppos<plength) 01135 if (p[_ppos]=='*') { 01136 *wpos = _wpos; 01137 *ppos = _ppos; 01138 *matches = _matches; 01139 return 1; 01140 } 01141 /* otherwise no match ;-/ */ 01142 *wpos = _wpos; 01143 *ppos = _ppos; 01144 *matches = _matches; 01145 return 0; 01146 } 01147 01148 01149 01150 int GWEN_Text__findSegment(const char *w, unsigned int *wpos, 01151 const char *p, unsigned int *ppos, 01152 int sensecase, 01153 unsigned int *matches) { 01154 unsigned int lwpos, lppos, lmatches; 01155 unsigned wlength; 01156 01157 wlength=strlen(w); 01158 lwpos=*wpos; 01159 lppos=*ppos; 01160 lmatches=*matches; 01161 while(lwpos<wlength) { 01162 *ppos=lppos; 01163 *wpos=lwpos; 01164 *matches=lmatches; 01165 if (GWEN_Text__cmpSegment(w,wpos,p,ppos,sensecase,matches)) 01166 return 1; 01167 lwpos++; 01168 } 01169 return 0; 01170 } 01171 01172 01173 int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase) { 01174 unsigned int ppos; 01175 unsigned int wpos; 01176 unsigned int matches; 01177 unsigned int plength; 01178 01179 ppos=wpos=matches=0; 01180 plength=strlen(p); 01181 01182 /* compare until first occurrence of '*' */ 01183 if (!GWEN_Text__cmpSegment(w,&wpos,p,&ppos,sensecase,&matches)) { 01184 return -1; 01185 } 01186 01187 while(1) { 01188 /* if pattern ends we have done it */ 01189 if (ppos>=plength) 01190 return matches; 01191 /* skip '*' in pattern */ 01192 ppos++; 01193 /* if pattern ends behind '*' the word matches */ 01194 if (ppos>=plength) 01195 return matches; 01196 /* find next matching segment */ 01197 if (!GWEN_Text__findSegment(w,&wpos,p,&ppos,sensecase,&matches)) { 01198 return -1; 01199 } 01200 } /* while */ 01201 /* I know, we'll never get to here ;-) */ 01202 return -1; 01203 } 01204 01205 01206 01207 int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize, 01208 int fillchar){ 01209 char lbuffer[128]; 01210 unsigned int i; 01211 01212 sprintf(lbuffer,"%d", num); 01213 i=strlen(lbuffer); 01214 if (i>=bufsize) { 01215 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%d>=%d)", i, bufsize); 01216 return -1; 01217 } 01218 if (fillchar>0) { 01219 /* fill right, but first copy chars */ 01220 strcpy(buffer, lbuffer); 01221 while(i<bufsize-1) 01222 buffer[i++]=fillchar; 01223 buffer[i]=0; 01224 return bufsize; 01225 } 01226 else if (fillchar<0) { 01227 int j, k; 01228 01229 fillchar=-fillchar; 01230 j=bufsize-1-i; 01231 for (k=0; k<j; k++) 01232 buffer[k]=fillchar; 01233 buffer[k]=0; 01234 strcat(buffer, lbuffer); 01235 return bufsize; 01236 } 01237 else { 01238 /* dont fill, just copy */ 01239 strcpy(buffer, lbuffer); 01240 return i; 01241 } 01242 } 01243 01244 01245 01246 void GWEN_Text_DumpString(const char *s, unsigned int l, 01247 unsigned int insert) { 01248 unsigned int i; 01249 unsigned int j; 01250 unsigned int pos; 01251 unsigned k; 01252 01253 pos=0; 01254 for (k=0; k<insert; k++) 01255 fprintf(stderr, " "); 01256 fprintf(stderr,"String size is %d:\n",l); 01257 while(pos<l) { 01258 for (k=0; k<insert; k++) 01259 fprintf(stderr, " "); 01260 fprintf(stderr,"%04x: ",pos); 01261 j=pos+16; 01262 if (j>=l) 01263 j=l; 01264 01265 /* show hex dump */ 01266 for (i=pos; i<j; i++) { 01267 fprintf(stderr,"%02x ",(unsigned char)s[i]); 01268 } 01269 if (j-pos<16) 01270 for (i=0; i<16-(j-pos); i++) 01271 fprintf(stderr," "); 01272 /* show text */ 01273 for (i=pos; i<j; i++) { 01274 if (s[i]<32) 01275 fprintf(stderr,"."); 01276 else 01277 fprintf(stderr,"%c",s[i]); 01278 } 01279 fprintf(stderr,"\n"); 01280 pos+=16; 01281 } 01282 } 01283 01284 01285 01286 void GWEN_Text_DumpString2Buffer(const char *s, unsigned int l, 01287 GWEN_BUFFER *mbuf, 01288 unsigned int insert) { 01289 unsigned int i; 01290 unsigned int j; 01291 unsigned int pos; 01292 unsigned k; 01293 char numbuf[32]; 01294 01295 pos=0; 01296 for (k=0; k<insert; k++) 01297 GWEN_Buffer_AppendByte(mbuf, ' '); 01298 GWEN_Buffer_AppendString(mbuf,"String size is "); 01299 snprintf(numbuf, sizeof(numbuf), "%d", l); 01300 GWEN_Buffer_AppendString(mbuf, numbuf); 01301 GWEN_Buffer_AppendByte(mbuf, '\n'); 01302 while(pos<l) { 01303 for (k=0; k<insert; k++) 01304 GWEN_Buffer_AppendByte(mbuf, ' '); 01305 snprintf(numbuf, sizeof(numbuf),"%04x: ",pos); 01306 GWEN_Buffer_AppendString(mbuf, numbuf); 01307 j=pos+16; 01308 if (j>=l) 01309 j=l; 01310 01311 /* show hex dump */ 01312 for (i=pos; i<j; i++) { 01313 snprintf(numbuf, sizeof(numbuf),"%02x ", (unsigned char)s[i]); 01314 GWEN_Buffer_AppendString(mbuf, numbuf); 01315 } 01316 if (j-pos<16) 01317 for (i=0; i<16-(j-pos); i++) 01318 GWEN_Buffer_AppendString(mbuf, " "); 01319 /* show text */ 01320 for (i=pos; i<j; i++) { 01321 if (s[i]<32) 01322 GWEN_Buffer_AppendByte(mbuf, '.'); 01323 else 01324 GWEN_Buffer_AppendByte(mbuf, s[i]); 01325 } 01326 GWEN_Buffer_AppendByte(mbuf, '\n'); 01327 pos+=16; 01328 } 01329 } 01330 01331 01332 01333 01334 01335 01336 01337 int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf) { 01338 while(*src) { 01339 unsigned char x; 01340 01341 x=(unsigned char)*src; 01342 if (!( 01343 (x>='A' && x<='Z') || 01344 (x>='a' && x<='z') || 01345 (x>='0' && x<='9'))) { 01346 unsigned char c; 01347 01348 GWEN_Buffer_AppendByte(buf, '%'); 01349 c=(((unsigned char)(*src))>>4)&0xf; 01350 if (c>9) 01351 c+=7; 01352 c+='0'; 01353 GWEN_Buffer_AppendByte(buf, c); 01354 c=((unsigned char)(*src))&0xf; 01355 if (c>9) 01356 c+=7; 01357 c+='0'; 01358 GWEN_Buffer_AppendByte(buf, c); 01359 } 01360 else 01361 GWEN_Buffer_AppendByte(buf, *src); 01362 01363 src++; 01364 } /* while */ 01365 01366 return 0; 01367 } 01368 01369 01370 01371 int GWEN_Text_UnescapeToBuffer(const char *src, GWEN_BUFFER *buf) { 01372 while(*src) { 01373 unsigned char x; 01374 01375 x=(unsigned char)*src; 01376 if ( 01377 (x>='A' && x<='Z') || 01378 (x>='a' && x<='z') || 01379 (x>='0' && x<='9')) { 01380 GWEN_Buffer_AppendByte(buf, *src); 01381 } 01382 else { 01383 if (*src=='%') { 01384 unsigned char d1, d2; 01385 unsigned char c; 01386 01387 /* skip '%' */ 01388 src++; 01389 if (!(*src) || !isxdigit((int)*src)) { 01390 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)"); 01391 return 0; 01392 } 01393 /* read first digit */ 01394 d1=(unsigned char)(toupper(*src)); 01395 01396 /* get second digit */ 01397 src++; 01398 if (!(*src) || !isxdigit((int)*src)) { 01399 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)"); 01400 return 0; 01401 } 01402 d2=(unsigned char)(toupper(*src)); 01403 /* compute character */ 01404 d1-='0'; 01405 if (d1>9) 01406 d1-=7; 01407 c=(d1<<4)&0xf0; 01408 d2-='0'; 01409 if (d2>9) 01410 d2-=7; 01411 c+=(d2&0xf); 01412 /* store character */ 01413 GWEN_Buffer_AppendByte(buf, (char)c); 01414 } 01415 else { 01416 DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum " 01417 "characters in escaped string (\"%s\")", 01418 src); 01419 return -1; 01420 } 01421 } 01422 src++; 01423 } /* while */ 01424 01425 return 0; 01426 } 01427 01428 01429 01430 int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) { 01431 while(*src) { 01432 unsigned char x; 01433 01434 x=(unsigned char)*src; 01435 if (!( 01436 (x>='A' && x<='Z') || 01437 (x>='a' && x<='z') || 01438 (x>='0' && x<='9') || 01439 x==' ' || 01440 x=='.' || 01441 x==',' || 01442 x=='.' || 01443 x=='_' || 01444 x=='-' || 01445 x=='*' || 01446 x=='?' 01447 )) { 01448 unsigned char c; 01449 01450 GWEN_Buffer_AppendByte(buf, '%'); 01451 c=(((unsigned char)(*src))>>4)&0xf; 01452 if (c>9) 01453 c+=7; 01454 c+='0'; 01455 GWEN_Buffer_AppendByte(buf, c); 01456 c=((unsigned char)(*src))&0xf; 01457 if (c>9) 01458 c+=7; 01459 c+='0'; 01460 GWEN_Buffer_AppendByte(buf, c); 01461 } 01462 else 01463 GWEN_Buffer_AppendByte(buf, *src); 01464 01465 src++; 01466 } /* while */ 01467 01468 return 0; 01469 } 01470 01471 01472 01473 int GWEN_Text_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) { 01474 while(*src) { 01475 const char *srcBak; 01476 int charHandled; 01477 01478 srcBak=src; 01479 charHandled=0; 01480 if (*src=='%') { 01481 if (strlen(src)>2) { 01482 unsigned char d1, d2; 01483 unsigned char c; 01484 01485 if (isxdigit((int)src[1]) && isxdigit((int)src[2])) { 01486 /* skip '%' */ 01487 src++; 01488 /* read first digit */ 01489 d1=(unsigned char)(toupper(*src)); 01490 01491 /* get second digit */ 01492 src++; 01493 d2=(unsigned char)(toupper(*src)); 01494 /* compute character */ 01495 d1-='0'; 01496 if (d1>9) 01497 d1-=7; 01498 c=(d1<<4)&0xf0; 01499 d2-='0'; 01500 if (d2>9) 01501 d2-=7; 01502 c+=(d2&0xf); 01503 /* store character */ 01504 GWEN_Buffer_AppendByte(buf, (char)c); 01505 charHandled=1; 01506 } 01507 } 01508 } 01509 if (!charHandled) 01510 GWEN_Buffer_AppendByte(buf, *src); 01511 src++; 01512 } /* while */ 01513 01514 return 0; 01515 } 01516 01517 01518 01519 int GWEN_Text_EscapeToBufferTolerant2(GWEN_BUFFER *src, GWEN_BUFFER *buf) { 01520 while(GWEN_Buffer_GetBytesLeft(src)) { 01521 int z; 01522 unsigned char x; 01523 01524 z=GWEN_Buffer_ReadByte(src); 01525 if (z==-1) { 01526 DBG_INFO(GWEN_LOGDOMAIN, "here"); 01527 return -1; 01528 } 01529 x=(unsigned char)z; 01530 if (!( 01531 (x>='A' && x<='Z') || 01532 (x>='a' && x<='z') || 01533 (x>='0' && x<='9') || 01534 x==' ' || 01535 x=='.' || 01536 x==',' || 01537 x=='.' || 01538 x=='*' || 01539 x=='?' 01540 )) { 01541 unsigned char c; 01542 01543 GWEN_Buffer_AppendByte(buf, '%'); 01544 c=(((unsigned char)x)>>4)&0xf; 01545 if (c>9) 01546 c+=7; 01547 c+='0'; 01548 GWEN_Buffer_AppendByte(buf, c); 01549 c=((unsigned char)x)&0xf; 01550 if (c>9) 01551 c+=7; 01552 c+='0'; 01553 GWEN_Buffer_AppendByte(buf, c); 01554 } 01555 else 01556 GWEN_Buffer_AppendByte(buf, x); 01557 } /* while */ 01558 01559 return 0; 01560 } 01561 01562 01563 01564 void GWEN_Text_LogString(const char *s, unsigned int l, 01565 const char *logDomain, 01566 GWEN_LOGGER_LEVEL lv){ 01567 GWEN_BUFFER *mbuf; 01568 01569 mbuf=GWEN_Buffer_new(0, ((l*16)<1024)?1024:l*16, 0, 1); 01570 GWEN_Text_DumpString2Buffer(s, l, mbuf, 0); 01571 GWEN_Logger_Log(logDomain, lv, GWEN_Buffer_GetStart(mbuf)); 01572 GWEN_Buffer_free(mbuf); 01573 } 01574 01575 01576 01577 void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf){ 01578 const char *p; 01579 char *dst; 01580 unsigned int size; 01581 unsigned int i; 01582 int lastWasBlank; 01583 char *lastBlankPos; 01584 01585 dst=GWEN_Buffer_GetStart(buf); 01586 p=dst; 01587 size=GWEN_Buffer_GetUsedBytes(buf); 01588 lastWasBlank=0; 01589 lastBlankPos=0; 01590 01591 for (i=0; i<size; i++) { 01592 /* remember next loop whether this char was a blank */ 01593 if (isspace((int)*p)) { 01594 if (!lastWasBlank) { 01595 /* store only one blank */ 01596 lastWasBlank=1; 01597 lastBlankPos=dst; 01598 *(dst++)=*p; 01599 } 01600 } 01601 else { 01602 lastWasBlank=0; 01603 lastBlankPos=0; 01604 *(dst++)=*p; 01605 } 01606 p++; 01607 } 01608 01609 /* remove trailing blanks */ 01610 if (lastBlankPos!=0) 01611 dst=lastBlankPos; 01612 01613 size=dst-GWEN_Buffer_GetStart(buf); 01614 GWEN_Buffer_Crop(buf, 0, size); 01615 } 01616 01617 01618 01619 int GWEN_Text_DoubleToBuffer(double num, GWEN_BUFFER *buf){ 01620 char numbuf[128]; 01621 int rv; 01622 #ifdef HAVE_SETLOCALE 01623 const char *orig_locale = setlocale(LC_NUMERIC, NULL); 01624 char *currentLocale = strdup(orig_locale ? orig_locale : "C"); 01625 setlocale(LC_NUMERIC,"C"); 01626 #endif 01627 01628 rv=snprintf(numbuf, sizeof(numbuf), "%f", num); 01629 01630 #ifdef HAVE_SETLOCALE 01631 setlocale(LC_NUMERIC, currentLocale); 01632 free(currentLocale); 01633 #endif 01634 01635 if (rv<1 || rv>=sizeof(numbuf)) 01636 return -1; 01637 GWEN_Buffer_AppendString(buf, numbuf); 01638 return 0; 01639 } 01640 01641 01642 01643 int GWEN_Text_StringToDouble(const char *s, double *num){ 01644 int rv; 01645 #ifdef HAVE_SETLOCALE 01646 const char *orig_locale = setlocale(LC_NUMERIC, NULL); 01647 char *currentLocale = strdup(orig_locale ? orig_locale : "C"); 01648 setlocale(LC_NUMERIC,"C"); 01649 #endif 01650 01651 rv=sscanf(s, "%lf", num); 01652 01653 #ifdef HAVE_SETLOCALE 01654 setlocale(LC_NUMERIC, currentLocale); 01655 free(currentLocale); 01656 #endif 01657 01658 if (rv!=1) 01659 return -1; 01660 return 0; 01661 } 01662 01663 01664 01665 double GWEN_Text__CheckSimilarity(const char *s1, const char *s2, int ign){ 01666 int nboth; 01667 int nmatch; 01668 double pc; 01669 01670 nboth=strlen(s1)+strlen(s2); 01671 nmatch=0; 01672 if (ign) { 01673 while(*s1 && *s2) { 01674 const char *t; 01675 int lmatch; 01676 01677 /* find next equal in s2 */ 01678 t=s2; 01679 lmatch=0; 01680 while(*t) { 01681 if (toupper(*s1)==toupper(*t)) { 01682 lmatch=2; 01683 break; 01684 } 01685 if (isalnum((int)*s1) && isalnum((int)*t)) { 01686 lmatch=1; 01687 break; 01688 } 01689 t++; 01690 } /* while */ 01691 01692 if (lmatch) { 01693 nmatch+=lmatch; 01694 s2=t+1; 01695 } 01696 01697 s1++; 01698 } /* while */ 01699 } 01700 else { 01701 while(*s1 && *s2) { 01702 const char *t; 01703 int lmatch; 01704 01705 /* find next equal in s2 */ 01706 t=s2; 01707 lmatch=0; 01708 while(*t) { 01709 if (*s1==*t) { 01710 lmatch=2; 01711 break; 01712 } 01713 if (toupper(*s1)==toupper(*t)) { 01714 lmatch=1; 01715 break; 01716 } 01717 if (isalnum((int)*s1) && isalnum((int)*t)) { 01718 lmatch=1; 01719 break; 01720 } 01721 t++; 01722 } /* while */ 01723 01724 if (lmatch) { 01725 nmatch+=lmatch; 01726 s2=t+1; 01727 } 01728 01729 s1++; 01730 } /* while */ 01731 } 01732 01733 pc=(nmatch*100)/nboth; 01734 return pc; 01735 } 01736 01737 01738 01739 double GWEN_Text_CheckSimilarity(const char *s1, const char *s2, int ign){ 01740 double pc1, pc2; 01741 01742 pc1=GWEN_Text__CheckSimilarity(s1, s2, ign); 01743 pc2=GWEN_Text__CheckSimilarity(s2, s1, ign); 01744 if (pc2>pc1) 01745 return pc2; 01746 return pc1; 01747 } 01748 01749 01750 01751 int GWEN_Text_CountUtf8Chars(const char *s, int len) { 01752 int count; 01753 int handled; 01754 01755 if (len==0) 01756 len=strlen(s); 01757 count=0; 01758 handled=0; 01759 while(handled<len) { 01760 unsigned char c; 01761 int i; 01762 01763 c=(unsigned char)*s; 01764 if ((c & 0xfe)==0xfc) 01765 i=5; 01766 else if ((c & 0xfc)==0xf8) 01767 i=4; 01768 else if ((c & 0xf8)==0xf0) 01769 i=3; 01770 else if ((c & 0xf0)==0xe0) 01771 i=2; 01772 else if ((c & 0xe0)==0xc0) 01773 i=1; 01774 else if (c & 0x80) { 01775 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid UTF8 character at pos %d", handled); 01776 return -1; 01777 } 01778 else 01779 i=0; 01780 if (handled+i+1>len) { 01781 DBG_ERROR(GWEN_LOGDOMAIN, 01782 "Incomplete UTF8 sequence at pos %d", handled); 01783 return -1; 01784 } 01785 s++; 01786 if (i) { 01787 int j; 01788 01789 for (j=0; j<i; j++) { 01790 if ((((unsigned char)*s) & 0xc0)!=0xc0) { 01791 DBG_ERROR(GWEN_LOGDOMAIN, 01792 "Invalid UTF8 sequence at pos %d (rel %d of %d)", 01793 handled, j, i); 01794 } 01795 s++; 01796 } 01797 } 01798 handled+=i+1; 01799 count++; 01800 } /* while */ 01801 01802 return count; 01803 } 01804 01805 01806 01807 int GWEN_Text_UnescapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) { 01808 char *pdst; 01809 uint32_t roomLeft; 01810 uint32_t bytesAdded; 01811 01812 #define GWEN_TEXT__APPENDCHAR(chr) \ 01813 if (roomLeft<2) { \ 01814 if (bytesAdded) { \ 01815 GWEN_Buffer_IncrementPos(buf, bytesAdded); \ 01816 GWEN_Buffer_AdjustUsedBytes(buf); \ 01817 } \ 01818 GWEN_Buffer_AllocRoom(buf, 2); \ 01819 pdst=GWEN_Buffer_GetPosPointer(buf); \ 01820 roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf); \ 01821 bytesAdded=0; \ 01822 } \ 01823 *(pdst++)=(unsigned char)chr; \ 01824 *pdst=0; \ 01825 bytesAdded++; \ 01826 roomLeft-- 01827 01828 pdst=GWEN_Buffer_GetPosPointer(buf); 01829 roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf); 01830 bytesAdded=0; 01831 01832 while(*src) { 01833 unsigned char x; 01834 int match; 01835 01836 match=0; 01837 x=(unsigned char)*src; 01838 if (x=='&') { 01839 if (src[1]=='#') { 01840 unsigned char num=0; 01841 01842 src++; 01843 src++; 01844 while(*src && isdigit((int)*src)) { 01845 num*=10; 01846 num+=(*src)-'0'; 01847 src++; 01848 } 01849 src++; 01850 GWEN_TEXT__APPENDCHAR(num); 01851 } 01852 else if (strncmp(src+1, "szlig;", 6)==0) { 01853 GWEN_TEXT__APPENDCHAR(0xc3); 01854 GWEN_TEXT__APPENDCHAR(0x9f); 01855 src+=7; 01856 match=1; 01857 } 01858 else if (strncmp(src+1, "Auml;", 5)==0) { 01859 GWEN_TEXT__APPENDCHAR(0xc3); 01860 GWEN_TEXT__APPENDCHAR(0x84); 01861 src+=6; 01862 match=1; 01863 } 01864 else if (strncmp(src+1, "Ouml;", 5)==0) { 01865 GWEN_TEXT__APPENDCHAR(0xc3); 01866 GWEN_TEXT__APPENDCHAR(0x96); 01867 src+=6; 01868 match=1; 01869 } 01870 else if (strncmp(src+1, "Uuml;", 5)==0) { 01871 GWEN_TEXT__APPENDCHAR(0xc3); 01872 GWEN_TEXT__APPENDCHAR(0x9c); 01873 src+=6; 01874 match=1; 01875 } 01876 else if (strncmp(src+1, "auml;", 5)==0) { 01877 GWEN_TEXT__APPENDCHAR(0xc3); 01878 GWEN_TEXT__APPENDCHAR(0xa4); 01879 src+=6; 01880 match=1; 01881 } 01882 else if (strncmp(src+1, "ouml;", 5)==0) { 01883 GWEN_TEXT__APPENDCHAR(0xc3); 01884 GWEN_TEXT__APPENDCHAR(0xb6); 01885 src+=6; 01886 match=1; 01887 } 01888 else if (strncmp(src+1, "uuml;", 5)==0) { 01889 GWEN_TEXT__APPENDCHAR(0xc3); 01890 GWEN_TEXT__APPENDCHAR(0xbc); 01891 src+=6; 01892 match=1; 01893 } 01894 else { 01895 const GWEN_TEXT_ESCAPE_ENTRY *e; 01896 e=gwen_text__xml_escape_chars; 01897 while(e->replace) { 01898 int l; 01899 01900 l=strlen(e->replace); 01901 if (strncasecmp(src, e->replace, l)==0) { 01902 GWEN_TEXT__APPENDCHAR(e->character); 01903 //GWEN_Buffer_AppendByte(buf, e->character); 01904 src+=l; 01905 match=1; 01906 break; 01907 } 01908 e++; 01909 } /* while */ 01910 } 01911 } 01912 if (!match) { 01913 GWEN_TEXT__APPENDCHAR(*(src++)); 01914 } 01915 } /* while */ 01916 01917 if (bytesAdded) { 01918 GWEN_Buffer_IncrementPos(buf, bytesAdded); 01919 GWEN_Buffer_AdjustUsedBytes(buf); 01920 } 01921 01922 return 0; 01923 #undef GWEN_TEXT__APPENDCHAR 01924 } 01925 01926 01927 01928 int GWEN_Text_EscapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) { 01929 while(*src) { 01930 unsigned char x; 01931 const GWEN_TEXT_ESCAPE_ENTRY *e; 01932 int match; 01933 01934 match=0; 01935 x=(unsigned char)*src; 01936 e=gwen_text__xml_escape_chars; 01937 while(e->replace) { 01938 if (x==e->character) { 01939 GWEN_Buffer_AppendString(buf, e->replace); 01940 match=1; 01941 break; 01942 } 01943 e++; 01944 } /* while */ 01945 01946 if (!match) { 01947 if (0 && x>127) { /* disabled */ 01948 char numbuf[32]; 01949 01950 snprintf(numbuf, sizeof(numbuf), "&#%d;", x); 01951 GWEN_Buffer_AppendString(buf, numbuf); 01952 } 01953 else 01954 GWEN_Buffer_AppendByte(buf, *src); 01955 } 01956 src++; 01957 } /* while */ 01958 01959 return 0; 01960 } 01961 01962 01963 01964 int GWEN_Text_ConvertCharset(const char *fromCharset, 01965 const char *toCharset, 01966 const char *text, int len, 01967 GWEN_BUFFER *tbuf) { 01968 if (len) { 01969 if (fromCharset && *fromCharset && toCharset && *toCharset && 01970 strcasecmp(fromCharset, toCharset)!=0) { 01971 #ifndef HAVE_ICONV 01972 DBG_INFO(GWEN_LOGDOMAIN, 01973 "iconv not available, can not convert from \"%s\" to \"%s\"", 01974 fromCharset, toCharset); 01975 #else 01976 iconv_t ic; 01977 01978 ic=iconv_open(toCharset, fromCharset); 01979 if (ic==((iconv_t)-1)) { 01980 DBG_ERROR(GWEN_LOGDOMAIN, "Charset \"%s\" or \"%s\" not available", 01981 fromCharset, toCharset); 01982 } 01983 else { 01984 char *outbuf; 01985 char *pOutbuf; 01986 /* Some systems have iconv in libc, some have it in libiconv 01987 (OSF/1 and those with the standalone portable GNU libiconv 01988 installed). Check which one is available. The define 01989 ICONV_CONST will be "" or "const" accordingly. */ 01990 ICONV_CONST char *pInbuf; 01991 size_t inLeft; 01992 size_t outLeft; 01993 size_t done; 01994 size_t space; 01995 01996 /* convert */ 01997 pInbuf=(char*)text; 01998 01999 outLeft=len*2; 02000 space=outLeft; 02001 outbuf=(char*)malloc(outLeft); 02002 assert(outbuf); 02003 02004 inLeft=len; 02005 pInbuf=(char*)text; 02006 pOutbuf=outbuf; 02007 done=iconv(ic, &pInbuf, &inLeft, &pOutbuf, &outLeft); 02008 if (done==(size_t)-1) { 02009 DBG_ERROR(GWEN_LOGDOMAIN, "Error in conversion: %s (%d)", 02010 strerror(errno), errno); 02011 free(outbuf); 02012 iconv_close(ic); 02013 return GWEN_ERROR_GENERIC; 02014 } 02015 02016 GWEN_Buffer_AppendBytes(tbuf, outbuf, space-outLeft); 02017 free(outbuf); 02018 DBG_DEBUG(GWEN_LOGDOMAIN, "Conversion done."); 02019 iconv_close(ic); 02020 return 0; 02021 } 02022 #endif 02023 } 02024 02025 GWEN_Buffer_AppendBytes(tbuf, text, len); 02026 } 02027 return 0; 02028 } 02029