• R/O
  • HTTP
  • SSH
  • HTTPS

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

oga's tools


File Info

Rev. 2b80abcdeb00aad07aa265bd434df3975aadbb9a
大小 28,367 字节
时间 2024-12-10 04:54:07
作者 hyperoga
Log Message

add color() func

Content

/*
 *   webget.c
 *
 *   Webファイル一括Getツール
 *
 *     指定したURL以下のディレクトリから、指定の拡張子のファイルを取り出す。
 *
 *     usage : webget <url> [{-s <suffix> | -all}]
 *
 *     1998/01/17 V1.00 by oga.
 *     1998/01/25 V1.01 support 'frame src='
 *     1998/02/15 V1.02 bug fix on cross reference html
 *     1998/03/07 V1.03 Ignore mailto:
 *     1998/03/17 V1.04 Ignore suffix case
 *     1999/03/07 V1.05 recv error retry
 *     1999/09/03 V1.07 support ommitting "http://" and -na option
 *     2000/07/22 V1.071 bug fix upperdir check
 *     1999/11/09 V1.08 support link trace limit (-t)
 *     2000/03/23 V1.10 support proxy server (not available)
 *     2001/06/26 V1.11 support "xx%" progress disp/ support host:port
 *     2001/07/01 V1.12 delimiter "'" support
 *     2001/07/24 V1.13 support progress bar
 *     2001/10/14 V1.14 support -bd option and delete # in "xx.html#xxx"
 *     2001/10/15 V1.15 support -i option
 *     2001/11/15 V1.16 support Windows
 *     2003/04/07 V1.17 support progress bytes (KB)
 *     2003/05/12 V1.18 support "img.*src"
 *     2003/10/29 V1.19 support signal handler for debug
 *     2003/11/01 V1.20 support analyzed list (donelist)
 *     2003/11/04 V1.21 bug fix upperdir check
 *     2010/01/03 V1.22 trace level 1up for img/default get css
 *     2010/02/14 V1.23 support link trace level 2
 *
 * Varbose Level
 *   1: xx
 *   2: link trace over file
 *   3: all GetURL path
 *
 * 取得の仕様 
 *   (1)ファイルが存在する場合はコンテンツをサーバから取ってこない
 *      但し、-f 指定の場合ファイルが存在してもサーバから取ってくる
 *   (2)既に解析したhtmlファイルは解析しない(V1.20より)
 *      (-na指定の場合、存在するファイルの内部解析をしない (古いオブション))
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#else
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#endif

#ifdef _WIN32
#define strncasecmp strnicmp
#define strcasecmp stricmp
/*
struct timeval {
    u_int tv_sec;
    u_int tv_usec;
};
*/

struct timezone {
    int tz_minuteswest;
    int tz_dsttime;
};

int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif /* _WIN32 */

/* types */
typedef struct filelist {
	struct filelist *next;
	char *fname;
} filen_t;

/* define */
#define	VER		"1.23"
#define	HOST		"HOST:"
#define	PORT		"PORT:"
#define	HTTP_PREFIX	"http://"
#define	FTP_PREFIX	"ftp://"
#define	dprintf		if (vf >= 4) printf
#define	PERSEC		1000


/* funcs */
void get_file_opt();
void GET_DATA(FILE *, int);	/* no use */
int  GetURLData(char *,int, char *); 
char *GetHREF(FILE *, char *);
char *GetTag(FILE *, char *);
int  mkdirp(char *);
void Url2HostPath(char *, char *, char *, int *);
int  suffck(char *, char *);
int  IsImgPath(char *);
void DelDot2(char *);

/* list utility */
int  AddList(filen_t **, char *);
void DelList(filen_t **, char *);
void FreeList(filen_t **);

/* globals */
int	vf = 0;			/* verboseモード  */
int     ff = 0;			/* forceフラグ    */
int	allf = 0;		/*                */
int     lv = 0;			/* 許可レベル     */
int     bdf = 0;		/* -bd 指定フラグ */
int     imf = 0;		/* -i  指定フラグ V1.15                 */
int     na = 0;			/* 1:ファイルが存在した場合、解析しない */
int	trl  = 0;		/* リンクトレース制限 0:無制限          */
int	trl_plus = 0;		/* リンクトレース制限(画像1plus)        */
int	first = 1;		/* 初取得フラグ                         */
int     trace_level = 0;        /* リンクトレース階層                   */
int     prox_port;	 	/* proxy port 番号 V1.10                */
char    suff[260];		/* suffix         */
char    startdir[1025] = "";	/* start dir      */
char    prox_host[256]=""; 	/* proxy host格納用 V1.10               */
filen_t	*openlist = NULL;	/* open file list */
filen_t	*donelist = NULL;	/* 解析済みlist   */
char    *bar = "##################################################                                                  ";

