Skip to content
Snippets Groups Projects
Select Git revision
  • slyedit_quote_line_wrap_user_toggle_option
  • dd_msg_area_chooser_coloring_fix_and_separator_char_fix
  • dailybuild_linux-x64
  • dailybuild_win32
  • master default protected
  • sqlite
  • rip_abstraction
  • dailybuild_macos-armv8
  • dd_file_lister_filanem_in_desc_color
  • mode7
  • dd_msg_reader_are_you_there_warning_improvement
  • c23-playing
  • syncterm-1.3
  • syncterm-1.2
  • test-build
  • hide_remote_connection_with_telgate
  • 638-can-t-control-c-during-a-file-search
  • add_body_to_pager_email
  • mingw32-build
  • cryptlib-3.4.7
  • sbbs320d
  • syncterm-1.6
  • syncterm-1.5
  • syncterm-1.4
  • sbbs320b
  • syncterm-1.3
  • syncterm-1.2
  • syncterm-1.2rc6
  • syncterm-1.2rc5
  • push
  • syncterm-1.2rc4
  • syncterm-1.2rc2
  • syncterm-1.2rc1
  • sbbs319b
  • sbbs318b
  • goodbuild_linux-x64_Sep-01-2020
  • goodbuild_win32_Sep-01-2020
  • goodbuild_linux-x64_Aug-31-2020
  • goodbuild_win32_Aug-31-2020
  • goodbuild_win32_Aug-30-2020
40 results

str_util.c

