Subversion Repositories wimsdev

Rev

Rev 11133 | Rev 11539 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18.  /* This is a small program used simply to fetch web pages.
  19.   * No fancy functionalities such as link redirection or site sucking is
  20.   * present.
  21.   * Page fetched can only be sent to stdout. */
  22.  
  23. #include <netdb.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26.  
  27. #include "../includes.h"
  28. #include "../wimsdef.h"
  29.  
  30. void inline IGNORE() {}  /* Ignore GCC Unused Result */
  31. void IGNORE();  /* see http://stackoverflow.com/a/16245669/490291 */
  32.  
  33. char *cheater1="User-Agent: WIMS-webget";
  34. char *cheater2="Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n\
  35. Accept-Encoding: gzip\r\n\
  36. Accept-Language: en, fr, it, de, es\r\n\
  37. Accept-Charset: iso-8859-1,*,utf-8";
  38. char pbuf[4096], tbuf[4096];
  39. char tfname[1024];
  40. char *tmpdir="/tmp";
  41. int soc, port, https;
  42. int charcnt;
  43. FILE *outf;
  44.  
  45. void errorquit(char *msg)
  46. {
  47.     fprintf(stderr,"%s: %s\n",msg,strerror(errno)); exit(1);
  48. }
  49.  
  50. /* Points to the end of the word */
  51. char *find_word_end(char *p)
  52. {
  53.     int i;
  54.     for(i=0;!isspace(*p) && *p!=0 && i<MAX_LINELEN; p++,i++);
  55.     return p;
  56. }
  57.  
  58. /* Strips leading spaces */
  59. char *find_word_start(char *p)
  60. {
  61.     int i;
  62.     for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
  63.     return p;
  64. }
  65.  
  66. /* Secured execution */
  67. void secure(char *host)
  68. {
  69.     char *p1, *p2, *p3, buf[MAX_LINELEN+1];
  70.     long int l;
  71.     FILE *f;
  72.  
  73.     p1=getenv("w_module"); if(p1==NULL || *p1==0) return;
  74.     p1=getenv("untrust"); if(p1==NULL || *p1==0) return;
  75.     f=fopen("webget.sites","r"); if(f==NULL) return;
  76.     l=fread(buf,1,MAX_LINELEN,f); fclose(f);
  77.     if(l<=0 || l>MAX_LINELEN) return;
  78.     buf[l]=0;
  79.     for(p1=find_word_start(buf);*p1;p1=find_word_start(p2)) {
  80.       p2=find_word_end(p1); if(*p2) *p2++=0;
  81.       p3=strstr(host,p1); if(p3==NULL) continue;
  82.       if((p3==host || *(p3-1)=='.') && *(p3+strlen(p1))==0) return;
  83.     }
  84.     exit(1);  /* unauthorized sites refused. */
  85. }
  86.  
  87. /* open a TCP/IP socket with host/port
  88.  * returns the file descriptor for the socket */
  89. int net_connect(char *host)
  90. {
  91.     struct hostent *hp;
  92.     struct sockaddr_in sin;
  93.     int soc;
  94.  
  95.     secure(host);
  96.     if(!(hp = gethostbyname(host))) errorquit("unknown host.");
  97.     if((soc = socket(hp->h_addrtype,SOCK_STREAM,0))<0)
  98.       errorquit("socket() error");
  99.     memmove(&sin.sin_addr,hp->h_addr,hp->h_length);
  100.     sin.sin_port=htons(port);
  101.     sin.sin_family = hp->h_addrtype;
  102.     if(connect(soc,(struct sockaddr *)&sin,sizeof(sin))<0) {
  103.       close(soc); errorquit("connect() error");
  104.     }
  105.     return soc;
  106. }
  107.  
  108. int gethttps(char *host)
  109. {
  110.     char buf[65536];
  111.     char *tp;
  112.  
  113.     tp=getenv("tmp_dir"); if(tp!=NULL && *tp!=0) tmpdir=tp;
  114.     snprintf(tfname,sizeof(tfname),"%s/https.tmp",tmpdir);
  115.     snprintf(buf,sizeof(buf),"\
  116. mkdir -p %s\n\
  117. openssl s_client -connect %s:%d -quiet 2>/dev/null >%s <<@\n\
  118. %s\n\
  119. @\n", tmpdir,host,port,tfname,tbuf);
  120.     if (system(buf))
  121.       errorquit("system() error");
  122.     return open(tfname,O_RDONLY);
  123. }
  124.  
  125. int main(int argc, char *argv[])
  126. {
  127.     char *parm, *pt, *p1, *p2, *p3, *p4, *dp, *pre;
  128.     char nbuf[4096], *pp1, *pp2;
  129.     char c;
  130.  
  131.     parm=getenv("wims_exec_parm");
  132.     if(parm==NULL || *parm==0) errorquit("no_parameter");
  133.     snprintf(pbuf,sizeof(pbuf),"%s",parm);
  134.     p1=find_word_start(pbuf); p2=find_word_end(p1);
  135.     if(*p2!=0) *p2++=0;
  136.     https=0;
  137.     outf=stdout; pp1=getenv("w_webget_output");
  138.     pp2=getenv("session_dir");
  139.     if(pp1!=NULL && strstr(pp1,"..")==NULL && isalnum(*pp1) && pp2!=NULL) {
  140.       snprintf(nbuf,sizeof(nbuf),"%s/%s",pp2,pp1);
  141.       outf=fopen(nbuf,"w"); if(outf==NULL) outf=stdout;
  142.     }
  143.     dp=getenv("w_webget_option");
  144.     if(dp!=NULL && strstr(dp,"direct")!=NULL) { /* direct get */
  145.       p1=getenv("w_webget_host");
  146.       p2=getenv("w_webget_port");
  147.       if(p1==NULL || p2==NULL) errorquit("incomplete_request");
  148.       port=atoi(p2);
  149.       soc=net_connect(p1); if(soc==-1) return 1;
  150.       c=' '; for(p3=parm; *p3; p3++) {
  151.           if(*p3=='\n' && c!='\r') IGNORE(write(soc,"\r",1));
  152.           IGNORE(write(soc,p3,1)); c=*p3;
  153.       }
  154.       IGNORE(write(soc,"\r\n\r\n",4));
  155.       pt=getenv("w_module");
  156.       if(pt==NULL || *pt==0 || strncmp(pt,"adm/",4)==0 ) {  /* File to post? */
  157.           pt=getenv("w_webget_post"); if(pt!=NULL && *pt!=0) {
  158.             FILE *f;
  159.             char buf[4096];
  160.             size_t l;
  161.             f=fopen(pt,"r"); if(f!=NULL) {
  162.                 do {
  163.                   l=fread(buf,1,sizeof(buf),f);
  164.                   if(l>0 && l<=sizeof(buf)) IGNORE(write(soc,buf,l));
  165.                 } while(l==sizeof(buf));
  166.                 fclose(f);
  167.             }
  168.           }
  169.       }
  170.       if(strstr(dp,"normalread")!=NULL) goto read;
  171.       charcnt=0;
  172.       while(read(soc,pbuf,1)>0 && charcnt<10240) {
  173.           fputc(pbuf[0],outf); charcnt++;
  174.       }
  175.       close(soc);
  176.       return 0;
  177.     }
  178.     if(strncasecmp(p1,"http://",strlen("http://"))==0) p1+=strlen("http://");
  179.     else if(strncasecmp(p1,"https://",strlen("https://"))==0) {
  180.       https=1; p1+=strlen("https://");
  181.     }
  182.     p3=strchr(p1,'/'); if(p3==NULL) p3="";
  183.     else {*p3++=0; while(*p3=='/') p3++;}
  184.     if(strncasecmp(p3,"http://",strlen("http://"))==0 ||
  185.        strncasecmp(p3,"https://",strlen("https://"))==0) pre="";
  186.     else pre="/";
  187.     snprintf(tbuf,sizeof(tbuf),"GET %s%s HTTP/1.0\r\n%s\r\n\
  188. Host: %s\r\n\
  189. %s\r\n\r\n",
  190.            pre,p3,cheater1,p1,cheater2);
  191.     p4=strchr(p1,':'); if(p4==NULL) {
  192.       if(https) port=443; else port=80;
  193.     }
  194.     else {*p4++=0; port=atoi(p4);}
  195.     if(https) {
  196.       soc=gethttps(p1); goto read;
  197.     }
  198.     soc=net_connect(p1);
  199.     IGNORE(write(soc,tbuf,strlen(tbuf)));
  200. /* header */
  201.     read: if(soc==-1) return 1;
  202.     c=-1;
  203.     while(read(soc,pbuf,1)>0) {
  204.       if(pbuf[0]=='\r') continue;
  205.       fputc(pbuf[0],stderr);
  206.       if((c=='\n') && (pbuf[0]=='\n')) break; else c=pbuf[0];
  207.     }
  208. /* body */
  209.     charcnt=0;
  210.     while(read(soc,pbuf,1)>0 && charcnt<MAX_WEBGETFLEN) {
  211.       fputc(pbuf[0],outf); charcnt++;
  212.     }
  213.     close(soc);
  214.     if(outf!=stdout) fclose(outf);
  215.     if(https) unlink(tfname);
  216.     return 0;
  217. }
  218.  
  219.