void usage()
{
    printf("webget Ver %s\n", VER);
    printf("usage : webget <url> [{-s <suffix> | -all}]\n");
    printf("               [-l {<0>|1|2|3}]\n");
    printf("               [-t <link_trace_level(0)>[+]\n");
    printf("               [-p <port>] [-f] [-na] [-v ...]\n");
    printf("               [-i] [-bd <base_dir>]\n");
#if SUPPORT_PROXY
    printf("               [-proxy <host> <port>]\n");
#endif
    printf("        -s <suffix>   : get only spcified suffix file(default .jpg)\n");
    printf("        -all          : get all file\n");
    printf("        -l {<0>|1|2}  : link allow level\n");
    printf("                        0: file under spcified URL only (default)\n");
    printf("                        1: allow same host\n");
    printf("                        2: allow all hosts (suffix only)\n");
    printf("                        3: allow all hosts\n");
    printf("        -t <level>[+] : link trace level. 0:no limit\n");
    printf("                        +: if image, trace level 1 up (ex. -t 3+)\n");
    printf("        -bd           : change base dir for -l option (no http://)\n");
    printf("        -p <port>     : port number\n");
    printf("        -f            : get duplicate file\n");
    printf("        -i            : don't send http version (for i-mode site)\n");
    printf("        -na           : no analize exist file\n");
    printf("        -v            : verbose mode\n");
#if SUPPORT_PROXY
    printf("        -proxy <host> <port> : use proxy server\n");
#endif
}

#ifndef _WIN32
void SigHup(int sig)
{
    ++vf;
    printf("### verbose level = %d\n", vf);
    signal(SIGHUP, SigHup);
}
#endif

int main(a,b)
int a;
char *b[];
{
	int	an      = 0;	/* 引数なし引数のカウンタ         */
	int     i;
	int	waitsec = 1;	/* send後のwait時間               */
	int     port;		/* port 番号 */
	char 	*recvfile   = NULL;
	char 	*sendf      = NULL;
	char 	*pt         = NULL;
	char    host[256];	/* host格納用    */
	char    path[260];	/* URL パス部分  */
	char    url[260];	/* URL           */
	char    basedir[260];	/* base dir      */

#ifdef _WIN32
        WSADATA  WsaData;
#endif


	/* init */
	first = 1;                      /* first data   */
	port = 80;			/* default port */
	strcpy(host,"localhost");	/* default host */
	strcpy(path,"/");		/* suffix */
	strcpy(suff,".jpg");		/* suffix */
	strcpy(url, "");

	/* arg */
	for (i = 1; i<a ; i++) {
	    if (!strcmp(b[i],"-h")) {	/* ヘルプ        */
		usage();
 	        exit(1);
	    }
	    if (!strcmp(b[i],"-s") && i+1<a) {	/* suffix */
	        strcpy(suff,b[++i]);
 	        continue;
	    }
	    if (!strcmp(b[i],"-all")) {	/* 全ファイル取り出し */
	        allf = 1;
 	        continue;
	    }
	    if (!strcmp(b[i],"-l") && i+1<a) {	/* allow level */
	        lv = atoi(b[++i]);
 	        continue;
	    }
	    if (!strcmp(b[i],"-bd") && i+1<a) {	/* base dir V1.  */
	        strcpy(startdir, b[++i]);
 	        continue;
	    }
	    if (!strcmp(b[i],"-p") && i+1<a) {	/* port */
	        port = atoi(b[++i]);
 	        continue;
	    }
	    if (!strcmp(b[i],"-f")) {	        /* force */
	        ff = 1;
 	        continue;
	    }
	    if (!strcmp(b[i],"-i")) {	        /* -i option V1.15-A  */
	        imf = 1;
 	        continue;
	    }
	    if (!strcmp(b[i],"-na")) {	/* no analize exist file V1.07 */
		/* クロスリンク無限ループ対策 */
	        na = 1;
 	        continue;
	    }
	    if (!strcmp(b[i],"-t") && i+1<a) {	/* link trace limit level V1.08 */
		/* リンクトレースレベル制限  0:制限なし */
	        trl = atoi(b[++i]);
		/* V1.22-A start */
		if (b[i][strlen(b[i])-1] == '+') {
		    trl_plus = 1;
		}
		/* V1.22-A end   */
 	        continue;
	    }
	    if (!strcmp(b[i],"-proxy")) {	/* proxy */
		if (i+2 < a) {
		    usage();
		    exit(1);
		}
	        strcpy(prox_host,b[++i]);
	        prox_port = atoi(b[++i]);
 	        continue;
	    }
	    if (!strcmp(b[i],"-v")) {	/* verbose  */
	        ++vf;
 	        continue;
	    }
	    strcpy(url,b[i]);		/* URL */
	}

	if (strlen(url) == 0) {         /* V1.13-A */
	    usage();
	    exit(1);
	}

#ifdef _WIN32
        WSAStartup(0x0101, &WsaData);
	/* Win don't support scroll bar.        */
	/* set i-mode flag (don't use HTTP/1.0) */
	/* imf = 1; */ /* V1.21-D */
#else  /* UNIX */
	signal(SIGHUP, SigHup);
#endif

#if 1
	Url2HostPath(url, host, path, &port);
#else
	/* Url2HostPath(url,host,path)にしよう */
	if (strstr(url,HTTP_PREFIX)) {
	    /* ホスト名取り出し */
	    strcpy(host,&url[strlen(HTTP_PREFIX)]);
	    pt = (char *)strchr(host,'/');	/* pt=/aaa/bbb/test.html */
	    if (pt) {
	        strcpy(path,pt);
		*pt = '\0';
	    }
	    dprintf("# hostname is [%s]\n",host);
	    dprintf("# path     is [%s]\n",path);
	}
#endif

	mkdir(host,0775);
	chdir(host);

	GetURLData(host,port,path);

	FreeList(&donelist);

#ifdef _WIN32
	WSACleanup();
#endif

	exit(0);
}

