Logo Search packages:      
Sourcecode: hitop version File versions

hitoplive.cc

// hitop - an HTML preprocessor
// Copyright 1997-2002 David Marshall & Darren Edmundson

#ifndef __tokenmaph__
  #include "tokenmap.h"
#endif
#ifndef __hitopcoreh__
  #include "hitopcore.h"
#endif
#ifndef __htmlstreamh__
  #include "htmlstream.h"
#endif
#ifndef __htmlh__
  #include "html.h"
#endif
#ifndef __errorh__
  #include "error.h"
#endif
#ifndef __tables_entitiesh__
  #include "tables/entities.h"
#endif
#include "fdstream.h"

#include <fstream>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>

extern "C" char** environ;

static string g_warnings;

static string ObliteratePassword(const string& message) {
  string uc=message,output=message,replace="PASSWORD=";
  string::iterator pos = uc.begin(),pos2,pos3,pos4;
  transform(uc.begin(),uc.end(),uc.begin(),ToUpper());
  do {
    pos = search(uc.begin(),uc.end(),replace.begin(),replace.end());
    if (pos!=uc.end()) {
      pos2=pos+replace.length();
      if (pos2!=uc.end()) {
        if ((*pos2=='\'') || (*pos2=='"')) {
        //quoted string
        pos3=find(pos2+1,uc.end(),*pos2);
        if (pos3!=uc.end()) ++pos3;
      } else {
        //space or > terminated
        pos3=find(pos2,uc.end(),' ');
        pos4=find(pos2,uc.end(),'>');
        if (pos4<pos3) pos3=pos4;
      }
      } else {
        pos3=uc.end();
      }
      output.erase(pos-uc.begin()+output.begin(),pos3-uc.begin()+output.begin());
      uc.erase(pos,pos3);
      pos=uc.begin(); // again, for security
    }
  } while (pos!=uc.end());
  return output;
}

void ErrorFooter(){

cout<<"<hr /><p align=\"center\">Hitoplive "+g_version+" \
&copy;"+g_years+" David Marshall &amp; Darren \
Edmundson\n("+g_dateISO+")<br /><a \
href=\"http://www.hitop.org/\">www.hitop.org</a></body></html>";

}

void doError(const string& mess) {

cout <<"Status: 500\nContent-type: text/html\n\n<head><title>500 - \
Internal Server Error</title></head><body bgcolor=\"#FFFFFF\"><h1>Error \
500&nbsp;- Internal Server Error</h1><p>We're sorry, but we were unable \
to process your request because an error occured while preparing your \
page. The following information may be of use to you in tracing the \
problem:</p><blockquote>" << EscapeSignificant(ObliteratePassword(mess))
<< "</blockquote>";

  ErrorFooter();
  exit(0);
}

void do_404() {

cout <<"Status: 404\nContent-type: text/html\n\n<head><title>404 - Not \
Found</title></head><body bgcolor=\"#FFFFFF\"><h1>Error 404&nbsp;- Not \
Found</h1><p>We're sorry, but we were unable to process your request \
because the resource you requested was not found.";

  ErrorFooter();
  exit(0);
}

void doWarn(const string& mess) {
  g_warnings+=ObliteratePassword(mess);
  g_warnings+="\n";
}

void doDebug(const string& mess) {
  g_warnings+=ObliteratePassword(mess);
  g_warnings+="\n";
}

static void DoEnv(HTMLStream *Main){
  string::iterator sep;
  char** current = environ;
  if (current == NULL) return;
  string varName,varVal,line;
  while (*current != NULL) {
    line=*current;
    sep=find(line.begin(),line.end(),'=');
    varName = string(line.begin(),sep);
    if (sep!=line.end()) ++sep;
    varVal  = Entities::Escape(string(sep,line.end()));
    Main->SetVar("ENV_"+varName,varVal,Vars::Global);
    ++current;
  }
}

static void DoSetFormVar(HTMLStream *Main, string FormPair) {
  if (!FormPair.empty()) {
    string::iterator sep,xform;
    if (FormPair.end() != (sep=find(FormPair.begin(),FormPair.end(),'='))) {
      string var="FORM_"+unescape(string(FormPair.begin(),sep));
      while (var.end()!=(xform=find(var.begin(),var.end(),' '))) {
        *xform='_';
      }
      while (var.end()!=(xform=find(var.begin(),var.end(),'.'))) {
        *xform='_';
      }
      Main->SetVar(var,Entities::Escape(unescape(string(++sep,FormPair.end()))),Vars::Global);
    } else {
      string var="FORM_"+unescape(string(FormPair.begin(),sep));
      while (var.end()!=(xform=find(var.begin(),var.end(),' '))) {
        *xform='_';
      }
      while (var.end()!=(xform=find(var.begin(),var.end(),'.'))) {
        *xform='_';
      }
      Main->SetVar(var,"",Vars::Global);
    }
  }
}

static void DoGenericForm(HTMLStream *Main, string FormData) {
  string::iterator sep=FormData.begin(),start=FormData.begin();
  while (FormData.end() != (sep = find(start,FormData.end(),'&'))) {
    DoSetFormVar(Main,string(start,sep));  
    start=sep+1;
  }
  DoSetFormVar(Main,string(start,FormData.end()));
}

static void DoGetForm(HTMLStream *Main) {
  char* qstring=getenv("QUERY_STRING");
  if(qstring!=NULL) DoGenericForm(Main,qstring);
}

