strtok()、strstr()などで

解決


Jack06  2006-02-03 21:06:29  No: 60643

長くなりますがお力をお貸しください。
Cのコンソールアプリ@VC6.0です。

172.20.1.46,2090,61.121.100.107,80,20060202115041
..GET /aaa/bbb/ccc.cgi HTTP/1.1..Accept: */*..Accept-Language: ja..Accept-Encoding: gzip, deflate..User-Agent: Mozilla/4.0 (ddd; eee; fff)..Host: ggg.hhh.com..Connection: Keep-Alive..Cookie: opqrstuvwxyz.....
172.20.1.46,2091,61.121.100.107,80,20060202115044
..GET /sss/ttt/uuu.cgi HTTP/1.1..User-Agent: Mozilla/4.0 (ddd; eee; fff)..Host: ggg.hhh.com..Cookie: abcdefghijk.....

奇数行に「自IP、ポート、相手IP、ポート、日時」が「,」という文字区切りで
偶数行にリファラーやUAなどのパケット情報が「..」という文字列区切りで
以下繰り返し表示されている。

上記のような内容のテキストファイルが
実行ファイル直下のtxtフォルダに多くありまして、
[IP、ポート]
  172.20.1.46, 2090 − 61.121.100.107 ,80
[Get]
  /aaa/bbb/ccc.cgi HTTP/1.1  
[Referer]

[User-Agent]
  Mozila/4.00 (ddd; eee; fff)
[Host]
  ggg.hhh.com

のように必要な部分だけを画面に表示したいのです。
奇数行はstrtok()で「,」で分割
複数行については
http://sometime.minidns.net/~ccgi/ref/strsplit.html
上記URLのstrsplit()関数を利用して「,,」で分割後
strstr()関数でGETやRefererといった文字列を探して表示させようと
考えていますがうまくいきません。

最初のファイルを読み込み必要な情報のみ表示し、
矢印キーなどで切り替え表示、ファイルエンドであれば
同じ日付の次のファイルを表示といったループにしたいのです。

int a,i = 0;
cDel[] = {0};
char str[8][512] = {0};
FILE *fp;
char* e_head = str[a]; // 最初は文字列の先頭を代入
char *token;
char elem[10][512];
char* next;
int iHeadCnt = 0;
char *p1, *p2, *p3, *p4;
char x[][16] = {"GET ","Referer:","User-Agent:","Host:"};

for (a=0;(fgets(str[a], 512, fp) != NULL);a++) {
  // 1行目(IP、ポート)取得
  fgets(str[a], 512, fp);

  printf("  [自IP, 自ポート − 相手IP, 相手ポート]\n");

  // トークンを取得 1行目IP、ポート表示
  token = strtok( str[a], cDel );
  printf("    %s", token);
  token = strtok( NULL, cDel );
  printf(", %s", token);
  token = strtok( NULL, cDel );
  printf(" − %s", token);
  token = strtok( NULL, cDel );
  printf(", %s\n\n", token);

  a++;

  // 2行目各情報取得
  fgets(str[a], 1024, fp);

  // 2行目を".."で分割
  for(i=0 ; (next=StrSplit(e_head,"..")) != NULL ; i++) {
    sprintf(elem[i],"%s",e_head);
    e_head = next;
    iHeadCnt++;
  }
  sprintf(elem[i],"%s",e_head);

  // [Get]
  puts("  [Get]");
  for(i=0; i<iHeadCnt; i++) {
    p1 = strstr(elem[i], x[0]);
    if (p1 != NULL) {
      printf("    %s\n\n",p1+4);
    break;
    }
  }

  // [Referer]
  puts("  [Referer]");
  for(i=0; i<=iHeadCnt; i++) {
    p2 = strstr(elem[i], x[1]);
    if (p2 != NULL) {
      printf("    %s\n\n",p2+8);
    break;
    }
  }
  
  // 省略
}


KING・王  2006-02-03 21:50:33  No: 60644

> strstr()関数でGETやRefererといった文字列を探して表示させようと
> 考えていますがうまくいきません。

どこで、どのように上手くいきませんか?

あまり詳しくは見ていませんが、とりあえず気づいた点をいくつか。

> for (a=0;(fgets(str[a], 512, fp) != NULL);a++) {
>    // 1行目(IP、ポート)取得
>    fgets(str[a], 512, fp);

これって、1行目を読み飛ばしませんか?

> char elem[10][512];
> (中略)
> // 2行目を".."で分割
> for(i=0 ; (next=StrSplit(e_head,"..")) != NULL ; i++) {
>     sprintf(elem[i],"%s",e_head);

2行目の中に".."が11個以上出てきた場合、メモリ破壊しませんか?
(".."が11個以上存在する可能性が皆無なら、問題ありませんが。)

>    // 1行目(IP、ポート)取得
>    fgets(str[a], 512, fp);
>  (中略)
>    // 2行目各情報取得
>    fgets(str[a], 1024, fp);

fgets()が成功したかのエラーチェックがありませんが、問題ありませんか?

ぱっと見、こんなところで。

まずデバッガで、ステップ実行しながら、どこまでが、Jack06さんの考えているとおりに動いており、
どの時点でおかしくなるかを確認しましょう。


Jack06  2006-02-15 04:07:15  No: 60645

関数にして何とか思い通り動くようになりました。

// アクセス履歴を解析
int aspParseAccess(char* sBuf1, char* sBuf2, AccessData* adata)
{
  int i, iHeadCnt;
  char sMethod[100][1024] = {0};
  char* e_head = sBuf2; /* 最初は文字列の先頭を代入しておく */
    char* pNext;
  char* cDel = ",";
  const char* token = 0;
  char *pGet, *pReferer, *pUserAgent, *pHost;
  
  // 奇数行を","で分割
  strcpy(adata->ports.sIp1, strtok(sBuf1, cDel));
  strcpy(adata->ports.sPort1, strtok(NULL, cDel));
  strcpy(adata->ports.sIp2, strtok(NULL, cDel));
  strcpy(adata->ports.sPort2, strtok(NULL, cDel));

  // 偶数行を".."で分割
  i = 0;
  iHeadCnt = 0;
  while ((pNext=aspStrSplit(e_head,"..")) != NULL) {
    sprintf(sMethod[i],"%s",e_head);
    e_head = pNext;
    iHeadCnt++;
    i++;
  }
  sprintf(sMethod[i],"%s",e_head);

  // [Get]
  for(i=0; i<=iHeadCnt; i++) {
    pGet = strstr(sMethod[i], "GET ");
    if (pGet != NULL) {
      strcpy(adata->sGet, pGet+4);
      break;}
    if(i == iHeadCnt){
      strcpy(adata->sGet, " ");
    }
  }
  // [Referer]
  for(i=0; i<=iHeadCnt; i++) {
    pReferer = strstr(sMethod[i], "Referer: ");
    if (pReferer != NULL) {
      strcpy(adata->sReferer, pReferer+9);
      break;}
    if(i == iHeadCnt){
      strcpy(adata->sReferer, " ");
    }
  }  
  // [User-Agent]
  for(i=0; i<=iHeadCnt; i++) {
    pUserAgent = strstr(sMethod[i], "User-Agent: ");
    if (pUserAgent != NULL) {  
      strcpy(adata->sUserAgent ,pUserAgent+12);
      break;}
    if(i == iHeadCnt){
      strcpy(adata->sUserAgent, " ");
    }
  }  
  // [Host]
  for(i=0; i<=iHeadCnt; i++) {
    pHost = strstr(sMethod[i], "Host: ");
    if (pHost != NULL) {
      strcpy(adata->sHost ,pHost+6);
      break;}
    if(i == iHeadCnt){
      strcpy(adata->sHost, " ");
    }
  }
  return 0;
}


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加