/*
 *  urlをhost名とpath部分に分解する
 *  V1.11 support host:port
 *
 *  http://host.domain[:port]/aaa/bbb/test.html
 *
 *    => host ... host.domain
 *    => path ... aaa/bbb/test.html
 *    => port ... nnnn
 */
void Url2HostPath(char *url, char *host, char *path, int *port)
{
	char *pt;
	char urlwk[2048];  /* V1.07 */

	if (!strncmp(url, HTTP_PREFIX, strlen(HTTP_PREFIX))) {
	    strcpy(urlwk, url);
	} else {
	    sprintf(urlwk, "%s%s",HTTP_PREFIX, url);
	}

	if (strstr(urlwk,HTTP_PREFIX)) {
	    /* ホスト名取り出し */
	    strcpy(host,&urlwk[strlen(HTTP_PREFIX)]);
	    pt = (char *)strchr(host,'/');	/* pt=/aaa/bbb/test.html */
	    if (pt) {
	        strcpy(path,pt);
		*pt = '\0';
	    }

            /* V1.11 get port */
	    pt = (char *)strchr(host,':');	/* pt=:8080 */
	    if (pt) {
	        *port = atoi(pt+1);
		if (*port == 0) {
		    *port = 80;
		}
		*pt = '\0';
	    }

	    dprintf("# hostname is [%s]\n",host);
	    dprintf("# port     is [%d]\n",*port);
	    dprintf("# path     is [%s]\n",path);
	}
}

/*
 * GetURLData()
 *
 *  IN  host : web hostname
 *      port : port (80)
 *      path : path without hostname (fullpath) (eg. /xxx/yyy.html)
 *
 */
