/* ********************************** * Websocket * **********************************/ static int do_ws_handshake(evhtp_request_t *req) { const char *upgrade = evhtp_header_find(req->headers_in, "Upgrade"); const char *connection = evhtp_header_find(req->headers_in, "Connection"); const char *ws_key = evhtp_header_find(req->headers_in, "Sec-WebSocket-Key"); if (upgrade && connection && ws_key) { if (!strstrcase(upgrade, "websocket") || !strstrcase(connection, "Upgrade")){ return EVHTP_RES_ERROR; } static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; unsigned char *str = calloc(strlen(ws_key)+strlen(magic)+1, sizeof(unsigned char)); strcpy((char *)str, ws_key); strcat((char *)str, magic); unsigned char hash[SHA_DIGEST_LENGTH]; SHA1(str, strlen((char *)str), hash); free(str); char ws_accept[29]; ws_accept[28] = '\0'; base64encode(&hash[0], sizeof(hash), &ws_accept[0], sizeof(ws_accept)-1); ws_headers_add_header(req->headers_out, "Connection", "Upgrade" ); ws_headers_add_header(req->headers_out, "Sec-WebSocket-Accept", &ws_accept[0]); ws_headers_add_header(req->headers_out, "Upgrade", "websocket"); evhtp_send_reply(req, EVHTP_RES_SWITCH_PROTO); return EVHTP_RES_SWITCH_PROTO; } return EVHTP_RES_OK; }
/** tList* strstrcase_back_tList(tList* pl, const char* key, int len, int no) char*型変数による後方からのノードの部分文字列サーチ.大文字小文字を無視. ポインタ pl以降のノードで,キー部の文字列または keyの文字列が相手の文字列に含まれる ノードの内,後ろから数えて no番目にあるのを捜し出す. @param pl サーチを開始するノードへのポインタ. @param key サーチキー. @param len 0以上: key が plのキーに含まれるかどうか検査する. @param len 負数: plのキーが Keyに含まれるかどうか検査する. @param no 一致した物の中で後ろから数えて何番目の物を返すか指定する.1から数える. @return 一致したノードへのポインタ @retval NULL 一致したものが無い */ tList* strstrcase_back_tList(tList* pl, const char* key, int len, int no) { int nn = 0; if (no<=0) no = 1; pl = find_tList_end(pl); while (pl!=NULL) { if (len>=0) { if (strstrcase((char*)(pl->ldat).key.buf, key)!=NULL) { nn++; if (no==nn) return pl; } } else if (len<0) { if (strstrcase(key, (char*)(pl->ldat).key.buf)!=NULL) { nn++; if (no==nn) return pl; } } pl = pl->prev; } return NULL; }
// fil="" : vérifier si règle déja enregistrée int checkrobots(robots_wizard* robots,char* adr,char* fil) { while(robots) { if (strfield2(robots->adr,adr)) { if (fil[0]) { int ptr=0; char line[250]; if (strnotempty(robots->token)) { do { ptr+=binput(robots->token+ptr,line,200); if (line[0]=='/') { // absolu if (strfield(fil,line)) { // commence avec ligne return -1; // interdit } } else { // relatif if (strstrcase(fil,line)) { return -1; } } } while( (strnotempty(line)) && (ptr<(int) strlen(robots->token)) ); } } else { return -1; } } robots=robots->next; } return 0; }
/** int replace_sip_contact(tList* lp, char* host, unsigned short port) Contactヘッダのアドレス部を host:portまたは hostに書き換える. */ void replace_sip_contact(tList* lp, char* host, unsigned short port) { char contct[LBUF]; char hostport[LBUF]; if (lp==NULL || host==NULL) return; tList* lc = strncasecmp_tList(lp, (char*)"Contact", 0, 1); if (lc==NULL || lc->ldat.val.buf==NULL) return; char* pa = (char*)lc->ldat.val.buf; char* ps = strstrcase(pa, "sip:"); while (ps!=NULL) { char* pp = strstr(ps, "@"); if (pp==NULL) pp = ps + 3; pp++; //int i, cnt=0; int i; for (i=0; i<LBUF-1; i++) { //if (*pp==':') cnt++; if (*pp=='\0' || *pp=='>' || *pp==' ' || *pp==';') break; contct[i] = *pp; pp++; } contct[i] = '\0'; if (i<LBUF-1) { //if (cnt==1 && port!=0) snprintf(hostport, LBUF, "%s:%d", host, port); //else snprintf(hostport, LBUF, "%s", host); if (port!=0) snprintf(hostport, LBUF, "%s:%d", host, port); else snprintf(hostport, LBUF, "%s", host); hostport[LBUF-1] = '\0'; Buffer buf = replace_sBuffer(lc->ldat.val, contct, hostport); free_Buffer(&lc->ldat.val); lc->ldat.val = buf; } ps = strstrcase(pp, "sip:"); } return; }
/** Buffer get_sip_via_address(tList* lp, int no) no番目の Viaヘッダから有効なレスポンスアドレスを獲得する.received=,rport= 対応. @return host:port 形式のアドレス. */ Buffer get_sip_via_address(tList* lp, int no) { char* pp; Buffer buf = init_Buffer(); if (lp==NULL) return buf; if (no<=0) no = 1; buf = search_protocol_header_item(lp, (char*)"Via", no, ' ', 2); if (buf.buf!=NULL) { // received, rport Buffer wrk = dup_Buffer(buf); pp = strstrcase((char*)wrk.buf, "received="); if (pp!=NULL) { char* pa = pp = pp + 9; while (*pp!=';' && *pp!='\0') pp++; if (*pp==';') *pp = '\0'; pp = strstrcase((char*)buf.buf, "rport="); if (pp!=NULL) { char* pt = pp = pp + 6; while (*pp!=';' && *pp!='\0') pp++; if (*pp==';') *pp = '\0'; Buffer hostport = comp_hostport(pa, (unsigned short)atoi(pt)); free_Buffer(&buf); free_Buffer(&wrk); return hostport; } } free_Buffer(&wrk); // pp = (char*)buf.buf; while (*pp!=';' && *pp!='\0') pp++; if (*pp==';') *pp = '\0'; } return buf; }
/** void insert_sip_record_route(tList* lp, char* host, unsigned short port, int add_mode) Record-Route ヘッダを追加する. */ void insert_sip_record_route(tList* lp, char* host, unsigned short port, int add_mode) { char ftag[LBUF]; char sipuri[LBUF]; tList* pm; if (lp==NULL || host==NULL) return; ftag[0] = '\0'; pm = strncasecmp_tList(lp, (char*)"Record-Route", 0, 1); if (pm==NULL) { if (add_mode) pm = strncmp_tList(lp, (char*)HDLIST_FIRST_LINE_KEY, 0, 1); if (pm==NULL) return; } else if (pm->prev!=NULL) { char* pp = strstrcase((char*)pm->ldat.val.buf, "ftag="); if (pp!=NULL) { pp = pp + 5; int i = 0; while (pp[i]!='\0' && pp[i]!=';' && pp[i]!='>' && i<LBUF) { ftag[i] = pp[i]; i++; } ftag[i] = '\0'; } pm = pm->prev; } else return; if (port!=0) { if (ftag[0]!='\0') snprintf(sipuri, LBUF, "<sip:%s:%d;ftag=%s;lr=on>", host, port, ftag); else snprintf(sipuri, LBUF, "<sip:%s:%d;lr=on>", host, port); } else { if (ftag[0]!='\0') snprintf(sipuri, LBUF, "<sip:%s;ftag=%s;lr=on>", host, ftag); else snprintf(sipuri, LBUF, "<sip:%s;lr=on>", host); } sipuri[LBUF-1] = '\0'; // to make sure add_tList_node_str(pm, "Record-Route", sipuri); return; }
/** tList* get_mime_filename(FILE* fp, char* bndry) ファイルから mime boundaryを探し出し,Content-Type行の内容をリストに格納して返す. 複数行に渡る場合も結合して返す. @param fp ファイルポインタ @param bndry '––' + MIMEの境界文字列 @return キー部にファイル名の入ったリスト */ tList* get_mime_filename(FILE* fp, char* bndry) { tList* lp = NULL; tList* ln = NULL; char* pt; Buffer mime, buf; fseek(fp, 0, SEEK_SET); buf = make_Buffer(LBUF); fgets_Buffer(&buf, fp); // ファイルから MIMEヘッダを抽出 while (!feof(fp)) { if (!strcmp((char*)buf.buf, bndry)) { // mime boundary を見つけた fgets_Buffer(&buf, fp); while(!feof(fp)) { ln = lp; lp = get_protocol_header_list_seq(lp, buf, ';', FALSE, FALSE); fgets_Buffer(&buf, fp); if (ln==lp) break; } } else { fgets_Buffer(&buf, fp); } } free_Buffer(&buf); lp = find_tList_top(lp); mime = init_Buffer(); // MIME_CONTEMT_LINE を取り出す. if (lp!=NULL) { int i, nn = 1; tList* lt = NULL; ln = NULL; Loop { mime = search_protocol_header(lp, (char*)MIME_CONTENT_LINE, nn); if (mime.buf==NULL) break; pt = strstrcase((char*)mime.buf, MIME_NAMEEQ_LINE); // name= if (pt!=NULL) { pt += strlen(MIME_NAMEEQ_LINE); } else { pt = strstrcase((char*)mime.buf, MIME_FILENAMESTAR_LINE); // filename* if (pt!=NULL) { i = 0; while(pt[i]!='\0' && pt[i]!='=') i++; if (pt[i]=='=') pt += i + 1; } } if (pt!=NULL) { pt = decode_mime_string(pt); // デコード if (pt!=NULL) { // リストに格納 lt = add_tList_node_str(lt, pt, NULL); if (ln==NULL) ln = lt; free(pt); } } nn++; free_Buffer(&mime); } }