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