int GetURLData(char *host,int port,char *path) 
{
	FILE	*ofp, *rfp;
	int	sockfd;		/* ソケットFD                     */
	int     len, slen;
	int     total,old;
	int     start,end;
	int     content_len;    /* Content Length         */
	int     port2;
	int     lvplus = 0;     /* trace level up for img V1.22-A */
	struct  sockaddr_in serv_addr;
	struct  hostent *hep;
	char	buf[4096];
	char	wk[4096];
	char	*pt;
	char	wfile[260];
	char    host2[256];	/* リンク先 host格納用    */
	char    path2[260];	/* リンク先 URL パス部分  */
	char    cwd[260];	/* 現在のディレクトリ     */
	char    strbar[100];    /* for progress bar V1.13 */
	struct stat stbuf;

	if (vf >= 3) printf("# GetURLData[%s] trace_level=%d\n",path, trace_level+1);
        ++trace_level;

	/* V1.22-A start */
	if (IsImgPath(path) && trl_plus) {
	    lvplus = 1;
	}
	/* V1.22-A end   */

	if (trl && trace_level > trl+lvplus) {  /* V1.08 V1.22-C */
	    if (vf >= 2) printf("##   Skip load %s (tracelevel %d)\n",path,trace_level);
	    --trace_level;
	    return 1;
	}

	/* コマンドに指定されたpathのディレクトリ部分を保存 */
	if (startdir[0] == '\0') {
	    strcpy(startdir,path);
	    if (pt = (char *)strrchr(startdir,'/')) {
	        if (&startdir[0] != pt) { /* V1.071-A */
	            *pt = '\0';
	        } else {                  /* V1.071-A */
		    *(pt+1) = '\0';
		}
	    }
	}

	/* allow level 0の場合は、指定ディレクトリより上のディレクトリの
	 * ファイルをGetしない
	 */
	if (!first && lv == 0 && strncmp(path,startdir,strlen(startdir))) {
	    if (vf) printf("##   Skip load %s (upper dir)\n",path);
	    --trace_level;
	    return 1;
	}
	first = 0;

        /* wk : 格納先パス用   path : 取得URL */
	if (pt = (char *)strchr(path,'#')) {
	    /* a nameの#は取る */
	    *pt = '\0';
	}
	strcpy(wk,path);
	if (pt = (char *)strchr(wk,'~')) {
	    /* ~は@に変換 */
	    *pt = '@';
	}

	/* ファイル格納用ディレクトリ作成 */
	mkdirp(wk);

	/* 格納用のファイル(wfile)は頭の/を削除 */
	if (wk[0] == '/') {
	    strcpy(wfile,&wk[1]);
	} else {
	    strcpy(wfile,wk);
	}

	/* /で終っていたら、index.htmlを付ける */
	if (!strlen(wfile) || wfile[strlen(wfile)-1] == '/') {
	    strcat(wfile,"index.html");
	}

	/* .html/.css と 指定した拡張子以外のファイルは読み込まない V1.22-C */
	if (!allf && !suffck(wfile,".html") && !suffck(wfile,".htm") 
	          && !suffck(wfile,".css") && !suffck(wfile,suff) ) {
	    /* 読む必要のないファイル */
	    --trace_level;
	    return 1;

	}

	/* cwd 設定 */
	strcpy(cwd,path);
	pt = (char *)strrchr(cwd,'/');
	if (pt) {
	    *(pt+1) = '\0';	/* cwd = /dir1/dir2/ */
	}

	/* 取得済みでない場合読み込む (-forceなら常に読む) */
	if (ff || stat(wfile,&stbuf)) {
	  if (ff) {
	    printf("## reload %s .\n");
	  }
	  /* 
	   *  start URL Get
	   */
	  memset((char *)&serv_addr, 0, sizeof(serv_addr));

	  hep = gethostbyname(host);
	  if (!hep) {
	    printf("Error: gethostbyname(%s) error \n",host);
	    --trace_level;
	    return 1;
	  }

	  serv_addr.sin_family	  = AF_INET;
	  serv_addr.sin_addr.s_addr = *(int *)hep->h_addr;
	  serv_addr.sin_port	  = htons(port);

	  if (vf >= 2) {
	    pt = (char *)&serv_addr.sin_addr.s_addr;
	    /*printf("# IP addr : %u.%u.%u.%u (%08x)\n", pt[0],pt[1],pt[2],pt[3],
				serv_addr.sin_addr.s_addr); */
	    printf("# IP addr : %s\n", inet_ntoa(serv_addr.sin_addr));
	  }

	  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("socket");
	        --trace_level;
	        return 1;
	  }

	  if(connect(sockfd, (struct sockaddr *)&serv_addr, 
					sizeof(serv_addr)) < 0){ 
		perror("connect");
	        --trace_level;
	        return 1;
	  }

	  /* 
	   *  write file open
	   */
	  dprintf("# fopen(%s)\n",wfile);
	  if (!(ofp = fopen(wfile,"wb"))) {             /* V1.16-C */
    	        printf("Error: recv data file open error : \n");
		perror("fopen");
	        --trace_level;
                return 1;
	  }

          if (imf) {    /* V1.15-A */
	      sprintf(buf, "GET %s\n",path);            /* V1.11-D V1.15-A */
	  } else {
	      sprintf(buf, "GET %s HTTP/1.0\n\n",path); /* V1.11-A */
	  }
	  len = strlen(buf);

	  dprintf("# send request = %s",buf);

          /* send data */
	  slen = send(sockfd, buf, len, 0);
	  if (slen != len) {
	    printf("Warning: send incompleted len=%d send=%d\n",len,slen);
	  }

          /* V1.11-A start */
	  content_len = 0;
	  if (!imf) {
	    /* for "GET xx HTTP/1.0" */
	    /* Get HTTP Header       */
	    do {
	      recv_oneline(sockfd, buf, sizeof(buf));
	      if (!strncasecmp(buf, "Content-Length: ", 16)) {
		  content_len = atoi(&buf[strlen("Content-Length: ")]);
	          dprintf("content_len = %d\n", content_len);
	      }
	    } while(strlen(buf) != 0);
	  }
          /* V1.11-A end   */

	  total = 0;
	  old   = 0;
	  printf("## LV:%d loading %s .",trace_level, wfile);
	  if (content_len) printf("\n");    /* V1.11 */
          fflush(stdout);
	  start = clock1000();
	  do {
	    /* recv data */
	    len = recv(sockfd,buf,sizeof(buf),0);
	    if (len > 0) {
	        fwrite(buf,1,len,ofp);
	    }
	    if (len < 0) {	/* V1.05 */
	        printf("# recv error (%d). retry!!\n");
	        continue;
	    }
	    /* printf("receive %d bytes\n", len); */
	    total += len;

	    if (content_len) {      /* V1.11-A */
		 /* for disp by %      V1.11-A */
		 int pcent;
		 if (content_len > 1024*1024) {
	             pcent = total/(content_len/100);
		 } else {
	             pcent = (total*100)/content_len;
		 }
		 /* for disp progress bar V1.03-A */
		 strncpy(strbar, &bar[50-pcent/2], 50);
		 strbar[0] = strbar[10] = strbar[20] = strbar[30] 
			   = strbar[40] = strbar[50] = '|';
		 strbar[51] = '\0';
	         /* printf("  %3d%% %s\n\033M", pcent, strbar); */
#ifdef _WIN32
	         printf("  %3d%% %s  %d/%d KB\r", pcent, strbar, total/1024, content_len/1024); /* V1.17-C */
#else  /* !_WIN32 */
	         printf("  %3d%% %s  %d/%d KB\n\033M", pcent, strbar, total/1024, content_len/1024); /* V1.17-C */
#endif /* !_WIN32 */
	         fflush(stdout);
            } else {
		 /* disp by dot */
	        if (total > old+4096) {
	            printf(".");
	            fflush(stdout);
	            old += 4096;
	        }
	    }
	  } while (len > 0);

	  if (ofp != stdout) {
	      dprintf("\n# fclose(%s)\n",wfile);
	      fclose(ofp);
	  }
	  close(sockfd);
	  end = clock1000();

          {
	      char wk2[256];          /* V1.17-A */
	      sprintf(wk2, " (%d bytes  %.2fKB/sec)                                                                ", /* V1.17-C */
	              total,((float)total)/(end-start)/1.024);
	      wk2[79] = '\0';         /* V1.17-A */
	      printf("%s\n", wk2);    /* V1.17-A */
	  }
	} else {
	    if (vf) printf("## %s is already loaded. skip load.\n",wfile);
	    if (na) {		/* V1.07 */
		/* 既にファイルが存在する場合は、ファイル内部を解析しない */
	        if (vf) printf("## and skip analyze.\n",wfile);
	        --trace_level;
		return 0;	/* V1.07 */
	    }			/* V1.07 */
	}


	/*
	 *  取り出したファイル(wfile) がHTMLなら 内容を解析して、
	 *  GetURLData()をリカーシブコール
	 *  
	 *  既に解析済みのものは解析しない
	 *    (トレース階層がリミットレベルの場合は解析済みリストに追加しない)
	 */
	if ((suffck(wfile,".html") || suffck(wfile,".htm"))
	    && ((trace_level >= trl+lvplus) || AddList(&donelist, wfile))) { /* V1.22-C */
	    /* html && 未解析 => 内容解析 */
	    if (AddList(&openlist, wfile) && (rfp = fopen(wfile,"r"))) {
		while (GetHREF(rfp,buf)) {
		    dprintf("# get link data %s\n",buf);
		    if (strstr(buf,HTTP_PREFIX)) {
			/* http://xxxx 形式 */
			port2 = 80; /* V1.11 */
		        Url2HostPath(buf, host2, path2, &port2);  /* V1.11-C */
		        if (!strlen(host2) || !strcmp(host2,host)) {
			    /* 自サイトならリンク先を取りに行く */
		            GetURLData(host,port,path2);
		        } else if (lv == 2 && suffck(wfile, suff)) {
			    /* 自サイトでなくてもallow level 2 で指定ファイルなら 
			     * リンク先を取りに行く 
			     */
		            GetURLData(host2,port2,path2);  /* V1.11-C */
		        } else if (lv >= 3) {
			    /* 自サイトでなくてもallow level 3 以上なら
			     * リンク先を取りに行く 
			     */
		            GetURLData(host2,port2,path2);  /* V1.11-C */
		        } else {
		            /* ホストが違うのでロードしない */
	    		    if (vf) printf("##   Skip load %s (other host)\n",buf);
		        }
		    } else if (strstr(buf,FTP_PREFIX)) {
		        continue;  /* V1.071-A */
		    } else {
		        /* http://指定なし */
			if (buf[0] == '/') {
			    /* 自ホスト絶対パス */
		            GetURLData(host,port,buf);
			} else if (!strcasecmp(buf,"mailto:")){
			    /* "mailto:<name@mail.adr>" は無視 V1.03 */
			    ;
			}else {
			    /* 自ホスト相対パス */
			    strcpy(wk,cwd);	/* Base Dir      */
			    strcat(wk,buf);	/* absolute path */
			    DelDot2(wk);
		            GetURLData(host,port,wk);
			}
		    }
		}
		fclose(rfp);
		DelList(&openlist, wfile);
	    }
	}

        --trace_level;
	return 0;

}

