|
|
1.1 ! root 1: /* str_util.c */ ! 2: ! 3: /* Synchronet string utility routines */ ! 4: ! 5: /* $Id: str_util.c,v 1.30 2004/09/11 09:36:19 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This program is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU General Public License for more details: gpl.txt or * ! 18: * http://www.fsf.org/copyleft/gpl.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include "sbbs.h" ! 39: ! 40: /****************************************************************************/ ! 41: /* Removes ctrl-a codes from the string 'instr' */ ! 42: /****************************************************************************/ ! 43: char* DLLCALL remove_ctrl_a(char *instr, char *outstr) ! 44: { ! 45: char str[1024],*p; ! 46: uint i,j; ! 47: ! 48: for(i=j=0;instr[i] && j<sizeof(str)-1;i++) { ! 49: if(instr[i]==CTRL_A && instr[i+1]!=0) ! 50: i++; ! 51: else str[j++]=instr[i]; ! 52: } ! 53: str[j]=0; ! 54: if(outstr!=NULL) ! 55: p=outstr; ! 56: else ! 57: p=instr; ! 58: strcpy(p,str); ! 59: return(p); ! 60: } ! 61: ! 62: char* DLLCALL strip_ctrl(char *str) ! 63: { ! 64: char tmp[1024]; ! 65: int i,j; ! 66: ! 67: for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++) { ! 68: if(str[i]==CTRL_A && str[i+1]!=0) ! 69: i++; ! 70: else if((uchar)str[i]>=' ') ! 71: tmp[j++]=str[i]; ! 72: } ! 73: if(i!=j) { ! 74: tmp[j]=0; ! 75: strcpy(str,tmp); ! 76: } ! 77: return(str); ! 78: } ! 79: ! 80: char* DLLCALL strip_exascii(char *str) ! 81: { ! 82: char tmp[1024]; ! 83: int i,j; ! 84: ! 85: for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++) ! 86: if(!(str[i]&0x80)) ! 87: tmp[j++]=str[i]; ! 88: tmp[j]=0; ! 89: strcpy(str,tmp); ! 90: return(str); ! 91: } ! 92: ! 93: char* DLLCALL prep_file_desc(char *str) ! 94: { ! 95: char tmp[1024]; ! 96: int i,j; ! 97: ! 98: for(i=j=0;str[i];i++) ! 99: if(str[i]==CTRL_A && str[i+1]!=0) ! 100: i++; ! 101: else if(j && str[i]<=' ' && tmp[j-1]==' ') ! 102: continue; ! 103: else if(i && !isalnum(str[i]) && str[i]==str[i-1]) ! 104: continue; ! 105: else if((uchar)str[i]>=' ') ! 106: tmp[j++]=str[i]; ! 107: else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF)) ! 108: tmp[j++]=' '; ! 109: tmp[j]=0; ! 110: strcpy(str,tmp); ! 111: return(str); ! 112: } ! 113: ! 114: /****************************************************************************/ ! 115: /* Pattern matching string search of 'insearchof' in 'fname'. */ ! 116: /****************************************************************************/ ! 117: BOOL DLLCALL findstr(char* insearchof, char* fname) ! 118: { ! 119: char* p; ! 120: char str[128]; ! 121: char search[81]; ! 122: int c; ! 123: int i; ! 124: BOOL found; ! 125: FILE* stream; ! 126: ! 127: if((stream=fopen(fname,"r"))==NULL) ! 128: return(FALSE); ! 129: ! 130: SAFECOPY(search,insearchof); ! 131: strupr(search); ! 132: ! 133: found=FALSE; ! 134: ! 135: while(!feof(stream) && !ferror(stream) && !found) { ! 136: if(!fgets(str,sizeof(str),stream)) ! 137: break; ! 138: ! 139: found=FALSE; ! 140: ! 141: p=str; ! 142: while(*p && *p<=' ') p++; /* Skip white-space */ ! 143: ! 144: if(*p==';') /* comment */ ! 145: continue; ! 146: ! 147: if(*p=='!') { /* !match */ ! 148: found=TRUE; ! 149: p++; ! 150: } ! 151: ! 152: truncsp(p); ! 153: c=strlen(p); ! 154: if(c) { ! 155: c--; ! 156: strupr(p); ! 157: if(p[c]=='~') { ! 158: p[c]=0; ! 159: if(strstr(search,p)) ! 160: found=!found; ! 161: } ! 162: ! 163: else if(p[c]=='^' || p[c]=='*') { ! 164: p[c]=0; ! 165: if(!strncmp(p,search,c)) ! 166: found=!found; ! 167: } ! 168: ! 169: else if(p[0]=='*') { ! 170: i=strlen(search); ! 171: if(i<c) ! 172: continue; ! 173: if(!strncmp(p+1,search+(i-c),c)) ! 174: found=!found; ! 175: } ! 176: ! 177: else if(!strcmp(p,search)) ! 178: found=!found; ! 179: } ! 180: } ! 181: fclose(stream); ! 182: return(found); ! 183: } ! 184: ! 185: /****************************************************************************/ ! 186: /* Searches the file <name>.can in the TEXT directory for matches */ ! 187: /* Returns TRUE if found in list, FALSE if not. */ ! 188: /****************************************************************************/ ! 189: BOOL DLLCALL trashcan(scfg_t* cfg, char* insearchof, char* name) ! 190: { ! 191: char fname[MAX_PATH+1]; ! 192: ! 193: sprintf(fname,"%s%s.can",cfg->text_dir,name); ! 194: return(findstr(insearchof,fname)); ! 195: } ! 196: ! 197: /****************************************************************************/ ! 198: /* Returns the number of characters in 'str' not counting ctrl-ax codes */ ! 199: /* or the null terminator */ ! 200: /****************************************************************************/ ! 201: int bstrlen(char *str) ! 202: { ! 203: int i=0; ! 204: ! 205: while(*str) { ! 206: if(*str==CTRL_A) ! 207: str++; ! 208: else ! 209: i++; ! 210: if(!(*str)) break; ! 211: str++; } ! 212: return(i); ! 213: } ! 214: ! 215: /****************************************************************************/ ! 216: /* Returns in 'string' a character representation of the number in l with */ ! 217: /* commas. */ ! 218: /****************************************************************************/ ! 219: char* DLLCALL ultoac(ulong l, char *string) ! 220: { ! 221: char str[256]; ! 222: int i,j,k; ! 223: ! 224: ultoa(l,str,10); ! 225: i=strlen(str)-1; ! 226: j=i/3+1+i; ! 227: string[j--]=0; ! 228: for(k=1;i>-1;k++) { ! 229: string[j--]=str[i--]; ! 230: if(j>0 && !(k%3)) ! 231: string[j--]=','; } ! 232: return(string); ! 233: } ! 234: ! 235: /****************************************************************************/ ! 236: /* Truncate string at first occurance of char in specified character set */ ! 237: /****************************************************************************/ ! 238: char* DLLCALL truncstr(char* str, const char* set) ! 239: { ! 240: char* p; ! 241: ! 242: p=strpbrk(str,set); ! 243: if(p!=NULL && *p!=0) ! 244: *p=0; ! 245: ! 246: return(p); ! 247: } ! 248: ! 249: /****************************************************************************/ ! 250: /* rot13 encoder/decoder - courtesy of Mike Acar */ ! 251: /****************************************************************************/ ! 252: char* DLLCALL rot13(char* str) ! 253: { ! 254: char ch, cap; ! 255: char* p; ! 256: ! 257: p=str; ! 258: while((ch=*p)!=0) { ! 259: cap = ch & 32; ! 260: ch &= ~cap; ! 261: ch = ((ch >= 'A') && (ch <= 'Z') ? ((ch - 'A' + 13) % 26 + 'A') : ch) | cap; ! 262: *(p++)=ch; ! 263: } ! 264: ! 265: return(str); ! 266: } ! 267: ! 268: /****************************************************************************/ ! 269: /* Puts a backslash on path strings if not just a drive letter and colon */ ! 270: /****************************************************************************/ ! 271: void backslashcolon(char *str) ! 272: { ! 273: int i; ! 274: ! 275: i=strlen(str); ! 276: if(i && !IS_PATH_DELIM(str[i-1]) && str[i-1]!=':') { ! 277: str[i]=PATH_DELIM; ! 278: str[i+1]=0; ! 279: } ! 280: } ! 281: ! 282: /****************************************************************************/ ! 283: /* Compares pointers to pointers to char. Used in conjuction with qsort() */ ! 284: /****************************************************************************/ ! 285: int pstrcmp(char **str1, char **str2) ! 286: { ! 287: return(strcmp(*str1,*str2)); ! 288: } ! 289: ! 290: /****************************************************************************/ ! 291: /* Returns the number of characters that are the same between str1 and str2 */ ! 292: /****************************************************************************/ ! 293: int strsame(char *str1, char *str2) ! 294: { ! 295: int i,j=0; ! 296: ! 297: for(i=0;str1[i];i++) ! 298: if(str1[i]==str2[i]) j++; ! 299: return(j); ! 300: } ! 301: ! 302: ! 303: /****************************************************************************/ ! 304: /* Returns string for 2 digit hex+ numbers up to 575 */ ! 305: /****************************************************************************/ ! 306: char *hexplus(uint num, char *str) ! 307: { ! 308: sprintf(str,"%03x",num); ! 309: str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1]; ! 310: str[1]=str[2]; ! 311: str[2]=0; ! 312: return(str); ! 313: } ! 314: ! 315: /****************************************************************************/ ! 316: /* Converts an ASCII Hex string into an ulong */ ! 317: /* by Steve Deppe (Ille Homine Albe) */ ! 318: /****************************************************************************/ ! 319: ulong ahtoul(char *str) ! 320: { ! 321: ulong l,val=0; ! 322: ! 323: while((l=(*str++)|0x20)!=0x20) ! 324: val=(l&0xf)+(l>>6&1)*9+val*16; ! 325: return(val); ! 326: } ! 327: ! 328: /****************************************************************************/ ! 329: /* Converts hex-plus string to integer */ ! 330: /****************************************************************************/ ! 331: uint hptoi(char *str) ! 332: { ! 333: char tmp[128]; ! 334: uint i; ! 335: ! 336: if(!str[1] || toupper(str[0])<='F') ! 337: return(ahtoul(str)); ! 338: strcpy(tmp,str); ! 339: tmp[0]='F'; ! 340: i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10); ! 341: return(i); ! 342: } ! 343: ! 344: /****************************************************************************/ ! 345: /* Returns 1 if a is a valid ctrl-a code, 0 if it isn't. */ ! 346: /****************************************************************************/ ! 347: BOOL DLLCALL validattr(char a) ! 348: { ! 349: ! 350: switch(toupper(a)) { ! 351: case '+': /* push attr */ ! 352: case '-': /* pop attr */ ! 353: case '_': /* clear */ ! 354: case 'B': /* blue fg */ ! 355: case 'C': /* cyan fg */ ! 356: case 'G': /* green fg */ ! 357: case 'H': /* high fg */ ! 358: case 'I': /* blink */ ! 359: case 'K': /* black fg */ ! 360: case 'L': /* cls */ ! 361: case 'M': /* magenta fg */ ! 362: case 'N': /* normal */ ! 363: case 'P': /* pause */ ! 364: case 'R': /* red fg */ ! 365: case 'W': /* white fg */ ! 366: case 'Y': /* yellow fg */ ! 367: case '0': /* black bg */ ! 368: case '1': /* red bg */ ! 369: case '2': /* green bg */ ! 370: case '3': /* brown bg */ ! 371: case '4': /* blue bg */ ! 372: case '5': /* magenta bg */ ! 373: case '6': /* cyan bg */ ! 374: case '7': /* white bg */ ! 375: return(TRUE); ! 376: } ! 377: return(FALSE); ! 378: } ! 379: ! 380: /****************************************************************************/ ! 381: /* Strips invalid Ctrl-Ax sequences from str */ ! 382: /* Returns number of ^A's in line */ ! 383: /****************************************************************************/ ! 384: size_t DLLCALL strip_invalid_attr(char *strin) ! 385: { ! 386: char str[1024]; ! 387: size_t a,c,d; ! 388: ! 389: for(a=c=d=0;strin[c] && d<sizeof(str)-1;c++) { ! 390: if(strin[c]==CTRL_A && strin[c+1]!=0) { ! 391: a++; ! 392: if(!validattr(strin[c+1])) { ! 393: c++; ! 394: continue; ! 395: } ! 396: } ! 397: str[d++]=strin[c]; ! 398: } ! 399: str[d]=0; ! 400: strcpy(strin,str); ! 401: return(a); ! 402: } ! 403:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.