/* find_http_req DATA LEN FOUND FOUNDLEN * Look for an HTTP request and response in buffer DATA of length LEN. The * return value is a pointer into DATA suitable for a subsequent call to this * function; *FOUND is either NULL, or a pointer to the start of an HTTP * request; in the latter case, *FOUNDLEN is the length of the match * containing enough information to obtain the URL. */ unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen) { unsigned char *req, *le, *blankline, *hosthdr; #define remaining(x) (len - (data - (x))) #define MAX_REQ 16384 /* HTTP requests look like: * * GET {path} HTTP/1.(0|1)\r\n * header: value\r\n * ... * \r\n * * We may care about the Host: header in the request. */ if (len < 40) return (unsigned char*)data; if (!(req = memstr(data, len, (unsigned char*) "GET ", 4))) return (unsigned char*)(data + len - 4); /* Find the end of the request line. */ if (!(le = memstr(req + 4, remaining(req + 4), (unsigned char*) "\r\n", 2))) { if (remaining(req + 4) > MAX_REQ) return (unsigned char*)(req + 4); else return (unsigned char*)req; } /* Not enough space for a path. */ if (le < req + 5) return le + 2; /* Not an HTTP request, just a line starting GET.... */ if (memcmp(le - 9, " HTTP/1.", 8) || !strchr("01", (int)*(le - 1))) return le + 2; /* Find the end of the request headers. */ if (!(blankline = memstr(le + 2, remaining(le + 2), (unsigned char*) "\r\n\r\n", 4))) { if (remaining(le + 2) > MAX_REQ) return (unsigned char*)(data + len - 4); else return req; } if (memcmp(req + 4, "http://", 7) == 0) /* Probably a cache request; in any case, don't need to look for a Host:. */ goto found; /* Is there a Host: header? */ if (!(hosthdr = memstr(le, blankline - le + 2, (unsigned char*) "\r\nHost: ", 8))) { return blankline + 4; } found: *http = req; *httplen = blankline - req; return blankline + 4; }
TEST(MiscTests, MemStr) { const char text[] = "zaqwsxcderfv543\xa6\00bnmjhgfrtcsKOTEKequdo825dgqjx92jdDCSIvfds9*%c3@^((b%^((*gswtysirkkwpfceoioGt7j"; const char pat1[] = "KOTEK"; const char pat2[] = "KO£EK"; EXPECT_NE(memstr(text, pat1, sizeof(pat1) - 1), nullptr); EXPECT_EQ(memstr(text, pat2, sizeof(pat2) - 1), nullptr); }
unsigned char *find_jpeg_image(const unsigned char *data, const size_t len, unsigned char **jpegdata, size_t *jpeglen) { unsigned char *jpeghdr; *jpegdata = NULL; *jpeglen = 0; if (data == NULL) { return NULL; } /* find SOI marker */ jpeghdr = memstr(data, len, (unsigned char*)"\xff\xd8", 2); if (!jpeghdr) return (unsigned char*)(data + len - 1); jpg_segment_t* segment; unsigned int segment_lenght = 2; unsigned char *block = jpeghdr; do { /* more data to advance ? */ if (data + len < block + segment_lenght) { break; } /* advance to next block */ block = block + segment_lenght; segment = (jpg_segment_t*) block; segment_lenght = is_jpeg_segment(segment); /* * start of scan * * XXX: dunno how to parse... */ if (segment->marker_type == SOS) { block = memstr(block, len - (block - data), (unsigned char*)"\xff\xd9", 2); if (block) { *jpegdata = jpeghdr; *jpeglen = block + 2 - jpeghdr; return block + 2; } else break; } } while (segment_lenght != 0); return jpeghdr; }
// 粘贴内存解析战果 BOOL CAirLogEx::PasteMemory(CHAR* lpMemory, DWORD dwsize) { DWORD dwOutsize = 0; CHAR* lpfltMemory = this->CharFilter(lpMemory, dwsize, FILTER_CHAR, &dwOutsize); BOOL bRet = FALSE; if (lpfltMemory) { CHAR* lpHead = memstr(lpfltMemory, BLOCK_ENDOFGAMESTATS, dwOutsize); if (lpHead) { lpHead += lstrlenA(BLOCK_ENDOFGAMESTATS); int nbodySize = dwOutsize - (lpHead - lpfltMemory); this->CutAllBlock(lpHead, nbodySize); if ( SWF_ERR_INT != this->GetFirstSummBlock(EndofGameStats.teamPlayerParticipantStats/*, lpfltMemory, dwsize*/) ) { int airIdx = this->GetPointsPenaltyBlock(&EndofGameStats.PointsPenalty); if (SWF_ERR_INT != airIdx) { if ( SWF_ERR_INT != this->GetNextSummBlock(EndofGameStats.otherTeamPlayerParticipantStats, airIdx) ) { if ( SWF_ERR_INT != this->GetEndOfGameBlock(&EndofGameStats) ) bRet = TRUE; } } } } this->FreeFilterStr(lpfltMemory); } FreeAirMemory(m_airMemoryArr.begin(), m_airMemoryArr.size()); return bRet; }
int rtl_mime_get_boundry(char *query_string, int query_string_len) { char *substr_start,*ptr; char *substr="----------------------------"; substr_start=memstr(query_string,substr,query_string_len); if(substr_start==NULL) { printf("can't get boundry string\n"); return -1; } int i=0; ptr=substr_start; while( (ptr[i] !=0x0d || ptr[i+1] !=0x0a) && i<MAX_BOUNDRY_LEN) { str_boundry[i]=ptr[i]; i++; } if(i>=MAX_BOUNDRY_LEN) { printf("the string of boundry is too long\n"); return -1; } str_boundry[i]=0;
int Add_To_Heap(char *s,int fancy) { int old_ofs; char *o; /* If string is already in table, no need to add! */ if ((o=memstr(strings,s,offset,strlen(s)+1)) != NULL) old_ofs=o-strings; else { strcpy(strings+offset,s); old_ofs=offset; offset += strlen(s)+1; #ifndef UNIX if (fancy) fancy_fn(strings+old_ofs); #endif } if (offset >= HEAP_SIZE) { printf("\n\aRan out of memory while adding `%s' to .PRM heap.\n",s); exit(1); } return old_ofs; }
// Print a classic memory dump with configurable base and grouping. void memdump(const char* data, size_t length, u_int8_t base, u_int8_t gsize, u_int8_t gcount) { int group_size = gsize; int group_count = gcount; int line_width = group_size * group_count; unsigned int offset = 0; while (length > offset) { const char* line = &data[offset]; size_t lineMax = MIN((length - offset), line_width); printf(" %p %06u |", &line[0], offset); for (int c = 0; c < lineMax; c++) { if ( (c % group_size) == 0 ) printf(" "); char* str = memstr(&line[c], 1, base); printf("%s ", str); FREE_BUFFER(str); } printf("|"); for (int c = 0; c < lineMax; c++) { if ( (c % group_size) == 0 ) printf(" "); char chr = line[c] & 0xFF; if (chr < 32) // ASCII unprintable chr = '.'; printf("%c", chr); } printf(" |\n"); offset += line_width; } }
} char *rtl_mime_get_name(char *query_string,char *param,int query_string_len) { char *ptr=NULL; ptr=memstr(query_string,param,query_string_len); if(ptr==NULL) return NULL;
void listenmain(void) { int size, ip_size; int stdoutFD = fileno(stdout); char packet[IP_MAX_SIZE+linkhdr_size]; char *p, *ip_packet; struct myiphdr ip; __u16 id; static __u16 exp_id; /* expected id */ exp_id = 1; while(1) { size = read_packet(packet, IP_MAX_SIZE+linkhdr_size); switch(size) { case 0: continue; case -1: exit(1); } /* Skip truncated packets */ if (size < linkhdr_size+IPHDR_SIZE) continue; ip_packet = packet + linkhdr_size; /* copy the ip header so it will be aligned */ memcpy(&ip, ip_packet, sizeof(ip)); id = ntohs(ip.id); ip_size = ntohs(ip.tot_len); if (size-linkhdr_size > ip_size) size = ip_size; else size -= linkhdr_size; if ((p = memstr(ip_packet, sign, size))) { if (opt_verbose) fprintf(stderr, "packet %d received\n", id); if (opt_safe) { if (id == exp_id) exp_id++; else { if (opt_verbose) fprintf(stderr, "packet not in sequence (id %d) received\n", id); send_hcmp(HCMP_RESTART, exp_id); if (opt_verbose) fprintf(stderr, "HCMP restart from %d sent\n", exp_id); continue; /* discard this packet */ } } p+=strlen(sign); write(stdoutFD, p, size-(p-ip_packet)); } } }
} char *rtl_mime_find_boundry(char *query_string, int query_string_len) { char *substr_start; substr_start=memstr(query_string,str_boundry,query_string_len); if(substr_start==NULL) return NULL; int len=strlen(str_boundry); substr_start+=len;
static void Str_split(struct v7_c_func_arg *cfa) { const struct v7_string *s = &cfa->this_obj->v.str; const char *p1, *p2, *e = s->buf + s->len; int limit = cfa->num_args == 2 && cfa->args[1]->type == V7_TYPE_NUM ? cfa->args[1]->v.num : -1; int num_elems = 0; v7_set_class(cfa->result, V7_CLASS_ARRAY); if (cfa->num_args == 0) { v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, s->buf, s->len, 1)); } else if (cfa->args[0]->type == V7_TYPE_STR) { const struct v7_string *sep = &cfa->args[0]->v.str; if (sep->len == 0) { // Separator is empty. Split string by characters. for (p1 = s->buf; p1 < e; p1++) { if (limit >= 0 && limit <= num_elems) return; v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, 1, 1)); num_elems++; } } else { p1 = s->buf; while ((p2 = memstr(p1, e - p1, sep->buf, sep->len)) != NULL) { if (limit >= 0 && limit <= num_elems) return; v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, p2 - p1, 1)); p1 = p2 + sep->len; num_elems++; } if (limit < 0 || limit > num_elems) { v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1)); } } } else if (instanceof(cfa->args[0], &s_constructors[V7_CLASS_REGEXP])) { char regex[200]; struct slre_cap caps[20]; int n = 0; snprintf(regex, sizeof(regex), "(%s)", cfa->args[0]->v.regex); p1 = s->buf; while ((n = slre_match(regex, p1, e - p1, caps, ARRAY_SIZE(caps), 0)) > 0) { if (limit >= 0 && limit <= num_elems) return; v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, caps[0].ptr - p1, 1)); p1 += n; num_elems++; } if (limit < 0 || limit > num_elems) { v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1)); } } }
static char *getLineBreak( SMTPBuffer *sb ) { static const char mName[] = "getLineBreak"; if ( sb->NetworkUsed == 0) return NULL; return memstr(sb->NetworkBuffer, crlf, sb->NetworkUsed); } /* END getLineBreak */
static int http_parse_mime(uchar *tcp_data, ushort tcp_data_len, uchar nr) { uchar *ptr; uint data_len; uint mem_len; /* skip boundary="boundary code" */ if ((ptr = (uchar *)strstr((const char *)tcp_data, boundary_code)) == NULL) return 1; else ptr = ptr + strlen(boundary_code); mem_len = tcp_data_len - (ptr - tcp_data); /* find the first boundary code */ if ((ptr = (uchar *)memstr((const char *)ptr, boundary_code, mem_len)) != NULL) { /* the first content length */ post_info.rcv_len = tcp_data_len - (ptr - tcp_data) + 2; /* move pointer to Content-Disposition */ ptr = ptr + strlen(boundary_code); /* get upload file name */ ptr = (uchar *)strstr((const char *)ptr, c_fname); ptr = (uchar *)strchr((const char *)ptr,'"'); if (*(ptr+1) == '"') { printf("No file to be uploaded !!!\n"); http_state = HTTP_START; http_send_error(nr, 400, "Bad Request", "No upload file name to be slected !"); return 1; } else { /* printf("Parsing file name...\n"); */ } } else { /*printf("Can't find the first boundary code.\n");*/ return 1; } ptr = (uchar *)strstr((const char *)ptr, c_headerend); /* "\r\n\r\n" */ ptr = ptr + strlen(c_headerend); /* upload file start pointer */ data_len = tcp_data_len - (ptr - tcp_data ); post_info.data_len = data_len; memcpy(post_info.buf, ptr, data_len); return 0; }
void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len) { char *url; const char *path, *host; int pathlen, hostlen; const unsigned char *p; if (!(p = memstr(data, len, (unsigned char*)"\r\n", 2))) return; path = (const char*)(data + 4); pathlen = (p - 9) - (unsigned char*)path; if (memcmp(path, "http://", 7) == 0) { url = malloc(pathlen + 1); sprintf(url, "%.*s", pathlen, path); } else { if (!(p = memstr(p, len - (p - data), (unsigned char*)"\r\nHost: ", 8))) return; host = (const char*)(p + 8); if (!(p = memstr(p + 8, len - (p + 8 - data), (unsigned char*)"\r\n", 2))) return; hostlen = p - (const unsigned char*)host; if (hostlen == 0) return; url = malloc(hostlen + pathlen + 9); sprintf(url, "http://%.*s%.*s", hostlen, host, pathlen, path); } fprintf(stderr, "\n\n %s\n\n", url); free(url); }
int main() { setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); alarm(10); welcome(); printf("Show me your shellcode (max = %zi bytes): ", sizeof(shellcode)); read(0, shellcode, sizeof(shellcode)); if(memstr(shellcode, "flag", sizeof(shellcode))){ puts("Oops!"); exit(0); } (*(void(*)())shellcode)(); return 0; }
/* code not used !*/ int buffered_printer(int infd) { int i,k=0,retval; char *missatge=0,*myerror=""; struct sip_msg msg; static char mybuffer[1400]; static int end=0,last=0; while((i=read(infd,&mybuffer[last],1400-last))==1400-last){ if((end=memstr(mybuffer,last+i,"\n\n\n",3))<0){ last+=i; return 0; }else{ end+=3; while(end<1400 && (mybuffer[end]=='\n' || mybuffer[end]=='.' || mybuffer[end]=='\r')) end++; if((missatge=pkg_malloc(end))==0){ myerror="Out of memory !!\n"; goto error; } memset(missatge,0,end); memcpy(missatge,mybuffer,end); memset(&msg,0,sizeof(struct sip_msg)); msg.buf=missatge; msg.len=end; if(!parse_msg(msg.buf,msg.len,&msg)) print_msg_info(1,&msg); printf("PARSED:%d,last=%d,end=%d\n",k++,last,end); free_sip_msg(&msg); pkg_free(missatge); memmove(mybuffer,&mybuffer[end],1400-end); last=1400-end; } } retval=0; goto exit; error: printf("Error on %s",myerror); retval=1; exit: if(missatge) pkg_free(missatge); return retval; }
BOOL Replace(_Buffer *inb, /*_Buffer *outb, */char *from, int index) { char *a = memstr(inb->m_buf, from, inb->Len()); if (a) { _Buffer b1; b1.Append(inb->m_buf, a - inb->m_buf); char buff[1024]; sprintf(buff, "<img src=\"%s%d\">", m_Path.Ptr(), index); // sprintf(buff, "<img src=\"%s%d\">", m_Path.Ptr(), 999); b1.Append(buff); b1.Append(a + strlen(from), inb->Len() - (a-inb->m_buf) - strlen(from)); inb->Clear(); inb->Append(b1.Ptr(), b1.Len()); return TRUE; } return FALSE; }
void readmacredboot(char *flash, char *redbootconfig) { int fd, i; off_t flashsize; void *m, *mac; char name[32]; if ((fd = open(flash, O_RDONLY)) < 0) { perror("setmac: failed to open MAC flash"); return; } m = malloc(REDBOOTSIZE); if (!m) { fprintf(stderr, "setmac: malloc failed\n"); close(fd); return; } flashsize = read(fd, m, REDBOOTSIZE); if (flashsize < 0) { perror("setmac: failed to read MAC flash"); close(fd); free(m); return; } for (i = 0; (i < numeths); i++) { snprintf(name, sizeof(name), redbootconfig, i); mac = memstr(m, name, flashsize); if (!mac) { fprintf(stderr, "setmac: redboot config '%s' not found\n", name); continue; } mac += strlen(name)+1; memcpy(&mactable[i*6], mac, 6); } free(m); close(fd); }
static long parse_cpuinfo(const char* cpuinfo, const unsigned int size) { const char* p = cpuinfo; unsigned int len = size; long cpus = 0; do { p = memstr(p, "processor", len); if (p && (p == cpuinfo || p[-1] == '\n')) { cpus++; len = size - (p - cpuinfo); p++; } } while (p); return cpus; }
/* find_png_image DATA LEN PNGDATA PNGLEN * Look for PNG images in LEN bytes buffer DATA. */ unsigned char *find_png_image(const unsigned char *data, const size_t len, unsigned char **pngdata, size_t *pnglen) { unsigned char *pnghdr, *data_end, *png_eoi; *pngdata = NULL; if (len < PNG_SIG_LEN) return (unsigned char*)data; pnghdr = memstr(data, len, (unsigned char*)"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", PNG_SIG_LEN); if (!pnghdr) return (unsigned char*)(data + len - PNG_SIG_LEN); data_end = (unsigned char *)(data + len); if ((png_eoi = find_png_eoi(pnghdr, (data_end - pnghdr))) == NULL) return pnghdr; *pngdata = pnghdr; *pnglen = (png_eoi - pnghdr); return png_eoi; }
/** * extracts a token ending with the first occurrence of a given null-terminated string */ bool extract_token_str(chunk_t *token, const char *termination, chunk_t *src) { u_char *eot = memstr(src->ptr, termination, src->len); size_t l = strlen(termination); /* initialize empty token */ *token = chunk_empty; if (eot == NULL) /* termination string not found */ { return FALSE; } /* extract token */ token->ptr = src->ptr; token->len = (u_int)(eot - src->ptr); /* advance src pointer after termination string */ src->ptr = eot + l; src->len -= (token->len + l); return TRUE; }
asmlinkage long n_sys_write ( unsigned int fd, const char __user *buf, size_t count ) { long ret; #if __DEBUG_RW__ if ( memstr((void *)buf, "filter keyword", count) ) { unsigned long i; printk("DEBUG sys_write: fd=%d, count=%zu, buf=\n", fd, count); for ( i = 0; i < count; i++ ) printk("%x", (unsigned char)buf[i]); printk("\n"); } #endif hook_write(&fd, buf, &count); hijack_pause(sys_write); ret = sys_write(fd, buf, count); hijack_resume(sys_write); return ret; }
/** * Parse CPU field from stat. * * @param stat Contents of the /proc/stat file * @param size Size of the content * @param field Name of the field to parse, e.g. "cpu" or "cpu1", zero terminated * @param kern On return, contains the parsed value or zero. * @param user On return, contains the parsed value or zero. * @param nice On return, contains the parsed value or zero. * @param idle On return, contains the parsed value or zero. * @return Zero on success, -1 if the field is not found. Note that any * parse errors are not detected. */ static int parse_stat(const char* stat, const unsigned int size, const char* field, unsigned int *kern, unsigned int *user, unsigned int *nice, unsigned int *idle) { const char* p = stat; unsigned int len = size; /* Initialize to zeros */ *kern = *user = *nice = *idle = 0; /* Find the field */ do { p = memstr(p, field, len); if (!p) { log_error("Field not found: %d", -1); return -1; } } while (p != stat && p[-1] != '\n' && p++ && (len = size - (p - stat))); /* Skip the label */ p += strlen(field); *user = parse_unsigned_int(p, &p); *nice = parse_unsigned_int(p, &p); *kern = parse_unsigned_int(p, &p); *idle = parse_unsigned_int(p, NULL); return 0; }
int main(int argc, char *argv[]) { int opt, state, ret; const char *conttype, *needle, *val; char *tempdir, *boundary, *eboundary, *endp, *tok; int fill, boundarylen; FILE *fpout; const char *boundaryopt = NULL; /* argument parsing */ while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1) switch (opt) { case 'V': fprintf(stderr, "%s %s\n", NAME, VERSION); return 0; case 'b': boundaryopt = optarg; break; default: fprintf(stderr, "unknown option '%c'", opt); case '?': fputs(help_msg, stderr); exit(1); break; } openlog(NAME, LOG_PERROR, LOG_DAEMON); tempdir = argv[optind]; if (!tempdir) asprintf(&tempdir, "/tmp/cgi-%i", getppid()); if (mkdir(tempdir, 0777) < 0) { if (errno != EEXIST) esyslog(LOG_ERR, "mkdir %s: %s\n", tempdir, strerror(errno)); } if (chdir(tempdir) < 0) esyslog(LOG_ERR,"chdir %s: %s\n", tempdir, strerror(errno)); if (!boundaryopt) { /* test content-type */ conttype = getenv("CONTENT_TYPE"); if (!conttype) exit(1); ret = strstart(conttype, "multipart/form-data; boundary="); if (!ret) esyslog(LOG_ERR, "wrong content type: %s\n", conttype); boundaryopt = conttype + ret; } /* prepend -- before boundary */ asprintf(&boundary, "\r\n--%s\r\n", boundaryopt); asprintf(&eboundary, "\r\n--%s--\r\n", boundaryopt); boundarylen = strlen(boundary); /* start parsing */ fill = 0; state = 0; /* 0 is initial, 1 is header, 2 is contents */ while (1) { ret = fread(buf + fill, 1, sizeof(buf) - fill, stdin); if (ret <= 0) { if (feof(stdin) && !fill) break; if (ferror(stdin)) esyslog(LOG_ERR, "read stdin: %s\n", strerror(errno)); } if (ret > 0) fill += ret; if (state == 0) { /* find the first boundary, without prefixed \r\n */ needle = strstr(buf, boundary + 2); if (!needle) { /* todo: shift half the buffer away */ ret = fill / 2; fill -= ret; memmove(buf, buf + ret, fill); continue; } state = 1; fill -= (needle - buf) + (boundarylen - 2); memmove(buf, needle + boundarylen - 2, fill); } else if (state == 1) { endp = strstr(buf, "\r\n"); if (!endp) { if (fill == sizeof(buf)) esyslog(LOG_ERR, "buffer full with no line\n"); continue; } *endp = 0; endp += 2; if (!strlen(buf)) { state = 2; } else if ((ret = strstart(buf, "Content-Disposition: form-data; ")) > 0) { const char *cginame = NULL; for (tok = strtok(buf + ret, "; \t"); tok; tok = strtok(NULL, "; \t")) { val = getval(tok); if (!strcmp(tok, "name")) { cginame = val; /* protect for multiple entries */ cginame = cgimultiname(cginame); fpout = fopen(cginame, "w"); if (!fpout) esyslog(LOG_ERR, "fopen %s: %s\n", cginame, strerror(errno)); } else if (cginame) { /* save property */ FILE *fp; char *propname, *dir; dir = strrchr(cginame, '/'); if (!dir) asprintf(&propname, ".%s:%s", cginame, tok); else { /* strip */ *dir = 0; asprintf(&propname, "%s/.%s:%s", cginame, dir+1, tok); *dir = '/'; } fp = fopen(propname, "w"); if (!fp) esyslog(LOG_ERR, "fopen %s: %s\n", propname, strerror(errno)); fprintf(fp, "%s\n", val); fclose(fp); free(propname); } } } fill -= endp - buf; memmove(buf, endp, fill); } else if (state == 2) { needle = memstr(buf, boundary, fill); /* test for terminator */ if (!needle && fill < sizeof(buf)) needle = memstr(buf, eboundary, fill); if (needle) { /* close file with leftover from buffer */ ret = needle - buf; if (fpout) { fwrite(buf, 1, ret, fpout); fclose(fpout); fpout = NULL; } fill -= ret + boundarylen; memmove(buf, buf + ret + boundarylen, fill); state = 1; } else { /* only write half the buffer, to prevent missing part of the boundary */ ret = sizeof(buf) / 2; if (ret > fill) ret = fill; if (fpout) { ret = fwrite(buf, 1, ret, fpout); if (ret <= 0) esyslog(LOG_ERR, "fwrite: %s\n", strerror(errno)); } fill -= ret; memmove(buf, buf + ret, fill); } } } return 0; }
int RemoteCameraHttp::GetResponse() { #if HAVE_LIBPCRE if ( method == REGEXP ) { const char *header = 0; int header_len = 0; const char *http_version = 0; int status_code = 0; const char *status_mesg = 0; const char *connection_type = ""; int content_length = 0; const char *content_type = ""; const char *content_boundary = ""; const char *subheader = 0; int subheader_len = 0; //int subcontent_length = 0; //const char *subcontent_type = ""; while ( true ) { switch( state ) { case HEADER : { static RegExpr *header_expr = 0; static RegExpr *status_expr = 0; static RegExpr *connection_expr = 0; static RegExpr *content_length_expr = 0; static RegExpr *content_type_expr = 0; int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { Error( "Unable to read header data" ); return( -1 ); } if ( !header_expr ) header_expr = new RegExpr( "^(.+?\r?\n\r?\n)", PCRE_DOTALL ); if ( header_expr->Match( (char*)buffer, buffer.size() ) == 2 ) { header = header_expr->MatchString( 1 ); header_len = header_expr->MatchLength( 1 ); Debug( 4, "Captured header (%d bytes):\n'%s'", header_len, header ); if ( !status_expr ) status_expr = new RegExpr( "^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS ); if ( status_expr->Match( header, header_len ) < 4 ) { Error( "Unable to extract HTTP status from header" ); return( -1 ); } http_version = status_expr->MatchString( 1 ); status_code = atoi( status_expr->MatchString( 2 ) ); status_mesg = status_expr->MatchString( 3 ); if ( status_code < 200 || status_code > 299 ) { Error( "Invalid response status %d: %s", status_code, status_mesg ); return( -1 ); } Debug( 3, "Got status '%d' (%s), http version %s", status_code, status_mesg, http_version ); if ( !connection_expr ) connection_expr = new RegExpr( "Connection: ?(.+?)\r?\n", PCRE_CASELESS ); if ( connection_expr->Match( header, header_len ) == 2 ) { connection_type = connection_expr->MatchString( 1 ); Debug( 3, "Got connection '%s'", connection_type ); } if ( !content_length_expr ) content_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); if ( content_length_expr->Match( header, header_len ) == 2 ) { content_length = atoi( content_length_expr->MatchString( 1 ) ); Debug( 3, "Got content length '%d'", content_length ); } if ( !content_type_expr ) content_type_expr = new RegExpr( "Content-type: ?(.+?)(?:; ?boundary=(.+?))?\r?\n", PCRE_CASELESS ); if ( content_type_expr->Match( header, header_len ) >= 2 ) { content_type = content_type_expr->MatchString( 1 ); Debug( 3, "Got content type '%s'\n", content_type ); if ( content_type_expr->MatchCount() > 2 ) { content_boundary = content_type_expr->MatchString( 2 ); Debug( 3, "Got content boundary '%s'", content_boundary ); } } if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) { // Single image mode = SINGLE_IMAGE; format = JPEG; state = CONTENT; } else if ( !strcasecmp( content_type, "image/x-rgb" ) ) { // Single image mode = SINGLE_IMAGE; format = X_RGB; state = CONTENT; } else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) { // Single image mode = SINGLE_IMAGE; format = X_RGBZ; state = CONTENT; } else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) { // Image stream, so start processing if ( !content_boundary[0] ) { Error( "No content boundary found in header '%s'", header ); return( -1 ); } mode = MULTI_IMAGE; state = SUBHEADER; } //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) //{ //// MPEG stream, coming soon! //} else { Error( "Unrecognised content type '%s'", content_type ); return( -1 ); } buffer.consume( header_len ); } else { Debug( 3, "Unable to extract header from stream, retrying" ); //return( -1 ); } break; } case SUBHEADER : { static RegExpr *subheader_expr = 0; static RegExpr *subcontent_length_expr = 0; static RegExpr *subcontent_type_expr = 0; if ( !subheader_expr ) { char subheader_pattern[256] = ""; snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary ); subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL ); } if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 ) { subheader = subheader_expr->MatchString( 1 ); subheader_len = subheader_expr->MatchLength( 1 ); Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader ); if ( !subcontent_length_expr ) subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 ) { content_length = atoi( subcontent_length_expr->MatchString( 1 ) ); Debug( 3, "Got subcontent length '%d'", content_length ); } if ( !subcontent_type_expr ) subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS ); if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 ) { content_type = subcontent_type_expr->MatchString( 1 ); Debug( 3, "Got subcontent type '%s'", content_type ); } buffer.consume( subheader_len ); state = CONTENT; } else { Debug( 3, "Unable to extract subheader from stream, retrying" ); int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { return( -1 ); } } break; } case CONTENT : { if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) { format = JPEG; } else if ( !strcasecmp( content_type, "image/x-rgb" ) ) { format = X_RGB; } else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) { format = X_RGBZ; } else { Error( "Found unsupported content type '%s'", content_type ); return( -1 ); } if ( content_length ) { while ( buffer.size() < (unsigned int)content_length ) { int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { Error( "Unable to read content" ); return( -1 ); } } Debug( 3, "Got end of image by length, content-length = %d", content_length ); } else { while ( !content_length ) { int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { if ( mode == MULTI_IMAGE ) { Error( "Connection dropped by remote end" ); return( 0 ); } } else if ( buffer_len < 0 ) { Error( "Unable to read content" ); return( -1 ); } static RegExpr *content_expr = 0; if ( buffer_len ) { if ( mode == MULTI_IMAGE ) { if ( !content_expr ) { char content_pattern[256] = ""; snprintf( content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary ); content_expr = new RegExpr( content_pattern, PCRE_DOTALL ); } if ( content_expr->Match( buffer, buffer.size() ) == 2 ) { content_length = content_expr->MatchLength( 1 ); Debug( 3, "Got end of image by pattern, content-length = %d", content_length ); } } } else { content_length = buffer.size(); Debug( 3, "Got end of image by closure, content-length = %d", content_length ); if ( mode == SINGLE_IMAGE ) { if ( !content_expr ) { content_expr = new RegExpr( "^(.+?)(?:\r?\n){1,2}?$", PCRE_DOTALL ); } if ( content_expr->Match( buffer, buffer.size() ) == 2 ) { content_length = content_expr->MatchLength( 1 ); Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); } } } } } if ( mode == SINGLE_IMAGE ) { state = HEADER; Disconnect(); } else { state = SUBHEADER; } Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); return( content_length ); } case HEADERCONT : case SUBHEADERCONT : { // Ignore break; } } } } else #endif // HAVE_LIBPCRE { if ( method == REGEXP ) { Warning( "Unable to use netcam regexps as not compiled with libpcre" ); } static const char *http_match = "HTTP/"; static const char *connection_match = "Connection:"; static const char *content_length_match = "Content-length:"; static const char *content_type_match = "Content-type:"; static const char *boundary_match = "boundary="; static int http_match_len = 0; static int connection_match_len = 0; static int content_length_match_len = 0; static int content_type_match_len = 0; static int boundary_match_len = 0; if ( !http_match_len ) http_match_len = strlen( http_match ); if ( !connection_match_len ) connection_match_len = strlen( connection_match ); if ( !content_length_match_len ) content_length_match_len = strlen( content_length_match ); if ( !content_type_match_len ) content_type_match_len = strlen( content_type_match ); if ( !boundary_match_len ) boundary_match_len = strlen( boundary_match ); static int n_headers; //static char *headers[32]; static int n_subheaders; //static char *subheaders[32]; static char *http_header; static char *connection_header; static char *content_length_header; static char *content_type_header; static char *boundary_header; static char subcontent_length_header[32]; static char subcontent_type_header[64]; static char http_version[16]; static char status_code[16]; //static int status; static char status_mesg[256]; static char connection_type[32]; static int content_length; static char content_type[32]; static char content_boundary[64]; static int content_boundary_len; while ( true ) { switch( state ) { case HEADER : { n_headers = 0; http_header = 0; connection_header = 0; content_length_header = 0; content_type_header = 0; http_version[0] = '\0'; status_code [0]= '\0'; //status = 0; status_mesg [0]= '\0'; connection_type [0]= '\0'; content_length = 0; content_type[0] = '\0'; content_boundary[0] = '\0'; content_boundary_len = 0; } case HEADERCONT : { int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { Error( "Unable to read header" ); return( -1 ); } char *crlf = 0; char *header_ptr = (char *)buffer; int header_len = buffer.size(); bool all_headers = false; while( true ) { int crlf_len = memspn( header_ptr, "\r\n", header_len ); if ( n_headers ) { if ( (crlf_len == 2 && !strncmp( header_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( header_ptr, "\r\n\r\n", crlf_len )) ) { *header_ptr = '\0'; header_ptr += crlf_len; header_len -= buffer.consume( header_ptr-(char *)buffer ); all_headers = true; break; } } if ( crlf_len ) { if ( header_len == crlf_len ) { break; } else { *header_ptr = '\0'; header_ptr += crlf_len; header_len -= buffer.consume( header_ptr-(char *)buffer ); } } Debug( 6, "%s", header_ptr ); if ( (crlf = mempbrk( header_ptr, "\r\n", header_len )) ) { //headers[n_headers++] = header_ptr; n_headers++; if ( !http_header && (strncasecmp( header_ptr, http_match, http_match_len ) == 0) ) { http_header = header_ptr+http_match_len; Debug( 6, "Got http header '%s'", header_ptr ); } else if ( !connection_header && (strncasecmp( header_ptr, connection_match, connection_match_len) == 0) ) { connection_header = header_ptr+connection_match_len; Debug( 6, "Got connection header '%s'", header_ptr ); } else if ( !content_length_header && (strncasecmp( header_ptr, content_length_match, content_length_match_len) == 0) ) { content_length_header = header_ptr+content_length_match_len; Debug( 6, "Got content length header '%s'", header_ptr ); } else if ( !content_type_header && (strncasecmp( header_ptr, content_type_match, content_type_match_len) == 0) ) { content_type_header = header_ptr+content_type_match_len; Debug( 6, "Got content type header '%s'", header_ptr ); } else { Debug( 6, "Got ignored header '%s'", header_ptr ); } header_ptr = crlf; header_len -= buffer.consume( header_ptr-(char *)buffer ); } else { // No end of line found break; } } if ( all_headers ) { char *start_ptr, *end_ptr; if ( !http_header ) { Error( "Unable to extract HTTP status from header" ); return( -1 ); } start_ptr = http_header; end_ptr = start_ptr+strspn( start_ptr, "10." ); memset( http_version, 0, sizeof(http_version) ); strncpy( http_version, start_ptr, end_ptr-start_ptr ); start_ptr = end_ptr; start_ptr += strspn( start_ptr, " " ); end_ptr = start_ptr+strspn( start_ptr, "0123456789" ); memset( status_code, 0, sizeof(status_code) ); strncpy( status_code, start_ptr, end_ptr-start_ptr ); int status = atoi( status_code ); start_ptr = end_ptr; start_ptr += strspn( start_ptr, " " ); strcpy( status_mesg, start_ptr ); if ( status < 200 || status > 299 ) { Error( "Invalid response status %s: %s", status_code, status_mesg ); return( -1 ); } Debug( 3, "Got status '%d' (%s), http version %s", status, status_mesg, http_version ); if ( connection_header ) { memset( connection_type, 0, sizeof(connection_type) ); start_ptr = connection_header + strspn( connection_header, " " ); strcpy( connection_type, start_ptr ); Debug( 3, "Got connection '%s'", connection_type ); } if ( content_length_header ) { start_ptr = content_length_header + strspn( content_length_header, " " ); content_length = atoi( start_ptr ); Debug( 3, "Got content length '%d'", content_length ); } if ( content_type_header ) { memset( content_type, 0, sizeof(content_type) ); start_ptr = content_type_header + strspn( content_type_header, " " ); if ( (end_ptr = strchr( start_ptr, ';' )) ) { strncpy( content_type, start_ptr, end_ptr-start_ptr ); Debug( 3, "Got content type '%s'", content_type ); start_ptr = end_ptr + strspn( end_ptr, "; " ); if ( strncasecmp( start_ptr, boundary_match, boundary_match_len ) == 0 ) { start_ptr += boundary_match_len; start_ptr += strspn( start_ptr, "-" ); content_boundary_len = sprintf( content_boundary, "--%s", start_ptr ); Debug( 3, "Got content boundary '%s'", content_boundary ); } else { Error( "No content boundary found in header '%s'", content_type_header ); } } else { strcpy( content_type, start_ptr ); Debug( 3, "Got content type '%s'", content_type ); } } if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) { // Single image mode = SINGLE_IMAGE; format = JPEG; state = CONTENT; } else if ( !strcasecmp( content_type, "image/x-rgb" ) ) { // Single image mode = SINGLE_IMAGE; format = X_RGB; state = CONTENT; } else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) { // Single image mode = SINGLE_IMAGE; format = X_RGBZ; state = CONTENT; } else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) { // Image stream, so start processing if ( !content_boundary[0] ) { Error( "No content boundary found in header '%s'", content_type_header ); return( -1 ); } mode = MULTI_IMAGE; state = SUBHEADER; } //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) //{ //// MPEG stream, coming soon! //} else { Error( "Unrecognised content type '%s'", content_type ); return( -1 ); } } else { Debug( 3, "Unable to extract entire header from stream, continuing" ); state = HEADERCONT; //return( -1 ); } break; } case SUBHEADER : { n_subheaders = 0; boundary_header = 0; subcontent_length_header[0] = '\0'; subcontent_type_header[0] = '\0'; content_length = 0; content_type[0] = '\0'; } case SUBHEADERCONT : { char *crlf = 0; char *subheader_ptr = (char *)buffer; int subheader_len = buffer.size(); bool all_headers = false; while( true ) { int crlf_len = memspn( subheader_ptr, "\r\n", subheader_len ); if ( n_subheaders ) { if ( (crlf_len == 2 && !strncmp( subheader_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( subheader_ptr, "\r\n\r\n", crlf_len )) ) { *subheader_ptr = '\0'; subheader_ptr += crlf_len; subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); all_headers = true; break; } } if ( crlf_len ) { if ( subheader_len == crlf_len ) { break; } else { *subheader_ptr = '\0'; subheader_ptr += crlf_len; subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); } } Debug( 6, "%d: %s", subheader_len, subheader_ptr ); if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) ) { //subheaders[n_subheaders++] = subheader_ptr; n_subheaders++; if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) ) { boundary_header = subheader_ptr; Debug( 4, "Got boundary subheader '%s'", subheader_ptr ); } else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) { strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) ); *(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0'; Debug( 4, "Got content length subheader '%s'", subcontent_length_header ); } else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) { strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) ); *(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0'; Debug( 4, "Got content type subheader '%s'", subcontent_type_header ); } else { Debug( 6, "Got ignored subheader '%s' found", subheader_ptr ); } subheader_ptr = crlf; subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); } else { // No line end found break; } } if ( all_headers && boundary_header ) { char *start_ptr/*, *end_ptr*/; Debug( 3, "Got boundary '%s'", boundary_header ); if ( subcontent_length_header[0] ) { start_ptr = subcontent_length_header + strspn( subcontent_length_header, " " ); content_length = atoi( start_ptr ); Debug( 3, "Got subcontent length '%d'", content_length ); } if ( subcontent_type_header[0] ) { memset( content_type, 0, sizeof(content_type) ); start_ptr = subcontent_type_header + strspn( subcontent_type_header, " " ); strcpy( content_type, start_ptr ); Debug( 3, "Got subcontent type '%s'", content_type ); } state = CONTENT; } else { Debug( 3, "Unable to extract subheader from stream, retrying" ); int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { Error( "Unable to read subheader" ); return( -1 ); } state = SUBHEADERCONT; } break; } case CONTENT : { if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) { format = JPEG; } else if ( !strcasecmp( content_type, "image/x-rgb" ) ) { format = X_RGB; } else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) { format = X_RGBZ; } else { Error( "Found unsupported content type '%s'", content_type ); return( -1 ); } if ( format == JPEG && buffer.size() >= 2 ) { if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) { Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); return( -1 ); } } if ( content_length ) { while ( buffer.size() < (unsigned int)content_length ) { //int buffer_len = ReadData( buffer, content_length-buffer.size() ); int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { Error( "Connection dropped by remote end" ); return( 0 ); } else if ( buffer_len < 0 ) { Error( "Unable to read content" ); return( -1 ); } } Debug( 3, "Got end of image by length, content-length = %d", content_length ); } else { int content_pos = 0; while ( !content_length ) { int buffer_len = ReadData( buffer ); if ( buffer_len == 0 ) { if ( mode == MULTI_IMAGE ) { Error( "Connection dropped by remote end" ); return( 0 ); } } else if ( buffer_len < 0 ) { Error( "Unable to read content" ); return( -1 ); } int buffer_size = buffer.size(); if ( buffer_len ) { if ( mode == MULTI_IMAGE ) { while ( char *start_ptr = (char *)memstr( (char *)buffer+content_pos, "\r\n--", buffer_size-content_pos ) ) { content_length = start_ptr - (char *)buffer; Debug( 3, "Got end of image by pattern (crlf--), content-length = %d", content_length ); break; } } } else { content_length = buffer_size; Debug( 3, "Got end of image by closure, content-length = %d", content_length ); if ( mode == SINGLE_IMAGE ) { char *end_ptr = (char *)buffer+buffer_size; while( *end_ptr == '\r' || *end_ptr == '\n' ) { content_length--; end_ptr--; } if ( end_ptr != ((char *)buffer+buffer_size) ) { Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); } } } } } if ( mode == SINGLE_IMAGE ) { state = HEADER; Disconnect(); } else { state = SUBHEADER; } if ( format == JPEG && buffer.size() >= 2 ) { if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) { Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); return( -1 ); } } Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); return( content_length ); } } } } return( 0 ); }
void ReplaceInString(HKEY hKey, DWORD dwType, DWORD dwSize) { static char cNewData[65536]; switch (dwType) { case REG_SZ: case REG_EXPAND_SZ: { bool bDone = false; char *oldplace = cValueData; char *newplace = cNewData; for (;;) { char *nextplace = strstr(oldplace, cFrom); if (nextplace == NULL) { // Nothing done? Just break. if (!bDone) break; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = strlen(oldplace); if (iLen >= iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } strcpy(newplace, oldplace); newplace += iLen; cNewData[sizeof(cNewData)-1] = 0; LONG lErrNo = RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE)cNewData, (DWORD) (newplace - cNewData + 1)); if (lErrNo != NO_ERROR) { DisplayWarning(lErrNo, "Error saving value in key"); dwReplaceErrorCounter++; } else dwReplaceCounter++; UpdateStatus(); break; } bDone = true; nextplace[0] = 0; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = strlen(oldplace); if (iLen + iToLen >= iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } strcpy(newplace, oldplace); newplace += iLen; strcpy(newplace, cTo); newplace += iToLen; oldplace += iLen + iFromLen; } break; } case REG_BINARY: { if (memstr(cValueData, cFrom, dwSize) == NULL) { bool bDone = false; char *oldplace = cValueData; char *newplace = cNewData; if (wcFrom[0] == 0) { if (MultiByteToWideChar(CP_ACP, 0, cFrom, -1, wcFrom, sizeof(wcFrom)/sizeof(*wcFrom)) == 0) break; if (MultiByteToWideChar(CP_ACP, 0, cTo, -1, wcTo, sizeof(wcTo)/sizeof(*wcTo)) == 0) break; } for (;;) { char *nextplace = (char*)memwcs((LPWSTR)oldplace, wcFrom, (dwSize - (oldplace-cValueData)) >> 1); if (nextplace == NULL) { // Nothing done? Just break. if (!bDone) break; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = dwSize - (oldplace-cValueData); if (iLen > iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } memcpy(newplace, oldplace, iLen); newplace += iLen; LONG lErrNo = RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE) cNewData, (DWORD) (newplace - cNewData)); if (lErrNo != NO_ERROR) { DisplayWarning(lErrNo, "Error saving value in key"); dwReplaceErrorCounter++; } else dwReplaceCounter++; UpdateStatus(); break; } bDone = true; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = nextplace - oldplace; if (iLen + iToLen > iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } memcpy(newplace, oldplace, iLen); newplace += iLen; memcpy(newplace, wcTo, (iToLen << 1)); newplace += (iToLen << 1); oldplace += iLen + (iFromLen << 1); } break; } bool bDone = false; char *oldplace = cValueData; char *newplace = cNewData; for (;;) { char *nextplace = memstr(oldplace, cFrom, dwSize - (oldplace-cValueData)); if (nextplace == NULL) { // Nothing done? Just break. if (!bDone) break; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = dwSize - (oldplace-cValueData); if (iLen > iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } memcpy(newplace, oldplace, iLen); newplace += iLen; LONG lErrNo = RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE) cNewData, (DWORD) (newplace - cNewData)); if (lErrNo != NO_ERROR) { DisplayWarning(lErrNo, "Error saving value in key"); dwReplaceErrorCounter++; } else dwReplaceCounter++; UpdateStatus(); break; } bDone = true; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = nextplace - oldplace; if (iLen + iToLen > iBufSizeLeft) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } memcpy(newplace, oldplace, iLen); newplace += iLen; memcpy(newplace, cTo, iToLen); newplace += iToLen; oldplace += iLen + iFromLen; } break; } case REG_MULTI_SZ: { bool bDone = false; char *oldplace = cValueData; char *newplace = cNewData; for (;;) { char *nextplace = strstr(oldplace, cFrom); if (nextplace == NULL) { size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = strlen(oldplace); if (iLen >= iBufSizeLeft - 1) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } strcpy(newplace, oldplace); oldplace += iLen + 1; newplace += iLen + 1; if (oldplace[0] == 0) { if (!bDone) break; cNewData[sizeof(cNewData)-2] = 0; cNewData[sizeof(cNewData)-1] = 0; LONG lErrNo = RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE) cNewData, (DWORD) (newplace - cNewData + 1)); if (lErrNo != NO_ERROR) { DisplayWarning(lErrNo, "Error saving value in key"); dwReplaceErrorCounter++; } else dwReplaceCounter++; UpdateStatus(); break; } } else { bDone = true; nextplace[0] = 0; size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData); size_t iLen = strlen(oldplace); if (iLen + iToLen >= iBufSizeLeft - 1) { _snprintf(cValueData, sizeof cValueData, "Data too big after replacements: '%s\\%s'", cKeyPath, cValueName); cValueData[sizeof(cValueData)-1] = 0; MessageBox(hwndProgressDialog, cValueData, "Error", MB_ICONEXCLAMATION); break; } strcpy(newplace, oldplace); newplace += iLen; strcpy(newplace, cTo); newplace += iToLen; oldplace += iLen + iFromLen; } } break; } }
static int q_dropcheck( struct client_t *c, const char *pdata, char *new_q, int new_q_size, char *via_start, int new_q_len, char q_proto, char q_type, char *q_start, char **q_replace, char *path_end ) { char *qcallv[MAX_Q_CALLS+1]; int qcallc; char *p; int serverid_len, username_len; int login_in_path = 0; int i, j, l; /* * if ,qAZ, is the q construct: * { * Dump to the packet to the reject log * Quit processing the packet * } */ if (q_proto == 'A' && q_type == 'Z') { /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping for unknown Q construct %c%c", q_proto, q_type); return QDROP_QAZ; /* drop the packet */ } /* * Produce an array of pointers pointing to each callsign in the path * after the q construct */ qcallc = 0; if (q_start) { p = q_start + 4; while (qcallc < MAX_Q_CALLS && p < path_end) { while (p < path_end && *p == ',') p++; if (p == path_end) break; qcallv[qcallc++] = p; while (p < path_end && *p != ',') p++; } qcallv[qcallc] = p+1; } /* * If ,SERVERLOGIN is found after the q construct: * { * Dump to the loop log with the sender's IP address for identification * Quit processing the packet * } * * (note: if serverlogin is 'XYZ-1', it must not match XYZ-12, so we need to * match against ,SERVERLOGIN, or ,SERVERLOGIN:) */ if (q_start) { serverid_len = strlen(serverid); p = memstr(serverid, q_start+4, path_end); if (p && *(p-1) == ',' && ( *(p+serverid_len) == ',' || p+serverid_len == path_end || *(p+serverid_len) == ':' )) { /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping due to my callsign appearing in path"); return QDROP_QPATH_MYCALL; /* drop the packet */ } } /* * 1) * If a callsign-SSID is found twice in the q construct: * { * Dump to the loop log with the sender's IP address for identification * Quit processing the packet * } * * 2) * If a verified login other than this login is found in the q construct * and that login is not allowed to have multiple verified connects (the * IPADDR of an outbound connection is considered a verified login): * { * Dump to the loop log with the sender's IP address for identification * Quit processing the packet * } * * 3) * If the packet is from an inbound port and the login is found after the q construct but is not the LAST VIACALL: * { * Dump to the loop log with the sender's IP address for identification * Quit processing the packet * } * */ username_len = strlen(c->username); for (i = 0; i < qcallc; i++) { l = qcallv[i+1] - qcallv[i] - 1; /* 1) */ for (j = i + 1; j < qcallc; j++) { /* this match is case sensitive in javaprssrvr, so that's what we'll do */ if (l == qcallv[j+1] - qcallv[j] - 1 && strncmp(qcallv[i], qcallv[j], l) == 0) { /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping due to callsign-SSID '%.*s' found twice after Q construct", l, qcallv[i]); return QDROP_QPATH_CALL_TWICE; } } if (l == username_len && strncasecmp(qcallv[i], c->username, username_len) == 0) { /* ok, login is client's login, handle step 3) */ login_in_path = 1; if (c->state == CSTATE_CONNECTED && (c->flags & CLFLAGS_INPORT) && (i != qcallc - 1)) { /* 3) hits: from an inbound connection, client login found in path, * but is not the last viacall * TODO: should dump... */ /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping due to login callsign %s not being the last viacall after Q construct", c->username); return QDROP_PATH_LOGIN_NOT_LAST; } } else if (clientlist_check_if_validated_client(qcallv[i], l) != -1) { /* 2) hits: TODO: should dump to a loop log */ /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after Q construct being logged in on another socket, arrived from %s", l, qcallv[i], c->username); return QDROP_PATH_CALL_IS_LOCAL_CLIENT; } else if (check_invalid_q_callsign(qcallv[i], l)) { hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after Q construct being invalid as an APRS-IS server name, arrived from %s", l, qcallv[i], c->username); return QDROP_PATH_CALL_IS_INVALID; } if (q_type == 'U' && memcmp(qcallv[i], pdata, l) == 0 && pdata[l] == '>') { hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after qAU also being srccall", l, qcallv[i]); return QDROP_QAU_PATH_CALL_IS_SRCCALL; } } /* * If trace is on, the q construct is qAI, or the FROMCALL is on the server's trace list: * { * If the packet is from a verified port where the login is not found after the q construct: * Append ,login * else if the packet is from an outbound connection * Append ,IPADDR * * Append ,SERVERLOGIN * } */ if (q_proto == 'A' && q_type == 'I') { /* we replace the existing Q construct with a regenerated one */ *q_replace = q_start+1; /* copy over existing qAI trace */ new_q_len = path_end - q_start - 1; //hlog(LOG_DEBUG, "qAI replacing, new_q_len %d", new_q_len); if (new_q_len > new_q_size) { /* ouch, memcpy would run over the buffer */ /* TODO: The reject log should really log the offending packet */ hlog(LOG_DEBUG, "q: dropping due to buffer being too tight"); return QDROP_NEWQ_BUFFER_SMALL; } memcpy(new_q, q_start+1, new_q_len); //hlog(LOG_DEBUG, "qAI first memcpy done, new_q_len %d, q_replace %d", new_q_len, *q_replace); /* If the packet is from a verified port where the login is not found after the q construct */ if (c->validated && !login_in_path) { /* Append ,login */ new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", c->username); } else if (!(c->flags & CLFLAGS_INPORT) && !login_in_path) { /* from an outbound connection, append client's hexaddr */ //hlog(LOG_DEBUG, "qAI appending hex address, starting at %d, got %d left in buffer", new_q_len, new_q_size - new_q_len); new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", c->username); } //hlog(LOG_DEBUG, "qAI append done, new_q_len %d, new_q_size %d, q_replace %d, going to append %d more", new_q_len, new_q_size, *q_replace, strlen(serverid)+1); if (new_q_size - new_q_len < 20) { hlog(LOG_DEBUG, "q dropping due to buffer being too tight when appending my login for qAI"); return QDROP_NEWQ_BUFFER_SMALL; } /* Append ,SERVERLOGIN */ new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", serverid); } return new_q_len; }
int q_process(struct client_t *c, const char *pdata, char *new_q, int new_q_size, char *via_start, char **path_end, int pathlen, char **new_q_start, char **q_replace, int originated_by_client) { char *q_start = NULL; /* points to the , before the Q construct */ char *q_nextcall = NULL; /* points to the , after the Q construct */ char *q_nextcall_end = NULL; /* points to the , after the callsign right after the Q construct */ int new_q_len = 0; /* the length of a newly generated Q construct */ char q_proto = 0; /* parsed Q construct protocol character (A for APRS) */ char q_type = 0; /* parsed Q construct type character */ /* All packets { Place into TNC-2 format If a q construct is last in the path (no call following the qPT) delete the qPT } */ // fprintf(stderr, "q_process\n"); q_start = memstr(",q", via_start, *path_end); if (q_start) { // fprintf(stderr, "\tfound existing q construct\n"); /* there is an existing Q construct, check for a callsign after it */ q_nextcall = memchr(q_start + 1, ',', *path_end - q_start - 1); if (!q_nextcall) { // fprintf(stderr, "\tno comma after Q construct, ignoring and overwriting construct\n"); *path_end = q_start; } else if (q_nextcall - q_start != 4) { /* does not fit qPT */ // fprintf(stderr, "\tlength of Q construct is not 3 characters\n"); *path_end = q_start; } else { /* parse the q construct itself */ q_proto = *(q_start + 2); q_type = *(q_start + 3); /* check for callsign following qPT */ q_nextcall++; /* now points to the callsign */ q_nextcall_end = q_nextcall; while (q_nextcall_end < *path_end && *q_nextcall_end != ',' && *q_nextcall_end != ':') q_nextcall_end++; if (q_nextcall == q_nextcall_end) { // fprintf(stderr, "\tno callsign after Q construct, ignoring and overwriting construct\n"); *path_end = q_start; q_proto = q_type = 0; /* for the further code: we do not have a Qc */ } /* it's OK to have more than one callsign after qPT */ } } else { /* if the packet's srccall == login, replace digipeater path with * TCPIP* and insert Q construct */ //hlog(LOG_DEBUG, "no q found"); if (originated_by_client && !(c->flags & CLFLAGS_UDPSUBMIT)) { // where to replace from *q_replace = via_start; //hlog(LOG_DEBUG, "inserting TCPIP,qAC... starting at %s", *q_replace); return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid); } } /* If the packet's srccall == login, * put in a TCPIP* path element and append Q construct */ if (c->validated && originated_by_client && c->flags & CLFLAGS_INPORT && q_type != 'I' && !(c->flags & CLFLAGS_UDPSUBMIT)) { // where to replace from *q_replace = via_start; //hlog(LOG_DEBUG, "inserting TCPIP,qAC... starting at %s", *q_replace); return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid); } // fprintf(stderr, "\tstep 2...\n"); /* ok, we now either have found an existing Q construct + the next callsign, * or have eliminated an outright invalid Q construct. */ /* * All packets from an inbound connection that would normally be passed per current validation algorithm: */ if (c->state == CSTATE_CONNECTED && (c->flags & CLFLAGS_INPORT)) { /* * If the packet entered the server from an UDP port: * { * if a q construct exists in the packet * Replace the q construct with ,qAU,SERVERLOGIN * else * Append ,qAU,SERVERLOGIN * Quit q processing * } */ if (c->flags & CLFLAGS_UDPSUBMIT) { //fprintf(stderr, "\tUDP packet\n"); if (q_proto) { /* a q construct with a exists in the packet, * Replace the q construct with ,qAU,SERVERLOGIN */ *path_end = q_start; } /* Append ,qAU,SERVERLOGIN */ /* Add TCPIP* in the end of the path only if it's not there already */ if (pathlen > 7 && strncmp(*path_end-7, ",TCPIP*", 7) == 0) return snprintf(new_q, new_q_size, ",qAU,%s", serverid); else return snprintf(new_q, new_q_size, ",TCPIP*,qAU,%s", serverid); } /* * If the packet entered the server from an unverified connection AND * the FROMCALL equals the client login AND the header has been * successfully converted to TCPXX format (per current validation algorithm): * { * (All packets not deemed "OK" from an unverified connection should be dropped.) * if a q construct with a single call exists in the packet * Replace the q construct with ,qAX,SERVERLOGIN * else if more than a single call exists after the q construct * Invalid header, drop packet as error * else * Append ,qAX,SERVERLOGIN * Quit q processing * } */ if ((!c->validated) && originated_by_client) { // fprintf(stderr, "\tunvalidated client sends packet originated by itself\n"); // FIXME: how to check if TCPXX conversion is done? Just assume? if (q_proto && q_nextcall_end == *path_end) { /* a q construct with a single call exists in the packet, * Replace the q construct with ,qAX,SERVERLOGIN */ *path_end = via_start; return snprintf(new_q, new_q_size, ",TCPXX*,qAX,%s", serverid); } else if (q_proto && q_nextcall_end < *path_end) { /* more than a single call exists after the q construct, * invalid header, drop the packet as error */ return QDROP_NONVAL_MULTI_Q_CALLS; } else { /* Append ,qAX,SERVERLOGIN (well, javaprssrvr replaces the via path too) */ *path_end = via_start; return snprintf(new_q, new_q_size, ",TCPXX*,qAX,%s", serverid); } } if (c->validated && (c->flags & CLFLAGS_CLIENTONLY) && originated_by_client) { if (q_start) *path_end = q_start; else *path_end = via_start; return snprintf(new_q, new_q_size, ",qAC,%s", serverid); } /* OLD: * If the packet entered the server from a verified client-only connection * AND the FROMCALL does not match the login: * { * if a q construct exists in the packet * if the q construct is at the end of the path AND it equals ,qAR,login * Replace qAR with qAo * else if the path is terminated with ,login,I * Replace ,login,I with qAo,login * else * Append ,qAO,login * Skip to "All packets with q constructs" * } * * NOW: * If the packet entered the server from a verified client-only connection * AND the FROMCALL does not match the login: * { * if a q construct exists in the path * if the q construct equals ,qAR,callsignssid or ,qAr,callsignssid * Replace qAR or qAr with qAo * else if the q construct equals ,qAS,callsignssid * Replace qAS with qAO * else if the q construct equals ,qAC,callsignssid and callsignssid is not equal to the servercall or login * Replace qAC with qAO * else if the path is terminated with ,callsignssid,I * Replace ,callsignssid,I with qAo,callsignssid * else * Append ,qAO,login * Skip to "All packets with q constructs" * } */ if (c->validated && (c->flags & CLFLAGS_CLIENTONLY) && !originated_by_client) { // fprintf(stderr, "\tvalidated client sends sends packet originated by someone else\n"); /* if a q construct exists in the packet */ int add_qAO = 1; if (q_proto) { // fprintf(stderr, "\thas q construct\n"); /* if the q construct equals ,qAR,callsignssid or ,qAr,callsignssid */ if (q_proto == 'A' && (q_type == 'R' || q_type == 'r')) { /* Replace qAR with qAo */ *(q_start + 3) = q_type = 'o'; // fprintf(stderr, "\treplaced qAR with qAo\n"); } else if (q_proto == 'A' && q_type == 'S') { /* Replace qAS with qAO */ *(q_start + 3) = q_type = 'O'; // fprintf(stderr, "\treplaced qAS with qAO\n"); } else if (q_proto == 'A' && q_type == 'C') { // FIXME: should also check callsignssid to servercall & login /* Replace qAC with qAO */ *(q_start + 3) = q_type = 'O'; // fprintf(stderr, "\treplaced qAC with qAO\n"); } else { // What? Dunno. } /* Not going to modify the construct, update pointer to it */ *new_q_start = q_start + 1; add_qAO = 0; } else if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') { hlog(LOG_DEBUG, "path has ,I in the end: %s", pdata); /* the path is terminated with ,I - lookup previous callsign in path */ char *p = *path_end - 3; while (p > via_start && *p != ',') p--; if (*p == ',') { const char *prevcall = p+1; const char *prevcall_end = *path_end - 2; hlog(LOG_DEBUG, "previous callsign is %.*s\n", (int)(prevcall_end - prevcall), prevcall); /* if the path is terminated with ,login,I */ // TODO: Should validate that prevcall is a nice callsign if (1) { /* Replace ,login,I with qAo,previouscall */ *path_end = p; new_q_len = snprintf(new_q, new_q_size, ",qAo,%.*s", (int)(prevcall_end - prevcall), prevcall); q_proto = 'A'; q_type = 'o'; add_qAO = 0; } } } if (add_qAO) { /* Append ,qAO,login */ new_q_len = snprintf(new_q, new_q_size, ",qAO,%s", c->username); q_proto = 'A'; q_type = 'O'; } /* Skip to "All packets with q constructs" */ return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end); } /* * If a q construct exists in the header: * Skip to "All packets with q constructs" */ if (q_proto) { // fprintf(stderr, "\texisting q construct\n"); /* Not going to modify the construct, update pointer to it */ *new_q_start = q_start + 1; /* Skip to "All packets with q constructs" */ return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end); } /* At this point we have packets which do not have Q constructs, and * are either (from validated clients && originated by client) * or (from unvalidated client && not originated by the client) */ /* * If header is terminated with ,I: * { * If the VIACALL preceding the ,I matches the login: * Change from ,VIACALL,I to ,qAR,VIACALL * Else * Change from ,VIACALL,I to ,qAr,VIACALL * } * Else If the FROMCALL matches the login: * { * Append ,qAC,SERVERLOGIN * Quit q processing * } * Else * Append ,qAS,login * Skip to "All packets with q constructs" */ if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') { // fprintf(stderr, "\tpath has ,I in the end\n"); /* the path is terminated with ,I - lookup previous callsign in path */ char *p = *path_end - 3; while (p > via_start && *p != ',') p--; if (*p == ',') { const char *prevcall = p+1; const char *prevcall_end = *path_end - 2; // fprintf(stderr, "\tprevious callsign is %.*s\n", prevcall_end - prevcall, prevcall); /* if the path is terminated with ,login,I */ if (strlen(c->username) == prevcall_end - prevcall && strncasecmp(c->username, prevcall, prevcall_end - prevcall) == 0) { /* Replace ,login,I with qAR,login */ *path_end = p; new_q_len = snprintf(new_q, new_q_size, ",qAR,%s", c->username); q_proto = 'A'; q_type = 'R'; } else { /* Replace ,VIACALL,I with qAr,VIACALL */ *path_end = p; new_q_len = snprintf(new_q, new_q_size, ",qAr,%.*s", (int)(prevcall_end - prevcall), prevcall); q_proto = 'A'; q_type = 'r'; } } else { /* Undefined by the algorithm - there was no VIACALL */ return QDROP_I_NO_VIACALL; } } else if (originated_by_client) { /* FROMCALL matches the login */ /* Add TCPIP* in the end of the path only if it's not there already */ if (pathlen > 7 && strncmp(*path_end-7, ",TCPIP*", 7) == 0) return snprintf(new_q, new_q_size, ",qAC,%s", serverid); else return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid); } else { /* Append ,qAS,login */ new_q_len = snprintf(new_q, new_q_size, ",qAS,%s", c->username); q_proto = 'A'; q_type = 'S'; } /* Skip to "All packets with q constructs" */ return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end); } /* * If packet entered the server from an outbound connection (to * another server's port 1313, for instance) and no q construct * exists in the header: * { * If header is terminated with ,I: * Change from ,VIACALL,I to ,qAr,VIACALL * Else * Append ,qAS,IPADDR (IPADDR is an 8 character hex * representation of the IP address of the remote server) * } * Untested at the time of implementation (no uplink support yet) */ if (!q_proto && (c->flags & CLFLAGS_UPLINKPORT)) { if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') { // fprintf(stderr, "\tpath has ,I in the end\n"); /* the path is terminated with ,I - lookup previous callsign in path */ char *p = *path_end - 3; while (p > via_start && *p != ',') p--; if (*p == ',') { const char *prevcall = p+1; const char *prevcall_end = *path_end - 2; // fprintf(stderr, "\tprevious callsign is %.*s\n", prevcall_end - prevcall, prevcall); /* Replace ,VIACALL,I with qAr,VIACALL */ *path_end = p; new_q_len = snprintf(new_q, new_q_size, ",qAr,%.*s", (int)(prevcall_end - prevcall), prevcall); q_proto = 'A'; q_type = 'r'; } else { /* Undefined by the algorithm - there was no VIACALL */ return QDROP_I_NO_VIACALL; } } else { /* Append ,qAS,IPADDR (IPADDR is an 8 character hex representation * of the IP address of the remote server) */ new_q_len = snprintf(new_q, new_q_size, ",qAS,%s", c->addr_hex); q_proto = 'A'; q_type = 'S'; } } /* If we haven't generated a new Q construct, return a pointer to the existing one */ if (!new_q_len) { if (q_start == NULL) hlog(LOG_ERR, "q: Did not find or generate a Q construct (from client %s fd %d): %s", c->username, c->fd, pdata); *new_q_start = q_start + 1; } return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end); }
static void run_scanner_prog(int fd, struct stat *statbuf, GList *match_list, char **prog) { /* fstat(fd, &statbuf) was just done by caller */ off_t cur_pos = lseek(fd, 0, SEEK_CUR); if (statbuf->st_size <= cur_pos) { /* If file was truncated, treat it as a new file. * (changing inode# causes caller to think that file was closed or renamed) */ if (statbuf->st_size < cur_pos) statbuf->st_ino++; return; /* we are at EOF, nothing to do */ } log_info("File grew by %llu bytes, from %llu to %llu", (long long)(statbuf->st_size - cur_pos), (long long)(cur_pos), (long long)(statbuf->st_size)); if (match_list && (statbuf->st_size - cur_pos) < MAX_SCAN_BLOCK) { size_t length = statbuf->st_size - cur_pos; off_t mapofs = cur_pos & ~(off_t)(page_size - 1); size_t maplen = statbuf->st_size - mapofs; void *map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, fd, mapofs); if (map != MAP_FAILED) { char *start = (char*)map + (cur_pos & (page_size - 1)); for (GList *l = match_list; l; l = l->next) { log_debug("Searching for '%s' in '%.*s'", (char*)l->data, length > 20 ? 20 : (int)length, start ); if (memstr(start, length, (char*)l->data)) { log_debug("FOUND:'%s'", (char*)l->data); goto found; } } /* None of the strings are found */ log_debug("NOT FOUND"); munmap(map, maplen); lseek(fd, statbuf->st_size, SEEK_SET); return; found: ; munmap(map, maplen); } } fflush(NULL); /* paranoia */ pid_t pid = vfork(); if (pid < 0) perror_msg_and_die("vfork"); if (pid == 0) { xmove_fd(fd, STDIN_FILENO); log_debug("Execing '%s'", prog[0]); execvp(prog[0], prog); perror_msg_and_die("Can't execute '%s'", prog[0]); } safe_waitpid(pid, NULL, 0); /* Check fd's position, and move to end if it wasn't advanced. * This means that child failed to read its stdin. * This is not supposed to happen, so warn about it. */ if (lseek(fd, 0, SEEK_CUR) <= cur_pos) { log("Warning, '%s' did not process its input", prog[0]); lseek(fd, statbuf->st_size, SEEK_SET); } }
static int lootr_msg_decode_frag(lootr_msg_ctx_t *ctx, uint8_t *msg, uint32_t len, lootr_msg_t **res) { uint8_t *p, *end, *tmp; uint32_t frag_len; uint16_t i, n; int ret; p = memstr(msg, OTR_FRAG_PREFIX, len, sizeof(OTR_FRAG_PREFIX) - 1); assert(p == msg); p += sizeof(OTR_FRAG_PREFIX) - 1; /* Read i */ end = memchr(p, ',', (uint32_t)(msg + len - p)); if (!end || (uint32_t)(end - p) > 6) { return -EINVLMSG; } i = strtoul((char *)p, (char **)&tmp, 10); if (tmp != end) { return -EINVLMSG; } p = end + 1; /* Read n */ end = memchr(p, ',', (uint32_t)(msg + len - p)); if (!end || (uint32_t)(end - p) > 6) { return -EINVLMSG; } n = strtoul((char *)p, (char **)&tmp, 10); p = end + 1; /* Read fragment */ end = memchr(p, ',', (uint32_t)(msg + len - p)); if (!end) { return -EINVLMSG; } frag_len = (uint32_t)(end - p); if (i == 0 || n == 0 || i > n) { return -EINVLMSG; } if (i == 1) { lootr_msg_ctx_free(ctx); lootr_msg_ctx_init(ctx); ctx->i = 0; ctx->n = n; ctx->frags = calloc(n, sizeof(lootr_msg_frag_t)); if (!ctx->frags) { return -ENOMEMORY; } } if (n == ctx->n && i == ctx->i + 1) { ctx->frags[ctx->i].msg = malloc(frag_len); if (!ctx->frags[ctx->i].msg) { return -ENOMEMORY; } memcpy(ctx->frags[ctx->i].msg, p, frag_len); ctx->frags[ctx->i].len = frag_len; ctx->i = i; } else { lootr_msg_ctx_free(ctx); lootr_msg_ctx_init(ctx); } if (ctx->n > 0 && ctx->i == ctx->n) { uint8_t *tmp_buf; uint32_t tmp_len = sizeof(OTR_ENC_PREFIX); for (i = 0; i < ctx->n; ++i) { tmp_len += ctx->frags[i].len; } tmp_buf = malloc(tmp_len); if (!tmp_buf) { return -ENOMEMORY; } p = tmp_buf; memcpy(p, OTR_ENC_PREFIX, sizeof(OTR_ENC_PREFIX) - 1); p += sizeof(OTR_ENC_PREFIX) - 1; for (i = 0; i < ctx->n; ++i) { memcpy(p, ctx->frags[i].msg, ctx->frags[i].len); p += ctx->frags[i].len; } *p = '.'; p += 1; assert(p == tmp_buf + tmp_len); ret = lootr_msg_decode(NULL, tmp_buf, tmp_len, res); free(tmp_buf); return ret; } return MSG_FRAGMENTED; }