/*
 *   suffix check
 *
 *      bufの終りがsufixであるかチェックする(大文字小文字無視)
 *
 *   IN  buf   : check path
 *       sufix : suffix
 *   OUT ret   : 1 ... match suffix
 *               0 ... no match suffix
 */
int suffck(char *buf, char *sufix)
{
    int len = strlen(buf);
    int len2 = strlen(sufix);

    if (len < len2) {
        return 0;
    }

    return (!strcasecmp(&buf[len-len2],sufix));
}

/*
 *  <...>のタグを取り出す
 *  
 *  IN   fp  : fopen("r")済みHTMLファイルポインタ 
 *  OUT  buf : タグ"<....>"を返す
 *       ret : buf タグ格納
 *             0   EOF
 */
char *GetTag(FILE *fp, char *buf)
{
    int i=0;
    int c=0;

    i = 0;
    while (c != EOF && c != '<') c = getc(fp);
    if (c == EOF) return 0;
    while (c != EOF && c != '>') {
	buf[i++] = c;
        c = getc(fp);
    }
    buf[i] = '\0';
    return buf;
}

/*
 *  bufから<link.*href="url"> を見つけたら"src"の先頭ポインタを返す V1.22
 *
 *
 */
char *GetCssSrc(char *buf)
{
    char *pt;

    if (!strstr(buf, "link ")) {
        if (!strstr(buf, "LINK ")) {
            return NULL;
        }
    }
    if (pt = strstr(buf, "href")) {
        return pt;
    }
    if (pt = strstr(buf, "HREF")) {
        return pt;
    }
    return NULL;
}

