osaisen.zip/osaisen.c
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
//#define DEBUG
enum{
HTTP,
FTP
};
typedef struct url{
int prot;
char host[64];
char path[1024];
DWORD addr;
int port;
}URL;
typedef struct list{
void *p;
struct list *next;
}LIST;
typedef struct id_list{
char id[10];
short num;
}ID_LIST;
char BoardURL[1024] = "http://jbbs.livedoor.jp/computer/41116/";
char ThreName[256] = "";
int matubi = 0;
int OtoZero = 0;
LIST *head = NULL;
URL *spliturl(char *url);
//free忘れ対策、終了時にfreeする
//(OSに任せても大丈夫?)
void freelist_free(void){
LIST *a;
while(head != NULL){
a = head;
head = head->next;
#ifdef DEBUG
printf("endfree is %d\n",a->p);
#endif
free(a->p);
free(a);
}
}
void end_free(void *p){
LIST *a;
if(head == NULL){
atexit(freelist_free);
head = (LIST *)malloc(sizeof(LIST));
a = head;
} else {
a = head;
while(a->next != NULL)a = a->next;
a->next = (LIST *)malloc(sizeof(LIST));
a = a->next;
}
a->next = NULL;
a->p = p;
#ifdef DEBUG
printf("free regist is %d\n",a->p);
#endif
}
void free2(void *p){
LIST *a,*b=NULL;
a = head;
while(a != NULL){
if(a->p == p){
if(b != NULL){
b->next = a->next;
} else {
head = a->next;
}
#ifdef DEBUG
printf("free2 is %d\n",a->p);
#endif
free(a->p);
free(a);
break;
}
b = a;
a = a->next;
}
}
//簡易ファイル作成関数
void fileout(char *fn,char *s){
FILE *fp;
fp = fopen(fn,"w");
fwrite(s,sizeof(char),strlen(s),fp);
fclose(fp);
}
void debugout(char *s){
static int count = 0;
char str[16];
sprintf(str,"debug_%d.log",count++);
fileout(str,s);
}
//簡易文字列置き換え関数
int ChangeStr(char *str,char s1,char s2){
int i,count = 0;
for(i = 0 ; str[i] != '\0' ; i++){
if(str[i] == s1){
str[i] = s2;
count++;
}
}
return count;
}
//デフォルト指定可能版atoi
int atoi2(char *str,int def){
int i;
if(!isdigit(str[0]))return def;
i = atoi(str);
if(i == 0 && str[0] != '0')return def;
return i;
}
//指定文字数検索
int countchr(char *str,char s){
int count = 0;
char *p = str;
if(str == NULL)return 0;
while(*p != '\0'){
if(*p == s)count++;
p++;
}
return count;
}
//設定読み込み処理
void LoadSetting(void){
FILE *fp;
char str[256];
fp = fopen("setting.ini","r");
if(fp==NULL)return;
while(fgets(str,256,fp) != NULL){
if(!strncmp(str,"//",2) || *str == '\n')continue;
ChangeStr((char *)&str,'\n','\0');
//if(!strncmp(str,"x=",strlen("x")+1))x=atoi2(&str[strlen("x")],-1)
//if(!strncmp(str,"x=",strlen("x")+1))strcpy(x,&str[strlen("x")])
if(!strncmp(str,"BoardURL=",strlen("BoardURL")+1))strcpy(BoardURL,&str[strlen("BoardURL")+1]);
if(!strncmp(str,"ThreName=",strlen("ThreName")+1))strcpy(ThreName,&str[strlen("ThreName")+1]);
if(!strncmp(str,"matubi=",strlen("matubi")+1))matubi=atoi2(&str[strlen("matubi")],-1);
if(!strncmp(str,"OtoZero=",strlen("OtoZero")+1))OtoZero=atoi2(&str[strlen("OtoZero")],-1);
}
return;
}
void socket_end(void){
//winsock2の終了処理
WSACleanup();
}
int socket_init(void){
WSADATA wsaData;
//初期化
if (WSAStartup(MAKEWORD(2,0), &wsaData)){
printf("WSAStartup Error\n");
getchar();
return 1;
}
atexit(socket_end);
return 0;
}
int inet_aton(const char *cp, struct in_addr *inp){
unsigned int addr = inet_addr(cp);
if(addr != INADDR_NONE || strcmp(cp,"255.255.255.255") == 0){
if(inp)inp->s_addr = addr;
return 1;
}
return 0;
}
DWORD getip(char *dns){
HOSTENT *host;
struct in_addr in;
if(inet_aton(dns,&in)){
return in.s_addr;
}
host = gethostbyname(dns);
if(host == NULL){
return -1;
} else {
return *((DWORD *)(host->h_addr_list[0]));
}
}
URL *spliturl(char *url){
char *s,*e,str[1024];
URL *ret;
if(url == NULL)return NULL;
strcpy(str,url);
s = strchr(str,':');
if(s == NULL || strncmp(s,"://",3))return NULL;
*s = '\0';
ret = (URL *)malloc(sizeof(URL));
if(!strcmp(str,"http"))ret->prot = HTTP;
else if(!strcmp(str,"ftp"))ret->prot = FTP;
else return NULL;
s+=3;
e = strchr(s,':');
if(e == NULL){
strcpy(ret->path,"/");
e = strchr(s,'/');
if(e != NULL){
strcpy(ret->path,e);
*e = '\0';
}
strcpy(ret->host,s);
ret->port = 80;//今はとりあえず80固定
} else {
*e = '\0';
strcpy(ret->host,s);
s = e+1;
strcpy(ret->path,"/");
e = strchr(s,'/');
if(e != NULL){
strcpy(ret->path,e);
*e = '\0';
}
ret->port = atoi(s);
}
ret->addr = getip(ret->host);
return ret;
}
void init(void){
LoadSetting();
socket_init();
}
int receive(SOCKET s,char* buf,int len){
int received;
int tmp;
received=0;
while(received<len){
tmp=recv(s,buf+received,len-received,0);
if(tmp==SOCKET_ERROR){ /* エラーが発生 */
return SOCKET_ERROR;
}
if(tmp==0){ /* ソケットが切断された */
return received;
}
received+=tmp;
}
return received;
}
int recv2(SOCKET sock,char *buf,int size,char *str){
char *s,i;
s = buf;
while(s < buf+size){
i = recv(sock,s,1,0);
if(i == 0 || i == SOCKET_ERROR)break;
if(*s == *str){
i = recv(sock,s+1,3,0);
if(i == 3 && strncmp(s,str,strlen(str))){
s += 4;
break;
}
s += i;
}
s++;
}
return s-buf;
}
//簡易HTTPGET関数
//問題点:
// タイムアウトしない(鯖に切断されるまで延々待機の無限ループ)
// 他にも色々
char *get(char *address){
char *s=NULL,*a,*b,str[1024];
SOCKET sock;
URL *url;
struct sockaddr_in addr;
int temp,size;
//ソケットの作成
sock= socket(AF_INET,SOCK_STREAM,0);
if(sock == INVALID_SOCKET)return NULL;
url = spliturl(address);
if(url == NULL)goto del_sock;
//ソケットの設定
addr.sin_family = AF_INET;
addr.sin_port = htons(url->port);
addr.sin_addr.S_un.S_addr = url->addr;
connect(sock,(struct sockaddr *)&addr,sizeof(addr));
if(sock == SOCKET_ERROR)goto del_url;
sprintf(str,"GET %s HTTP/1.1\nConnection: close\nHost: %s:%d\r\n\r\n",url->path,url->host,url->port);
//printf("send\n%s\n",str);
if(SOCKET_ERROR == send(sock,str,strlen(str)+1,0))goto del_url;
temp = receive(sock,str,1023);
str[temp] = '\0';
a = strstr(str,"\r\n\r\n");
if(a == NULL)goto del_url;
*a = '\0';
if(NULL != strstr(str,"Transfer-Encoding: chunked")){ //ストリーミング受信
strcpy(str,a+2);
size = 0;
while(1){
if(size == 0){
if(*str == '\0'){
temp = receive(sock,str,1023);
str[temp] = '\0';
}
//printf("%s:",str);
a = strstr(str+2,"\r\n");
*a = '\0';
sscanf(str+2,"%x",&size);
//printf("%d\n",size);
if(size == 0)break;
a+=2;
if(s == NULL){
s = (char *)malloc(sizeof(char)*(size+1));
strncpy(s,a,size);
} else {
b = s;
s = (char *)malloc(sizeof(char)*(size+1+strlen(s)));
strcpy(s,b);
free(b);
strncat(s,a,size);
}
size-=strlen(a);
} else {
if(size < 1023)temp = receive(sock,str,size);
else temp = receive(sock,str,1023);
if(temp == 0)break;
str[temp] = '\0';
strncat(s,str,size);
size-=strlen(str);
}
if(size < 0)break;
*str = '\0';
}
s[strlen(s)-1] = '\0';
} else { //通常受信
s = (char *)malloc(sizeof(char)*(strlen(a+4)+1));
strcpy(s,a+4);
while(1){
temp = receive(sock,str,1023);
//printf("%d:%s",temp,str);
if(temp != SOCKET_ERROR && temp != 0){
str[temp] = '\0';
a = (char *)malloc(sizeof(char)*(strlen(s)+1+temp));
if(a == NULL)break;
strcpy(a,s);
strcpy(&(a[strlen(s)]),str);
free(s);
s = a;
} else break;
}
}
del_url:
shutdown(sock,SD_BOTH);
free(url);
del_sock:
closesocket(sock);
if(s != NULL)end_free((void *)s);
return s;
}
char *strtok2(char *s1, const char *s2){
static char *p = NULL;
if(p != s1){
p = s1;
return strtok(s1,s2);
} else return strtok(NULL,s2);
}
int geturl(char *url){
char temp[1024],*data,*p,*s;
int ret = 0;
URL *uri;
strcpy(temp,BoardURL);
data = get(strcat(temp,"subject.txt"));
while( NULL != (p = strtok2(data,"\n")) ){
if(strstr(p,ThreName) != NULL){
ChangeStr(p,'.','\0');
uri = spliturl(BoardURL);
sprintf(temp,"http://%s/bbs/rawmode.cgi%s%s/",uri->host,uri->path,p);
free(uri);
strcpy(url,temp);
ret = 1;
break;
}
}
free2(data);
return ret;
}
ID_LIST *getidlist(char *data){
char *p,*c;
ID_LIST *list,*a,*b;
int size;
if(data == NULL)return NULL;
size = countchr(data,'\n')+1;
list = (ID_LIST *)malloc(sizeof(ID_LIST)*(size+1));
if(list == NULL)return NULL;
end_free(list);
a = list;
while( NULL != (c = strtok2(data,"\n")) ){
p = strchr(c,'<');
*p = '\0';
a->num = atoi(c);
p = strrchr(p+1,'>');
p++;
b = list;
while(b < a){
if(strcmp(p,b->id) == 0)break;
b++;
}
if(a != b){
//printf("Failed ID:%s\n",p);
continue;
}
strcpy(a->id,p);
a++;
}
a->id[0] = '\0';
return list;
}
int id2money(ID_LIST *list){
char *s,a[10];
int count = 0,flag = 0;
strcpy(a,list->id);
if(OtoZero){
s = a;
while(s < a+10){
if(*s == 'o' || *s == 'O')*s = '0';
s++;
}
}
if(!matubi){
a[8] = '\0';
}
s = a;
while(s < a+10){
if(isdigit(*s)){
if(flag == 0){
count += atoi(s);
flag = 1;
}
} else {
if(flag == 1){
flag = 0;
}
}
s++;
}
return count;
}
int main(){
char *s,url[1024],str[5894];
ID_LIST *max_p,*list;
unsigned int temp,sum,max,count,zero;
init();
if(matubi == -1 || OtoZero == -1)printf("処理方法を選択してください\n");
while(matubi == -1){
printf("末尾(IDの9字目を含める場合は1を、含めないなら0を入力してください\n>");
gets(str);
matubi = atoi2(str,-1);
}
while(OtoZero == -1){
printf("oO(オー)を0に変換する場合は1を、しないなら0を入力してください\n>");
gets(str);
OtoZero = atoi2(str,-1);
}
if(0 == geturl(url)){
printf("Error: ThreName NotFound\n");
return 1;
}
s = get(url);
if(s == NULL){
printf("Error: DatFile NotFound\nURL:%s\n",url);
return 1;
}
list = getidlist(s);
if(list != NULL){
sum = 0;
max = 0;
count = 0;
zero = 0;
str[0] = '\0';
while(list->id[0] != '\0'){
count++;
temp = id2money(list);
//printf("%s:%d\n",list->id,temp);
sum += temp;
if(temp >= max){
max = temp;
max_p = list;
}
if(temp == 0){
//printf("%s\n",list->id);
sprintf(&str[strlen(str)],">>%d ",list->num);
zero++;
}
list++;
}
}
sprintf(&str[strlen(str)-1],"\n");
fileout("夢想封印.txt",str);
//printf("%s",str);
sprintf(str,"%d人が入れたようです。\nそのうち0円の人を除くと%d人が入れてくれたようです。\n最高金額の人 >>%d の人:\\%d\n合計:\\%d\n",count,count-zero,max_p->num,max,sum);
fileout("結果.txt",str);
//printf("%s",str);
//printf("Money is %d\nmax:%s %d\n",sum,max_p,max);
printf("処理を終了します。\n結果.txt に結果を記録しました。\n夢想封印.txt に0円/英字のみだった人を記録しました。\n終了するにはenterを押してください\n");
gets(str);
return 0;
}