『Tea-Cup』エージェント airWeb PR6付属 tcup.r


#include <awlib.h>

char TGTFILE[260];
#define BUFSIZEUNIT 8192

typedef struct _STRBUF {
    char *text;
    int bsize;
    int esize;
    int tsize;
} STRBUF;

typedef struct _MSGBUF {
    struct _MSGBUF *next;
    char *msgtext;
} MSGBUF;

MSGBUF *MSGSTACK = NULL;

static char daynames_j[] = "日月火水木金土";
static char daynames_e[] = "SunMonTueWedThuFriSat";

static int istripod = 0;

int getmessagedate(struct tm *trec,char *datestr) {
    time_t t;
    char tmp[32];
    char week1[16];
    char week2[16];
    int count;
    
    time(&t);
    memcpy(trec,localtime(&t),sizeof(struct tm));
    
    /* 012345678901234567890123 */
    /* 07月14日(金)18時06分09秒 */
    strncpy(tmp,datestr,24);
    
    tmp[2]='\0';
    trec->tm_mon=atoi(tmp);
    tmp[6]='\0';
    trec->tm_mday=atoi(tmp+4);
    tmp[11]='\0';
    tmp[14]='\0';
    trec->tm_hour=atoi(tmp+12);
    tmp[18]='\0';
    trec->tm_min=atoi(tmp+16);
    tmp[22]='\0';
    
    for(trec->tm_wday = 0; trec->tm_wday < 7; trec->tm_wday++) {
        if(!strncmp(daynames_j+trec->tm_wday*2,tmp+9,2)) {
            strncpy(week1,daynames_e+trec->tm_wday*3,3);
            break;
        }
    }
    trec->tm_sec=atoi(tmp+20);
    for(count=0;count<10;count++) {
        strftime(week2,sizeof(week2),"%a",trec);
        if(!strncmp(week1,week2,3)) break;
        trec->tm_year--;
    }
    return 0;
}

int storemessage(QDATA *qd,char *subject,char *sender,char *mail,char *date,char *text) {
    MSGBUF *tmpmsg;
    char idstr[128];
    struct tm tmp;
    char timestamp[128];
    int result;
    str tmptext;

    getmessagedate(&tmp,date);
    strftime(timestamp,sizeof(timestamp),"%c",&tmp);
    strftime(idstr,sizeof(idstr),"<%Y%m%d%H%M%S>",&tmp);

    if(qfind(qd,QFIND_MESSAGEID,(int)idstr)==-1) {
//      debug("store %s",idstr);
        //setstatustext(subject);
        tmpmsg = (MSGBUF *)malloc(sizeof(MSGBUF));
        tmptext = "From foo@bar " + timestamp + "\r\n";
        if(mail) {
            tmptext = tmptext + "From: " + sender + " <" + mail + ">\r\n";
        } else {
            tmptext = tmptext + "From: " + sender + "\r\n";
        }
        tmptext = tmptext + "Message-ID: " + idstr + "\r\n";
        tmptext = tmptext + "Date: " + timestamp + "\r\n";
        tmptext = tmptext + "Subject: " + subject + "\r\n";
        tmptext = tmptext + "\r\n";
        tmptext = tmptext + text;
        tmptext = tmptext + "\r\n";
        tmptext = tmptext + "\r\n";
        
        tmpmsg->msgtext = strcpy(malloc(strlen(tmptext)+1),tmptext);
        
        tmpmsg->next = MSGSTACK;
        MSGSTACK = tmpmsg;
        
        result=1;
    } else {
        debug("cache hit %s",idstr);
        result=0;
    }
    return result;
}

int checkmessages(STRBUF *buf) {
    QDATA *qd;

    PAGE *page;
    ELEMENTS *el;
    ELEMENTS *ea;
    int scan;
    int index;
    int result,count;
    char *mail;

    result=0;
    qd=qopen(TGTFILE);

    page=page_create(buf->text,buf->esize);
    ea=page_elements(page);
    el=page_find_elements(page,NULL,"HR");
    for(scan=0;scan<el->count;scan++) {
        index=el->items[scan].number+1;
        if((ea->items[index].tag=="FONT") &&
            (ea->items[index+1].tag=="B") &&
            (ea->items[index+2].tag=="") &&
            (page_element_text(page,&ea->items[index+3])==" 投稿者:")) {
            if(ea->items[index+5].tag=="A") mail=page_element_att(page,&ea->items[index+5],"href")+7;
            else mail=NULL;
            count=storemessage(
                qd,
                page_element_text(page,&ea->items[index]),
                page_element_text(page,&ea->items[index+4]),
                mail,
                page_element_text(page,&ea->items[index+7])+10,
                page_element_text(page,&ea->items[index+11])
            );
            if(!count) break;
            result += count;
        }
    }
    page_free(page);
    qclose(qd);
    return result;
}