/*
 *  bufから<img.*src="url"> を見つけたら"src"の先頭ポインタを返す V1.18
 *
 *
 */
char *GetImgSrc(char *buf)
{
    char *pt;

    if (!strstr(buf, "img ")) {
        if (!strstr(buf, "IMG ")) {
            return NULL;
        }
    }
    if (pt = strstr(buf, "src")) {
        return pt;
    }
    if (pt = strstr(buf, "SRC")) {
        return pt;
    }
    return NULL;
}

/*
 *  a href= または、img src=のリンク先をbufに返す
 *  
 *  img src=があったら、GetURLDataを呼ぶ 
 *  
 *  IN   fp  : fopen("r")済みHTMLファイルポインタ 
 *  
 *  OUT  ret : buf リンクあり
 *             0   EOF
 */
char *GetHREF(FILE *fp, char *buf)
{
	int  i = 0;
	char *pt;
	char *status;
	char wk[4096];

	while (status = GetTag(fp,wk)) {
	    if ((pt = GetImgSrc(wk)) 
	     || (pt = GetCssSrc(wk))                    /* V1.22 */
	     || (pt = (char *)strstr(wk,"frame src"))   /* V1.01 */
	     || (pt = (char *)strstr(wk,"FRAME SRC"))   /* V1.01 */
	     || (pt = (char *)strstr(wk,"a href"))
	     || (pt = (char *)strstr(wk,"A href"))
	     || (pt = (char *)strstr(wk,"A HREF"))) {
	         while (*pt != '"' && *pt != '\'' && *pt != '\0') pt++;/*V1.12*/
	         pt++;
	         while (*pt != '"' && *pt != '\'' && *pt != '\0') {    /*V1.12*/
	             buf[i++] = *pt;
	             ++pt;
	         }
	         buf[i] = '\0';
	         break;
	    }
	}
	if (status == NULL) {
	    return (char *)0;
	}
	dprintf("# find Link [%s]\n",buf);
	return buf;
}

