/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Web Sniffer. * * The Initial Developer of the Original Code is Erik van der Poel. * Portions created by Erik van der Poel are * Copyright (C) 1998,1999,2000 Erik van der Poel. * All Rights Reserved. * * Contributor(s): Bruce Robson */ /* host and port of proxy that this proxy connects to */ #define PROXY_HOST "w3proxy.netscape.com" #define PROXY_PORT 8080 /* #define PROXY_HOST "127.0.0.1" #define PROXY_PORT 4444 */ #include "plat.h" #include #include #include #include #include #include #include #include #include #include #ifdef PLAT_WINDOWS #include #endif #include "html.h" #include "http.h" #include "mutex.h" #include "net.h" #include "utils.h" #include "view.h" typedef int (*Handler)(int fd); typedef struct FD { Handler handler; int id; FILE *logFile; int port; int suspend; int writeFD; } FD; typedef struct Arg { View *view; } Arg; DECLARE_MUTEX; static fd_set fdSet; static int id = 0; static u_short mainPort = 40404; static int maxFD = -1; static FD **table = NULL; static unsigned char suspendStr[1024]; static char *welcome = "HTTP/1.0 200 OK Content-Type: text/html Interceptor

HTTP Interceptor Persistent Window

Keep this window alive as long as you want to continue the session. It is recommended that you Minimize (Iconify) this window. Do not click the Back button in this window. Do not load another document in this window.