int getmessages(STRBUF *buf,INET *inet,char *ownerid,int offset) {
    HTTP *http;
    int tmplen;
    char tmp[80];
    int result,count;
//  REGEX *re;
//  char *spanstr;

    if(offset) http=http_open(inet,"POST",(istripod ? "/cgi-bin/" : "/cgi-localbin/")+ownerid+".cgi",NULL,0);
    else http=http_open(inet,"GET","/"+ownerid+".html",NULL,0);
    if (http) {
        buf->bsize += BUFSIZEUNIT;
        buf->text = realloc(buf->text,buf->bsize+1);
        sprintf(tmp,"ダウンロード中... %d メッセージ (%d bytes)",offset,buf->tsize);
        setstatustext(tmp);
        if(offset) {
            sprintf(tmp,"page=%d&m=",offset);
            tmplen = http_request(http,tmp,strlen(tmp),buf->text+buf->esize,BUFSIZEUNIT+1);
        } else {
            tmplen = http_request(http,NULL,0,buf->text+buf->esize,BUFSIZEUNIT+1);
        }
        buf->esize += tmplen;
        buf->tsize += buf->esize;
        while(tmplen==BUFSIZEUNIT) {
            buf->bsize+=BUFSIZEUNIT;
            buf->text=realloc(buf->text,buf->bsize+1);
            tmplen=http_read(http,buf->text+buf->esize,BUFSIZEUNIT+1);
            buf->esize += tmplen;
            buf->tsize += buf->esize;
            sprintf(tmp,"ダウンロード中... %d メッセージ (%d bytes)",offset,buf->tsize);
            setstatustext(tmp);
        }
        buf->text[buf->esize]='\0';
        sprintf(tmp,"ダウンロード中... %d メッセージ (%d bytes)",offset,buf->tsize);
        setstatustext(tmp);
        http_close(http);
    }
    result = 0;
    if(count = checkmessages(buf)) {
/* //このメッセージがない場合があるので無視
        re=re_compile("1回の表示で([0-9]+)件を越える場合は、.*</i></font>");
        if(re_search(re,buf->text)>=0 && (spanstr=re_get_group(re,1))) result=atoi(spanstr);
        re_free(re);
*/
        if(strstr(buf->text,"<input type=submit value=\"次のページ\">")) result = offset + count;
        else result = 0;
    }
    if(buf->text) {
        free(buf->text);
        buf->esize = 0;
        buf->bsize = 0;
        buf->text = NULL;
    }
    return result;
}

int main(int argc,char **argv) {
    FILE *out;
    char filename[260];
    QDATA *qd;
    MSGBUF *tmp;
    INET *inet;
    STRBUF buffer;
    LOCATION loc;
    char stat[80];
    int ofs;
    char *scan;
    char* p;

    if(argc<2) return -1;
    for(ofs=1;ofs<argc-1;ofs++) {
        if(!strcmp(argv[ofs],"-o")) {
            ofs++;
            if(ofs<argc-1) {
                if(p = strrchr(argv[ofs], '\\')) // ディレクトリを無視!
                    ++p;
                else
                    p = argv[ofs];
                sprintf(TGTFILE,"%s\\tcup\\%s", getenv("DATA_DIR"), p);
            }
            else return -1;
        }
    }
    memset(&loc,0,sizeof(LOCATION));
    loc.size=sizeof(LOCATION);
    decodeurl(&loc,argv[argc-1]);
    
    scan=strend(loc.path);
    ofs=0;
    while(scan>=loc.path) {
        if(*scan=='.') *scan='\0';
        else if(*scan=='/') {
            ofs++;
            if(ofs==2) {
                memcpy((void *)loc.path,scan+1,strlen(scan+1)+1);
                break;
            }
        }
        scan--;
    }
    istripod = (strstr(loc.host, "tripod.co.jp") != NULL);
    inet=inet_open(NULL,loc.host,loc.port,INET_SERVICE_HTTP,NULL,NULL,0);
    if(inet) {
        memset(&buffer,0,sizeof(STRBUF));
        ofs=0;
        setstatustext("ダウンロード開始");
        do {
            ofs = getmessages(&buffer,inet,loc.path,ofs);
        } while(ofs && !terminated);
    
        ofs = 0;
        if(MSGSTACK) {
            strcpy(filename,TGTFILE);
            scan=strrchr(filename,'.');
            if(!scan) scan=strend(filename);
            strcpy(scan,".g00");
            out=fopen(filename,"a+");
            while(MSGSTACK) {
                ofs++;
                fwrite(MSGSTACK->msgtext,1,strlen(MSGSTACK->msgtext),out);
                tmp = MSGSTACK->next;
                free(MSGSTACK->msgtext);
                free(MSGSTACK);
                MSGSTACK = tmp;
            }
            fclose(out);
            qd=qopen(TGTFILE);
            qupdate(qd);
            qclose(qd);
        }
        if(ofs > 0)
            sprintf(stat,"巡回完了 (%d件取得)",ofs);
        else
            strcpy(stat,"巡回完了");
        setstatustext(stat);
        inet_close(inet);
    }
    return 0;
}