/*
 *  指定されたパスのディレクトリ部分のディレクトリを作成する
 *
 *  path = /aaa/bbb/test.html
 *
 *  mkdir -p ./aaa/bbb
 */
int mkdirp(char *path)
{
    char *pt;
    char cwd[260];
    char wk[260];

    dprintf("# mkdirp=[%s]\n",path);

    getcwd(cwd,sizeof(cwd));

    dprintf("#   pwd=[%s]\n",cwd);

    /* path = /aaa/bbb/test.html */
    if (path[0] == '/') {
        strcpy(wk,&path[1]);
    } else {
        strcpy(wk,path);
    }
    pt = (char *)strrchr(wk,'/');
    if (!pt) {
	/* ディレクトリ部分なし */
	return 0;
    }
    *pt = '\0';
    /* wk = aaa/bbb */

    pt = (char *)strtok(wk,"/");
    while (pt) {
	dprintf("#   mkdir %s\n",pt);
	mkdir(pt, 0775);
	chdir(pt);
	pt = (char *)strtok(NULL,"/");
    }

    chdir(cwd);
    return 0;

}


/*
 *  send data ファイル内の埋め込みオプションを取り込む。
 *  コマンドの引数に設定されている場合は取り込まない。
 *
 *  IN  sendf : send data file
 *  OUT host  : HOST:で指定されたホスト名
 *      port  : PORT:で指定されたポート番号(文字列)
 *      (注) host,portとも呼出時に長さが0で渡された場合のみ設定される
 *
 */
void get_file_opt(sendf,host,port)
char *sendf, *host, *port;
{
    FILE *fp;
    char buf[2048];
    int  len;

    if (!(fp = fopen(sendf,"r"))) {
        return;
    }
    while (fgets(buf,sizeof(buf),fp)) {
	/* 改行削除 */
        len = strlen(buf);
        if (buf[len-1] == 0x0a) {
            buf[len-1] = '\0';
        }
        if (!strncmp(buf,HOST,strlen(HOST)) && !strlen(host)) {
            strcpy(host,&buf[strlen(HOST)]);
        }
        if (!strncmp(buf,PORT,strlen(PORT)) && !strlen(port)) {
            strcpy(port,&buf[strlen(PORT)]);
        }
        if (strlen(host) && strlen(port)) {
            /* 両方設定された時点で終了 */
            break;
        }
    }
    fclose(fp);
}

/*
 *   clock1000()
 *
 *       1/PERSEC sec 単位の値をリターンする
 */
int clock1000()
{
    int code = 0;
#ifdef AIX
    struct tms buf;

    code = times(&buf)*PERSEC/HZ;
#else
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv,&tz);

    code = tv.tv_sec*PERSEC+(tv.tv_usec)/(1000000/PERSEC);
#endif /* AIX */
    return code;
}

#define SIZE 4096
/* 
 *   sockfd : input fd (socket)
 *   fd     : output fp
 */
void GET_DATA(fp, sockfd)
FILE *fp;
int sockfd;
{
	char c[SIZE];
	int size, all=0;
	struct timeval tv, tv2;
	unsigned int wk,wk2,diff;

	if (vf >= 3) {
	    gettimeofday(&tv,0);
	    wk = tv.tv_sec*1000000 + tv.tv_usec;
	    printf("start usec : %u\n",wk);
        }

	while((size = read(sockfd, c, SIZE)) != 0) {
		fwrite(c,1,size,fp);
		/* c[size] = '\0'; */
		/* printf("%s",c); */
		/* fflush(stdout); */
		all += size;
	}

	if (vf >= 3) {
	    gettimeofday(&tv,0);
	    wk2 = tv.tv_sec*1000000 + tv.tv_usec;
	    diff = wk2-wk;
	    if (diff <0 ) diff = -diff;
	    printf("  end usec : %u\n",wk2);
	    printf(" diff usec : %u\n",diff);
	    printf("size = %d  time = %.6fsec  perf = %dKB/sec\n",
			all,
			(float)diff/1000000,
			(all*1000)/diff);
	}
}

/*
 *  listにpathがあるかチェックする
 *
 *  OUT ret  0:すでにpathはlistにある
 *           1:listにpathを追加した
 *
 */