"; static FD * addFD(int fd, Handler func) { FD *f; if (fd > maxFD) { if (table) { table = utilRealloc(table, (maxFD + 1) * sizeof(*table), (fd + 1) * sizeof(*table)); } else { table = calloc(fd + 1, sizeof(*table)); } if (!table) { return NULL; } maxFD = fd; } f = malloc(sizeof(FD)); if (!f) { return NULL; } f->handler = func; f->id = -1; f->logFile = NULL; f->port = 0; f->suspend = 0; f->writeFD = -1; table[fd] = f; FD_SET(fd, &fdSet); return f; } static void removeFD(int fd) { FD *f; f = table[fd]; if (f) { FD_CLR(fd, &fdSet); if (f->logFile && (fileno(f->logFile) == fd)) { fclose(f->logFile); } else { close(fd); } free(f); table[fd] = NULL; } } static int logRequest(FD *f, Input *input) { Arg arg; HTTP *http; if ( (table[fileno(f->logFile)]->suspend) || (strstr(current(input), suspendStr)) ) { table[f->writeFD]->suspend = 1; return 0; } table[f->writeFD]->suspend = 0; fprintf ( f->logFile, "\n"); fflush(f->logFile); return 1; } static int readClientRequest(int fd) { FD *f; Input *input; f = table[fd]; input = readAvailableBytes(fd); write(f->writeFD, current(input), inputLength(input)); if (!logRequest(f, input)) { inputFree(input); } return 0; } static int logResponse(FD *f, Input *input) { Arg arg; HTTP *http; if ((table[fileno(f->logFile)]->suspend) || (f->suspend)) { return 0; } fprintf ( f->logFile, "\n"); fflush(f->logFile); return 1; } static int readProxyResponse(int fd) { FD *f; Input *input; f = table[fd]; input = readStream(fd, "readProxyResponse"); write(f->writeFD, current(input), inputLength(input)); if (!logResponse(f, input)) { inputFree(input); } removeFD(f->writeFD); removeFD(fd); return 0; } static int acceptNewClient(int fd) { FD *client; int clientFD; FD *f; FD *proxy; int proxyFD; clientFD = netAccept(fd); if (clientFD < 0) { fprintf(stderr, "netAccept failed\n"); return 0; } client = addFD(clientFD, readClientRequest); if (!client) { fprintf(stderr, "addFD failed\n"); return 0; } proxyFD = netConnect(NULL, PROXY_HOST, PROXY_PORT); if (proxyFD < 0) { fprintf(stderr, "netConnect to proxy %s:%d failed\n", PROXY_HOST, PROXY_PORT); return 0; } proxy = addFD(proxyFD, readProxyResponse); if (!proxy) { fprintf(stderr, "addFD failed\n"); return 0; } client->writeFD = proxyFD; proxy->writeFD = clientFD; f = table[fd]; client->logFile = f->logFile; proxy->logFile = f->logFile; client->id = id; proxy->id = id; id++; return 0; } static int readLoggerRequest(int fd) { unsigned char buf[10240]; int bytesRead; int doSuspend; FD *f; FILE *file; unsigned char *host; int i; unsigned char *p; u_short port; int proxyListenFD; unsigned char *resume; unsigned char *str; unsigned char *suspend; int suspendPort; bytesRead = read(fd, buf, sizeof(buf) - 1); if (bytesRead < 0) { if (errno != ECONNRESET) { perror("read"); } removeFD(fd); return 0; } else if (!bytesRead) { removeFD(fd); return 0; } buf[bytesRead] = 0; resume = "/resume"; suspend = "/suspend"; if (strstr(buf, "/exit")) { char *goodbye = "HTTP/1.0 200 OK\n" "Content-Type: text/html\n" "\n" "Bye!" ; write(fd, goodbye, strlen(goodbye)); removeFD(fd); return 1; } else if ((strstr(buf, resume)) || (strstr(buf, suspend))) { if (strstr(buf, resume)) { str = resume; doSuspend = 0; } else { str = suspend; doSuspend = 1; } p = strstr(buf, str); p += strlen(str); if (*p != '/') { char *notOK = "HTTP/1.0 200 OK\n" "Content-Type: text/html\n" "\n" "No backslash after command!" ; write(fd, notOK, strlen(notOK)); removeFD(fd); return 0; } sscanf(p + 1, "%d", &suspendPort); for (i = 0; i <= maxFD; i++) { if (table[i] && (table[i]->port == suspendPort)) { table[i]->suspend = doSuspend; break; } } if (i <= maxFD) { char *ok = "HTTP/1.0 200 OK\n" "Content-Type: text/html\n" "\n" "OK!" ; write(fd, ok, strlen(ok)); } else { char *notOK = "HTTP/1.0 200 OK\n" "Content-Type: text/html\n" "\n" "Cannot find port number in table!" ; write(fd, notOK, strlen(notOK)); } removeFD(fd); return 0; } /* XXX write(1, buf, bytesRead); */ file = fdopen(fd, "w"); if (!file) { char *err = "fdopen failed\n"; write(fd, err, strlen(err)); removeFD(fd); return 0; } table[fd]->logFile = file; port = 0; proxyListenFD = netListen(NULL, &host, &port); if (proxyListenFD < 0) { fprintf(file, "listen failed\n"); removeFD(fd); fclose(file); return 0; } f = addFD(proxyListenFD, acceptNewClient); if (!f) { fprintf(file, "addFD failed\n"); removeFD(fd); fclose(file); return 0; } fprintf ( file, welcome, host, port, host, mainPort, port, host, mainPort, port ); sprintf(suspendStr, "http://%s:%d/suspend/%d", host, mainPort, port); free(host); fflush(file); f->logFile = file; table[fd]->port = port; return 0; } static int acceptNewLogger(int fd) { FD *f; int newFD; newFD = netAccept(fd); if (newFD < 0) { fprintf(stderr, "netAccept failed\n"); return 0; } f = addFD(newFD, readLoggerRequest); if (!f) { fprintf(stderr, "addFD failed\n"); return 0; } return 0; } void reportContentType(void *a, unsigned char *contentType) { } void reportHTML(void *a, Input *input) { Arg *arg; arg = a; viewHTML(arg->view, input); } void reportHTMLAttributeName(void *a, HTML *html, Input *input) { Arg *arg; arg = a; viewHTMLAttributeName(arg->view, input); } void reportHTMLAttributeValue(void *a, HTML *html, Input *input) { Arg *arg; arg = a; viewHTMLAttributeValue(arg->view, input); } void reportHTMLTag(void *a, HTML *html, Input *input) { Arg *arg; arg = a; viewHTMLTag(arg->view, input); } void reportHTMLText(void *a, Input *input) { Arg *arg; arg = a; viewHTMLText(arg->view, input); } void reportHTTP(void *a, Input *input) { Arg *arg; arg = a; viewHTTP(arg->view, input); } void reportHTTPBody(void *a, Input *input) { Arg *arg; arg = a; viewHTTP(arg->view, input); } void reportHTTPCharSet(void *a, unsigned char *charset) { } void reportHTTPHeaderName(void *a, Input *input) { Arg *arg; arg = a; viewHTTPHeaderName(arg->view, input); } void reportHTTPHeaderValue(void *a, Input *input, unsigned char *url) { Arg *arg; arg = a; viewHTTPHeaderValue(arg->view, input); } void reportStatus(void *a, char *message, char *file, int line) { } void reportTime(int task, struct timeval *theTime) { } int main(int argc, char *argv[]) { FD *f; int fd; fd_set localFDSet; int ret; MUTEX_INIT(); fd = netListen(NULL, NULL, &mainPort); if (fd < 0) { fprintf(stderr, "netListen failed\n"); return 1; } f = addFD(fd, acceptNewLogger); if (!f) { fprintf(stderr, "addFD failed\n"); return 1; } while (1) { localFDSet = fdSet; ret = select(maxFD + 1, &localFDSet, NULL, NULL, NULL); if (ret == -1) { perror("select"); } for (fd = 0; fd <= maxFD; fd++) { if (FD_ISSET(fd, &localFDSet)) { if ((*table[fd]->handler)(fd)) { for (fd = 0; fd <= maxFD; fd++) { removeFD(fd); } return 0; } } } } return 1; }