static void DoPostForm(HTMLStream *Main) {
  char *clen =getenv("CONTENT_LENGTH");
  if (clen == NULL) return;
  unsigned int bytes = atoi(clen);
  char *buffer = new char[bytes+1];
  cin.read(buffer,bytes);
  buffer[bytes]=0;
  DoGenericForm(Main,buffer);
  delete [] buffer;
}

static void DoForm(HTMLStream *Main){
  char *method = getenv("REQUEST_METHOD");
  if(method==NULL) return;
  if (0==strcmp(method,"GET")) {
    DoGetForm(Main);
  } else if (0==strcmp(method,"POST")) {
    DoPostForm(Main);
  }
}

static void DoOneCookie(HTMLStream *Main, string::iterator &begin,
  string::iterator end) {
  string::iterator startofname=begin,endofname,startofval,endofval;
  while ((startofname!=end)&&(*startofname==' ')) startofname++;
  endofname=find(startofname,end,'=');
  if (endofname==end) {
    begin=end;
    return;
  }
  startofval=endofname+1;
  //chomp whitespace around the '='
  while (((endofname-1)!=begin)&&(*(endofname-1)==' ')) --endofname;
  while ((startofval!=end)&&(*startofval==' ')) ++startofval;
  if (startofval==end) {
    begin=end;
    return;
  }
  if (*startofval=='"') { //quoted string - RFC2109 style
    ++startofval;  
    endofval = find(startofval,end,'"');
  } else { //token - netscape style
    endofval = find(startofval,end,';');
  }
  if (endofval!=end) {
    begin=endofval+1;
  } else {
    begin=end;
  }
  Main->SetVar(string("COOKIE_")+string(startofname,endofname),string(startofval,endofval),Vars::Global);
};

static void DoCookies(HTMLStream *Main) {
  char* ccookies = getenv("HTTP_COOKIE");
  if (ccookies==NULL) return;
  string cookies =ccookies;
  string::iterator i = cookies.begin();
  while (i!=cookies.end()) {
    DoOneCookie(Main,i,cookies.end());
  }
}

static string calcPath(string filename){
  // Nasty hack time, boys and girls
  // looks in the current and each parent directory until it finds a hitop.base
  // file, and the calculates the relative path between the two...
  // things that can go wrong: symlinks!
  if (0 != chdir(PathPart(filename).c_str())) {
    Error("Cannot chdir to "+PathPart(filename));
  }
  struct stat statInfo;
  char* ccwd;
  ccwd = getcwd(NULL,0);
  if (ccwd==NULL) {
    Error("getcwd returned NULL.");
  }
  int dircount = count(ccwd,ccwd+strlen(ccwd),'/');
  bool found = false;
  while ((!found) && (dircount>0))  {
    if (found=(0==stat("hitop.base",&statInfo))) {
      // we found it! *Yeah*
      found = true;
    } else {
      chdir("..");
      --dircount;
    }
  }
  if (!found) {
    Error("Could not find the hitop.base file");
  }
  char* baseCwd = getcwd(NULL,0);
  if (baseCwd==NULL) {
    Error("getcwd() returned null.");
  }
  string fullpath = filename;
  fullpath = ccwd;
  fullpath+='/';
  fullpath+=FilePart(filename);
  string relative = string(fullpath.begin()+strlen(baseCwd)+1,fullpath.end());
  free(baseCwd);
  free(ccwd);
  return relative;
}

int main(int argn,char* argc[]){
  timeval starttime;
  gettimeofday(&starttime,NULL);
  TokenMap::Init();
  const string About("hitoplive "+g_version+" "+g_years+" David Marshall\n("+
    g_dateISO+") http://www.hitop.org/");
  const string Usage("Usage: hitoplive infile.hitop [outfile.html]");
  string inFile;
  char *ptrans = getenv("PATH_TRANSLATED");
  if (ptrans == NULL) Error("No PATH_TRANSLATED set. Are you sure this is cgi?");
  int fd=open(ptrans,O_RDONLY);
  if (fd==-1) {
    do_404();
  }
  inFile = calcPath(ptrans);
  HTMLStream Main;
  Main.m_FName=inFile;
  fdistream InFile(fd);
  InFile>>Main;
  Main.SetVar("FILE",inFile,Vars::Global);
  string path=PathPart(inFile);
  Main.SetVar("RELPATH",replicate("../",count(path.begin(),path.end(),'/')),Vars::Global);
  Main.m_ThisPath=path;
  DoVars(&Main);
  DoEnv(&Main);
  DoForm(&Main);
  DoCookies(&Main);
  Main.Process();
  if(!g_isXML&&g_isHTML) Main.CheckHTML();
  if (!g_statusHeader.empty()) cout<<"Status: "<<g_statusHeader<<endl;
  for(multimap<string,string>::iterator i=g_httpHeader.begin();i!=g_httpHeader.end();++i){
    cout<<i->first<<": "<<i->second<<endl;
  }
  cout<<"Content-type: "<<g_contentType<<"\n\n" << Main;
  timeval endtime;
  gettimeofday(&endtime,NULL);
  long int runtime = (endtime.tv_usec - starttime.tv_usec)+ 1000000*(endtime.tv_sec-starttime.tv_sec);
  cout<<"<!-- "<<g_warnings<<runtime<<" microseconds -->"<<endl;
}

Generated by  Doxygen 1.6.0   Back to index