int AddList(filen_t **listpp, char *path)
{
    filen_t *wk, *wkold;
    wk    = *listpp;
    wkold = (filen_t *)listpp;
    while (wk) {
        if (!strcmp(wk->fname,path)) {
            /* already open */
            dprintf("# already opend [%s]\n",path);
            return 0;
        }
        wkold = wk;
        wk = wk->next;
    }
    wk = (filen_t *)malloc(sizeof(filen_t));
    memset(wk,0,sizeof(filen_t));
    wkold->next = wk;
    wk->fname   = (char *)strdup(path);
    return 1;
}

/*
 *  listからpathのあるエントリを削除する
 *
 */
void DelList(filen_t **listpp, char *path)
{
    filen_t *wk, *wkold;
    wk    = *listpp;
    wkold = (filen_t *)listpp;
    while (wk) {
        if (!strcmp(wk->fname,path)) {
            wkold->next = wk->next;
            free(wk->fname);
            free(wk);
            return;
        }
        wkold = wk;
        wk = wk->next;
    }
    printf("# path(%s) not found in openlist\n",path);
}

/*
 *  listをすべて開放する
 *
 */
void FreeList(filen_t **listpp)
{
    filen_t *wk, *wknext;
    int     cnt = 1;

    wk = *listpp;
    while (wk) {
        if (vf >= 3) printf("# FreeList(%d:%s)\n", cnt, wk->fname);
	wknext = wk->next;
        free(wk->fname);
        free(wk);
        wk = wknext;
	++cnt;
    }
    *listpp = NULL;
}

/*
 *  path から、/../ /./を除いてきれいなパスにする
 *
 */
void DelDot2(char *path)
{
    char *pt,*pt2;
    if (pt = (char *)strstr(path,"/../")) {
        pt2 = pt + strlen("/../");    /* pt2 : aaa/bbb/../Ibbb */
        *pt = '\0';                   /* path: aaa/bbb ../bbb  */
        pt = (char *)strrchr(path,'/');       /* pt  : aaaI/bbb ../bbb */
        pt++;			      /* pt  : aaa/Ibbb ../bbb */
        strcpy(pt,pt2);
        DelDot2(path);
    }
    if (pt = (char *)strstr(path,"/./")) {
        pt2 = pt + strlen("/./");     /* pt2 : aaa/bbb/./Ibbb */
        pt++;			      /* pt  : aaa/bbb/I./bbb */
        strcpy(pt,pt2);
        DelDot2(path);
    }
}

/* 
 *   1行recv  V1.11
 *   IN   sockfd  socket fd
 *        sz      bufのサイズ
 *   OUT  buf     読み込んだ1行(改行除く)
 *        ret     読み込んだ文字数(改行除く)
 *
 */
int recv_oneline(int sockfd, char *buf, int sz)
{
    int i = 0;
    int ret = 0;

    while (i < (sz-1) && (ret = recv(sockfd,&buf[i],1,0))) {
	if (buf[i++] == 0x0a) {
	    break;
	}
    }
    buf[i] = '\0';

    /* del CRLF */
    if (buf[i-1] == 0x0a) {
        buf[i-1] = '\0';
	i--;
    }
    if (buf[i-1] == 0x0d) {
        buf[i-1] = '\0';
	i--;
    }

    dprintf("buf=[%s]\n",buf);
    return i;
}


#ifdef _WIN32
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    	SYSTEMTIME syst;

        //GetSystemTime(&syst);   // UTC
        GetLocalTime(&syst);
	tv->tv_sec  = syst.wHour * 3600 +
       		      syst.wMinute *60 +
        	      syst.wSecond;
	tv->tv_usec = syst.wMilliseconds * 1000;
	return 0;
}
#endif /* _WIN32 */

/*
 *   イメージ等のファイルかどうかのチェック  
 *
 *   IN  path  path(URL)
 *   OUT ret   0: no image file
 *             1: image file path
 */
int IsImgPath(char *path)
{
	int pos;

	pos = strlen(path) - 4;
	/* とりあえずこれだけが対象 */
	if (!strcasecmp(&path[pos],   ".jpg")  ||
	    !strcasecmp(&path[pos-1], ".jpeg") ||
	    !strcasecmp(&path[pos],   ".gif")  ||
	    !strcasecmp(&path[pos],   ".bmp")  ||
	    !strcasecmp(&path[pos],   ".pdf")  ||
	    !strcasecmp(&path[pos],   ".png")) {
	    return 1;
	}
	return 0;
}

/* vim:ts=8:sw=8
 */