Blame
  • str_util.c 14.38 KiB
    /* str_util.c */
    
    /* Synchronet string utility routines */
    
    /* $Id$ */
    
    /****************************************************************************
     * @format.tab-size 4		(Plain Text/Source Code File Header)			*
     * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
     *																			*
     * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
     *																			*
     * This program is free software; you can redistribute it and/or			*
     * modify it under the terms of the GNU General Public License				*
     * as published by the Free Software Foundation; either version 2			*
     * of the License, or (at your option) any later version.					*
     * See the GNU General Public License for more details: gpl.txt or			*
     * http://www.fsf.org/copyleft/gpl.html										*
     *																			*
     * Anonymous FTP access to the most recent released source is available at	*
     * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
     *																			*
     * Anonymous CVS access to the development source and modification history	*
     * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
     * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
     *     (just hit return, no password is necessary)							*
     * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
     *																			*
     * For Synchronet coding style and modification guidelines, see				*
     * http://www.synchro.net/source.html										*
     *																			*
     * You are encouraged to submit any modifications (preferably in Unix diff	*
     * format) via e-mail to mods@synchro.net									*
     *																			*
     * Note: If this box doesn't appear square, then you need to fix your tabs.	*
     ****************************************************************************/
    
    #include "sbbs.h"
    
    /****************************************************************************/
    /* Removes ctrl-a codes from the string 'instr'                             */
    /****************************************************************************/
    char* DLLCALL remove_ctrl_a(char *instr, char *outstr)
    {
    	char str[1024],*p;
    	uint i,j;
    
    	for(i=j=0;instr[i] && j<sizeof(str)-1;i++) {
    		if(instr[i]==CTRL_A && instr[i+1]!=0)
    			i++;
    		else str[j++]=instr[i]; 
    	}
    	str[j]=0;
    	if(outstr!=NULL)
    		p=outstr;
    	else
    		p=instr;
    	strcpy(p,str);
    	return(p);
    }
    
    char* DLLCALL strip_ctrl(char *str)
    {
    	char tmp[1024];
    	int i,j;
    
    	for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++)
    		if(str[i]==CTRL_A && str[i+1]!=0)
    			i++;
    		else if((uchar)str[i]>=SP)
    			tmp[j++]=str[i];
    	tmp[j]=0;
    	strcpy(str,tmp);
    	return(str);
    }
    
    char* DLLCALL strip_exascii(char *str)
    {
    	char tmp[1024];
    	int i,j;
    
    	for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++)
    		if(!(str[i]&0x80))
    			tmp[j++]=str[i];
    	tmp[j]=0;
    	strcpy(str,tmp);
    	return(str);
    }
    
    char* DLLCALL prep_file_desc(char *str)
    {
    	char tmp[1024];
    	int i,j;
    
    	for(i=j=0;str[i];i++)
    		if(str[i]==CTRL_A && str[i+1]!=0)
    			i++;
    		else if(j && str[i]<=SP && tmp[j-1]==SP)
    			continue;
    		else if(i && !isalnum(str[i]) && str[i]==str[i-1])
    			continue;
    		else if((uchar)str[i]>=SP)
    			tmp[j++]=str[i];
    		else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
    			tmp[j++]=SP;
    	tmp[j]=0;
    	strcpy(str,tmp);
    	return(str);
    }
    
    /****************************************************************************/
    /* Pattern matching string search of 'insearchof' in 'fname'.				*/
    /****************************************************************************/
    BOOL DLLCALL findstr(char* insearchof, char* fname)
    {
    	char*	p;
    	char	str[128];
    	char	search[81];
    	int		c;
    	int		i;
    	BOOL	found;
    	FILE*	stream;
    
    	if((stream=fopen(fname,"r"))==NULL)
    		return(FALSE); 
    
    	SAFECOPY(search,insearchof);
    	strupr(search);
    
    	found=FALSE;
    
    	while(!feof(stream) && !ferror(stream) && !found) {
    		if(!fgets(str,sizeof(str),stream))
    			break;
    		
    		found=FALSE;
    
    		p=str;	
    		while(*p && *p<=' ') p++; /* Skip white-space */
    
    		if(*p==';')		/* comment */
    			continue;
    
    		if(*p=='!')	{	/* !match */
    			found=TRUE;
    			p++;
    		}
    
    		truncsp(p);
    		c=strlen(p);
    		if(c) {
    			c--;
    			strupr(p);
    			if(p[c]=='~') {
    				p[c]=0;
    				if(strstr(search,p))
    					found=!found; 
    			}
    
    			else if(p[c]=='^' || p[c]=='*') {
    				p[c]=0;
    				if(!strncmp(p,search,c))
    					found=!found; 
    			}
    
    			else if(p[0]=='*') {
    				i=strlen(search);
    				if(i<c)
    					continue;
    				if(!strncmp(p+1,search+(i-c),c))
    					found=!found; 
    			}
    
    			else if(!strcmp(p,search))
    				found=!found; 
    		} 
    	}
    	fclose(stream);
    	return(found);
    }
    
    /****************************************************************************/
    /* Searches the file <name>.can in the TEXT directory for matches			*/
    /* Returns TRUE if found in list, FALSE if not.								*/
    /****************************************************************************/
    BOOL DLLCALL trashcan(scfg_t* cfg, char* insearchof, char* name)
    {
    	char fname[MAX_PATH+1];
    
    	sprintf(fname,"%s%s.can",cfg->text_dir,name);
    	return(findstr(insearchof,fname));
    }
    
    /****************************************************************************/
    /* Returns the number of characters in 'str' not counting ctrl-ax codes		*/
    /* or the null terminator													*/
    /****************************************************************************/
    int bstrlen(char *str)
    {
    	int i=0;
    
    	while(*str) {
    		if(*str==CTRL_A)
    			str++;
    		else
    			i++;
    		if(!(*str)) break;
    		str++; }
    	return(i);
    }
    
    /****************************************************************************/
    /* Returns in 'string' a character representation of the number in l with   */
    /* commas.																	*/
    /****************************************************************************/
    char* DLLCALL ultoac(ulong l, char *string)
    {
    	char str[256];
    	int i,j,k;
    
    	ultoa(l,str,10);
    	i=strlen(str)-1;
    	j=i/3+1+i;
    	string[j--]=0;
    	for(k=1;i>-1;k++) {
    		string[j--]=str[i--];
    		if(j>0 && !(k%3))
    			string[j--]=','; }
    	return(string);
    }
    
    /****************************************************************************/
    /* Truncates white-space chars off end of 'str'								*/
    /****************************************************************************/
    char* DLLCALL truncsp(char *str)
    {
    	uint c;
    
    	c=strlen(str);
    	while(c && (uchar)str[c-1]<=' ') c--;
    	str[c]=0;
    	return(str);
    }
    
    /****************************************************************************/
    /* Truncate string at first occurance of char in specified character set	*/
    /****************************************************************************/
    char* DLLCALL truncstr(char* str, const char* set)
    {
    	char* p;
    
    	p=strpbrk(str,set);
    	if(p!=NULL)
    		*p=0;
    
    	return(p);
    }
    
    /****************************************************************************/
    /* Puts a backslash on path strings 										*/
    /****************************************************************************/
    void backslash(char *str)
    {
        int i;
    
    	i=strlen(str);
    	if(i && str[i-1]!='\\' && str[i-1]!='/') {
    		str[i]=BACKSLASH; 
    		str[i+1]=0; 
    	}
    }
    
    /****************************************************************************/
    /* Puts a backslash on path strings if not just a drive letter and colon	*/
    /****************************************************************************/
    void backslashcolon(char *str)
    {
        int i;
    
    	i=strlen(str);
    	if(i && str[i-1]!='\\' && str[i-1]!='/' && str[i-1]!=':') {
    		str[i]=BACKSLASH; 
    		str[i+1]=0; 
    	}
    }
    
    /****************************************************************************/
    /* Compares pointers to pointers to char. Used in conjuction with qsort()   */
    /****************************************************************************/
    int pstrcmp(char **str1, char **str2)
    {
    	return(strcmp(*str1,*str2));
    }
    
    /****************************************************************************/
    /* Returns the number of characters that are the same between str1 and str2 */
    /****************************************************************************/
    int strsame(char *str1, char *str2)
    {
    	int i,j=0;
    
    	for(i=0;str1[i];i++)
    		if(str1[i]==str2[i]) j++;
    	return(j);
    }
    
    /****************************************************************************/
    /* Returns an ASCII string for FidoNet address 'addr'                       */
    /****************************************************************************/
    char *faddrtoa(faddr_t* addr, char* outstr)
    {
    	static char str[64];
        char point[25];
    
    	if(addr==NULL)
    		return("0:0/0");
    	sprintf(str,"%hu:%hu/%hu",addr->zone,addr->net,addr->node);
    	if(addr->point) {
    		sprintf(point,".%hu",addr->point);
    		strcat(str,point); }
    	if(outstr==NULL)
    		return(str);
    	strcpy(outstr,str);
    	return(outstr);
    }
    
    char* DLLCALL net_addr(net_t* net)
    {
    	if(net->type==NET_FIDO)
    		return(faddrtoa((faddr_t*)net->addr,NULL));
    	return(net->addr);
    }
    
    static ulong msgid_serialno(smbmsg_t* msg)
    {
    	return (msg->idx.time-1000000000) + msg->idx.number;
    }
    
    /****************************************************************************/
    /* Returns a FidoNet (FTS-9) message-ID										*/
    /****************************************************************************/
    char* DLLCALL ftn_msgid(sub_t *sub, smbmsg_t* msg)
    {
    	static char msgid[256];
    
    	if(msg->ftn_msgid!=NULL && *msg->ftn_msgid!=0)
    		return(msg->ftn_msgid);
    
    	snprintf(msgid,sizeof(msgid)
    		,"%s %08lx %lu.%s %08lX"
    		,faddrtoa(&sub->faddr,NULL)
    		,msgid_serialno(msg)
    		,msg->idx.number
    		,sub->code
    		,msgid_serialno(msg)
    		);
    
    	return(msgid);
    }
    
    /****************************************************************************/
    /* Return a general purpose (RFC-822) message-ID							*/
    /****************************************************************************/
    char* DLLCALL get_msgid(scfg_t* cfg, uint subnum, smbmsg_t* msg)
    {
    	static char msgid[256];
    
    	if(msg->id!=NULL && *msg->id!=0)
    		return(msg->id);
    
    	if(subnum>=cfg->total_subs)
    		snprintf(msgid,sizeof(msgid)
    			,"<%08lX.%lu@%s>"
    			,msg->idx.time
    			,msg->idx.number
    			,cfg->sys_inetaddr);
    	else
    		snprintf(msgid,sizeof(msgid)
    			,"<%08lX.%lu.%s@%s>"
    			,msg->idx.time
    			,msg->idx.number
    			,cfg->sub[subnum]->code
    			,cfg->sys_inetaddr);
    
    	return(msgid);
    }
    /****************************************************************************/
    /* Retrieve a message by RFC822 message-ID									*/
    /****************************************************************************/
    BOOL DLLCALL get_msg_by_id(scfg_t* scfg, smb_t* smb, char* id, smbmsg_t* msg)
    {
    	ulong		n;
    	int			ret;
    
    	for(n=0;n<smb->status.last_msg;n++) {
    		memset(msg,0,sizeof(smbmsg_t));
    		msg->offset=n;
    		if(smb_getmsgidx(smb, msg)!=0)
    			break;
    
    		if(smb_lockmsghdr(smb,msg)!=0)
    			continue;
    
    		ret=smb_getmsghdr(smb,msg);
    
    		smb_unlockmsghdr(smb,msg); 
    
    		if(ret!=SMB_SUCCESS)
    			continue;
    
    		if(strcmp(get_msgid(scfg,smb->subnum,msg),id)==0)
    			return(TRUE);
    
    		smb_freemsgmem(msg);
    	}
    
    	return(FALSE);
    }
    
    /****************************************************************************/
    /* Returns string for 2 digit hex+ numbers up to 575						*/
    /****************************************************************************/
    char *hexplus(uint num, char *str)
    {
    	sprintf(str,"%03x",num);
    	str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
    	str[1]=str[2];
    	str[2]=0;
    	return(str);
    }
    
    /****************************************************************************/
    /* Converts an ASCII Hex string into an ulong                               */
    /* by Steve Deppe (Ille Homine Albe)										*/
    /****************************************************************************/
    ulong ahtoul(char *str)
    {
        ulong l,val=0;
    
    	while((l=(*str++)|0x20)!=0x20)
    		val=(l&0xf)+(l>>6&1)*9+val*16;
    	return(val);
    }
    
    /****************************************************************************/
    /* Converts hex-plus string to integer										*/
    /****************************************************************************/
    uint hptoi(char *str)
    {
    	char tmp[128];
    	uint i;
    
    	if(!str[1] || toupper(str[0])<='F')
    		return(ahtoul(str));
    	strcpy(tmp,str);
    	tmp[0]='F';
    	i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
    	return(i);
    }
    
    
    /****************************************************************************/
    /* Updates 16-bit "rcrc" with character 'ch'                                */
    /****************************************************************************/
    void ucrc16(uchar ch, ushort *rcrc) 
    {
    	ushort i, cy;
        uchar nch=ch;
     
    	for (i=0; i<8; i++) {
    		cy=*rcrc & 0x8000;
    		*rcrc<<=1;
    		if (nch & 0x80) *rcrc |= 1;
    		nch<<=1;
    		if (cy) *rcrc ^= 0x1021; }
    }
    
    /****************************************************************************/
    /* Returns CRC-16 of ASCIIZ string (not including terminating NULL)			*/
    /****************************************************************************/
    ushort DLLCALL crc16(char *str)
    {
    	int 	i=0;
    	ushort	crc=0;
    
    	ucrc16(0,&crc);
    	while(str[i])
    		ucrc16(str[i++],&crc);
    	ucrc16(0,&crc);
    	ucrc16(0,&crc);
    	return(crc);
    }
    
    /****************************************************************************/
    /* Returns 1 if a is a valid ctrl-a code, 0 if it isn't.                    */
    /****************************************************************************/
    BOOL DLLCALL validattr(char a)
    {
    
    	switch(toupper(a)) {
    		case '-':   /* clear        */
    		case '_':   /* clear        */
    		case 'B':   /* blue     fg  */
    		case 'C':   /* cyan     fg  */
    		case 'G':   /* green    fg  */
    		case 'H':   /* high     fg  */
    		case 'I':   /* blink        */
    		case 'K':   /* black    fg  */
    		case 'L':   /* cls          */
    		case 'M':   /* magenta  fg  */
    		case 'N':   /* normal       */
    		case 'P':   /* pause        */
    		case 'R':   /* red      fg  */
    		case 'W':   /* white    fg  */
    		case 'Y':   /* yellow   fg  */
    		case '0':   /* black    bg  */
    		case '1':   /* red      bg  */
    		case '2':   /* green    bg  */
    		case '3':   /* brown    bg  */
    		case '4':   /* blue     bg  */
    		case '5':   /* magenta  bg  */
    		case '6':   /* cyan     bg  */
    		case '7':   /* white    bg  */
    			return(TRUE); 
    	}
    	return(FALSE);
    }
    
    /****************************************************************************/
    /* Strips invalid Ctrl-Ax sequences from str                                */
    /* Returns number of ^A's in line                                           */
    /****************************************************************************/
    size_t DLLCALL strip_invalid_attr(char *strin)
    {
        char str[1024];
        size_t a,c,d;
    
    	for(a=c=d=0;strin[c] && d<sizeof(str)-1;c++) {
    		if(strin[c]==CTRL_A && strin[c+1]!=0) {
    			a++;
    			if(!validattr(strin[c+1])) {
    				c++;
    				continue; 
    			} 
    		}
    		str[d++]=strin[c]; 
    	}
    	str[d]=0;
    	strcpy(strin,str);
    	return(a);
    }
    
    ushort DLLCALL subject_crc(char *subj)
    {
    	char str[512];
    
    	while(!strnicmp(subj,"RE:",3)) {
    		subj+=3;
    		while(*subj==SP)
    			subj++; 
    	}
    
    	SAFECOPY(str,subj);
    	strlwr(str);
    	return(crc16(str));
    }