/***********************************************************************************/ /* * siffi.c: CGI Programm, das Statistiken erstellt & ausgiebt * * ***********************************************************************************/ #include #include #include #include #include #include #include #include /*********************/ /* Data File entries */ /*********************/ #define IPADDRESS "*IP:" #define HOSTNAME "#Hostname:" #define ZEIT "#Zeit:" #define NAVIGATOR "#Navigator:" #define EMAIL "#email:" /*********************************/ /* known & defined query_strings */ /*********************************/ #define COLLECT "ds=gugus" #define COLLECTSIFFI "ds=siffi" #define LIST "ds=list" #define LISTME "ds=listme" #define LISTALL "ds=listall" #define LISTMONTH "ds=listmonth" #define LISTSIFFIALL "ds=listsiffiall" #define LISTSIFFIMONTH "ds=listsiffimonth" /*******************/ /* data file names */ /*******************/ #define KATFCOUNT "sifficount.txt" #define SIFFICOUNT "siffihome.txt" #define KnownNamesFile "SiffisVIP.txt" #define GifFile "best.gif" /*****************/ /* defined links */ /*****************/ #define SIFFISMAIL "mailto:erich_siffert@notesbe.krinfo.ch" #define SIFFISHOME "http://www.siffert.ch/" #define KATFHOME "http://www.siffert.ch/kat_f.htm" #define MYSTAT "http://notes.krinfo.ch/cgi-bin/siffi.exe?ds=listme" #define ALLSTAT "http://notes.krinfo.ch/cgi-bin/siffi.exe?ds=listall" #define MONTHSTAT "http://notes.krinfo.ch/cgi-bin/siffi.exe?ds=listmonth" #define SIFFIMONTH "http://notes.krinfo.ch/cgi-bin/siffi.exe?ds=listsiffimonth" #define SIFFIALL "http://notes.krinfo.ch/cgi-bin/siffi.exe?ds=listsiffiall" #define NOTME 2 #define ONLYME 1 #define ALLUSERS 0 #define MAXHIT 128 char* query_string, // query info passed to pgm. Appended to URL with "?" * remote_host, // remote hostname of user making the request * remote_addr, // remote IP address of user making the request * remote_user, // authenticated name of user * remote_ident, // only set if client supports RFC 931 & NCSA IdentityCheck flag enabled * http_from, // email address of user (most broswers do not support) * http_user_agent, // the browser the client is using to issue request * http_referer; char* pLine; // Pointer to line from inputfile char* pIdent; char* DataFile; char chOutput [256]; // working array.... char chTime[64]; // to hold the time... char Month [3] = " "; u_long ip; // ip address int iFlag, i; int iPerCounter =0, iAllCounter = 0; // hit-counters // struct sockaddr_in client; /* client address information */ struct hostent *hostnm; // struct containing client name information FILE *fp; // file pointer for "data" file FILE *fnames; // file pointer for file containing known names char buffer [4096]; // output buffer for gif-file time_t temp; // variable for local time struct tm *timeptr; // time-structure, used to build LOG-file name struct UserTab { char IPAddress[20]; char Hostname[32]; char Time[3]; int hits; } ; struct UserTab HitTab [MAXHIT]; void ListMonth(void); void WriteMonth(void); /********************************************************************/ /* MAIN */ /********************************************************************/ void main (int argc, char * argv[]) { /**************************************/ /* read the environment variables.... */ /**************************************/ query_string = getenv ("QUERY_STRING"); remote_host = getenv ("REMOTE_HOST"); remote_addr = getenv ("REMOTE_ADDR"); remote_user = getenv ("REMOTE_USER"); remote_ident = getenv ("REMOTE_IDENT"); http_from = getenv ("HTTP_FROM"); http_user_agent = getenv ("HTTP_USER_AGENT"); http_referer = getenv ("HTTP_REFERER"); // Test-Stuff //query_string = "ds=listsiffimonth"; //query_string = "ds=siffi"; //remote_addr = "193.192.19.143"; /**************************************/ /* initialize current date and time */ /**************************************/ temp = time(NULL); timeptr = localtime(&temp); strftime(chTime,sizeof(chTime)-1,"%a, %b %d %Y at %H:%M:%S", timeptr); /*********************************************************************/ /* received an empty query string... do nothing in this case */ /*********************************************************************/ if (query_string == NULL) { printf("Content-type: text/plain\n\n"); printf("You didn't supply any information to siffi.exe," " this means: the query string is null and the program has no idea what to do!" ); } /********************************************************************************/ /* in this section we collect the statistics and try to display an image....... */ /********************************************************************************/ else if ( strlen(query_string) > 0 && ( memcmp(query_string, COLLECT, strlen( COLLECT ) ) == 0 || memcmp(query_string, COLLECTSIFFI, strlen(COLLECTSIFFI) ) == 0 ) ) { /*********************************************************************************/ /* print out a "dummy" gif file to collect data */ /* (this is done by adding a link like */ /*********************************************************************************/ if ( (fp = fopen( GifFile, "rb" ) ) == NULL) { // read the Gif-file printf("Content-type: text/plain\n\n"); // and print it to the screen fprintf(stderr, "Could not open %s\n", GifFile); // really quick'n'dirty! } else { printf("Content-type: image/gif\n\n"); while ( !feof (fp) ) { i = fread( buffer, 1, sizeof(buffer), fp); if ( ferror(fp) ) { printf("Error while reading %s\n", GifFile); } fwrite( buffer, i, 1, stdout); } } fclose(fp); /********************************************/ /* set the data file name */ /********************************************/ if (memcmp(query_string, COLLECT, strlen(COLLECT) ) == 0) { DataFile = KATFCOUNT; } else if (memcmp(query_string, COLLECTSIFFI, strlen(COLLECTSIFFI) ) == 0) { DataFile = SIFFICOUNT; } else { printf("No valid Data File name to open received!"); } if ((fp = fopen( DataFile, "a")) == NULL) { fprintf(stderr, "Could not open datafile"); } else { fprintf( fp, "%s%s\n", IPADDRESS, remote_addr); // get the users ip address // sock_init(); ip = inet_addr(remote_addr); // get the users hostname hostnm = gethostbyaddr( (char *) &ip, sizeof(ip), AF_INET ); if (hostnm != NULL) { fprintf(fp,"%s%s\n", HOSTNAME, hostnm->h_name); fflush(fp); } else { fprintf(fp, "%s(no hostname defined)\n", HOSTNAME); } fprintf( fp, "%s%s\n", ZEIT, chTime); // print current time if (http_user_agent != NULL) { // save info concering used browser fprintf( fp, "%s%s\n", NAVIGATOR, http_user_agent); } if (http_from != NULL) { // get email address if possible fprintf( fp, "%s%s\n", EMAIL, http_from); } fclose(fp); // all done, close datafile } } /********************************************************************************/ /* in this section we are going to display the stored data */ /********************************************************************************/ else if ( strlen(query_string) > 0 && memcmp(query_string, LIST, strlen( LIST ) ) == 0) { printf ( "Content-type: text/html\n\n"); printf ( "Listing access statistic for %s at %s" "" "

", remote_addr, chTime); /**********************************************************/ /* well-known ip addresses are contained in this file. */ /* prepare a personal welcome if we know this user! */ /**********************************************************/ if ((fnames = fopen( KnownNamesFile, "r")) == NULL) { // do nothing ... } else { while ( !feof(fnames) ) { // loop over this file if (( (pLine = fgets(chOutput, sizeof(chOutput)-1, fnames)) != NULL) && (memcmp(pLine, remote_addr, strlen(remote_addr)) == 0) ) { pLine = strchr(chOutput, '#'); if (pLine != NULL) { pLine++; printf("%s
", pLine); // print the personal welcome msg } } } fclose(fnames); } /*******************************************************/ /* check now what we have to do: read the query_string */ /* and make necessary settings... */ /*******************************************************/ if (memcmp(query_string, LISTALL, strlen(LISTALL) ) == 0) { // list everything pIdent = "the overall statistic for
the Kat F Homepage

"; DataFile = KATFCOUNT; } else if (memcmp(query_string, LISTMONTH, strlen(LISTMONTH) ) == 0) { //list by month pIdent = "the overall by month statistic for
the Kat F Homepage"; DataFile = KATFCOUNT; } else if (memcmp(query_string, LISTME, strlen(LISTME) ) == 0) { // list my entries // list only my entries pIdent = "YOUR personal statistic for
the Kat F Homepage"; DataFile = KATFCOUNT; } else if (memcmp(query_string, LISTSIFFIALL, strlen(LISTSIFFIALL) ) == 0) { // siffis home pIdent = " the overall statistic for
Siffis Homepage"; DataFile = SIFFICOUNT; } else if (memcmp(query_string, LISTSIFFIMONTH, strlen(LISTSIFFIMONTH) ) == 0) { pIdent = "the overall by month statistic for
Siffis Homepage"; DataFile = SIFFICOUNT; } else { // unusable & strange stuff supplied! printf("Sorry, but I have no idea what you really want & I can't help you!
" "Please try it again with a valid query_string
" "This program will be terminated now (w/o error)...."); printf(""); return; } /******************************/ /* print welcome message */ /******************************/ printf ( "Dear user at %s, I'll prepare now %s" "(btw: your are coming from %s)
", remote_addr, pIdent, KATFHOME, http_referer, http_referer); printf ("

Local time in Bern, Switzerland is %s

\n", chTime); /**********************************/ /* open the datafile in read mode */ /**********************************/ if ((fp = fopen( DataFile, "r")) == NULL) { printf("Could not open the data file %s
"); printf("Please inform Siffi and try later!", DataFile, SIFFISMAIL); } else { /******************************************************/ /* Listing by month is required. Got to "ListMonth()" */ /******************************************************/ if (memcmp(query_string, LISTMONTH, strlen (LISTMONTH) ) == 0 || memcmp(query_string, LISTSIFFIMONTH, strlen(LISTSIFFIMONTH) ) == 0) { ListMonth(); } else { printf("\n"); printf("\n" "\n" "\n" "\n" "\n" "\n" "\n"); /**********************************/ /* read all entries from datafile */ /**********************************/ while ( !feof(fp)) { if ((pLine = fgets(chOutput, sizeof(chOutput)-1, fp)) != NULL) { if (*pLine == '*') { // first entry: '*IPADDRESS:' pLine += strlen(IPADDRESS); iAllCounter++; if (memcmp(query_string, LISTALL, strlen(LISTALL)) == 0 || memcmp(query_string, LISTSIFFIALL, strlen(LISTSIFFIALL) ) == 0) { iFlag = ALLUSERS; } else { // List only my Hits! if (memcmp(remote_addr, pLine, strlen(remote_addr) ) == 0) { iFlag = ONLYME; iPerCounter++; } else { // we found a hit from another user... iFlag = NOTME; } } if (iFlag != NOTME) { printf("\n"); } } else if (memcmp(pLine, HOSTNAME, strlen(HOSTNAME) ) == 0) { pLine += strlen( HOSTNAME); } else if (memcmp(pLine, ZEIT, strlen(ZEIT) ) == 0) { pLine += strlen( ZEIT); } else if (memcmp(pLine, NAVIGATOR, strlen(NAVIGATOR) ) == 0) { pLine += strlen( NAVIGATOR); } else if (memcmp(pLine, EMAIL, strlen(EMAIL) ) == 0) { pLine += strlen( EMAIL); } if (iFlag != NOTME) { printf("", pLine); } } } fclose(fp); // close the data file printf("
IP-AddressHostnameTime (CET)Navigatoremail
%s
\n"); // make proper html code if (memcmp(query_string, LISTME, strlen(LISTME) ) == 0) { printf("


Dear %s, you had %i hits on the Kat-F " "Homepage (overall %i hits since Jan 28 1998)
", remote_addr, iPerCounter, iAllCounter); } else if (memcmp(query_string, LISTSIFFIALL, strlen(LISTSIFFIALL) ) == 0) { printf("


Dear %s, Siffis " "Homepage had %i hits since Feb 27 1998
", remote_addr, iAllCounter); } else { printf("


Dear %s, the Kat-F " "Homepage had %i hits since Jan 28 1998
", remote_addr, iAllCounter); } } } printf ("


\n"); if (memcmp(query_string, LISTME, strlen(LISTME) ) == 0) { printf("[ Overall statistic ", ALLSTAT); printf("| Monthly statistic/per Address ", MONTHSTAT); } else if (memcmp(query_string, LISTMONTH, strlen(LISTMONTH) ) == 0) { printf("[ Your personal statistic ", MYSTAT); printf("| Overall statistic ", ALLSTAT); } else if (memcmp(query_string, LISTSIFFIMONTH, strlen(LISTSIFFIMONTH) ) == 0) { printf("[ Overall statistic ", SIFFIALL); } else if (memcmp(query_string, LISTSIFFIALL, strlen(LISTSIFFIALL) ) == 0) { printf("[ Monthly /by hostname ", SIFFIMONTH); } else { printf("[ Your personal statistic ", MYSTAT); printf("| Monthly statistic/per Address ", MONTHSTAT); } printf (" | Contact Siffi | " " Kat F Home | " " Siffi's home]\n", SIFFISMAIL, KATFHOME, SIFFISHOME); printf ( "
"); } /********************************************************************/ /* no query_string supplied. copy this to the browser... */ /********************************************************************/ else { printf("Content-type: text/html\n\n"); printf("Sorry, you didn't supply any information (or unusable information) to \"Siffi.exe\" and in this case" " nothing will happen of course....
" ); printf("The only thing you can do: Go back to your last page...
" "see you soon!", http_referer); } return; } /***************************************************/ /* Function ListMonth: lists entries by Month */ /***************************************************/ void ListMonth( void ) { int it = 0, iFound = 0; iPerCounter = iAllCounter = i = 0; printf("
\n"); printf("\n" "\n" "\n" "\n" "\n" "\n"); while ( !feof(fp) && i < MAXHIT ) { if ((pLine = fgets(chOutput, sizeof(chOutput)-1, fp)) != NULL) { if (*pLine == '*') { // first entry: '*IPADDRESS:' pLine += strlen(IPADDRESS); iAllCounter++; iPerCounter++; for ( it = 0; it <= i; it++) { // check if already in HitTab! if (memcmp(HitTab [it].IPAddress, pLine, strlen(pLine)) == 0) { HitTab[it].hits++; iFound++; break; } } if (iFound == 0) { // no, not yet in HitTab. Copy this entry memset(HitTab [i].IPAddress, '\0', sizeof(HitTab[i].IPAddress) ); memcpy(HitTab [i].IPAddress, pLine, strlen(pLine) ); HitTab[i].hits = 1; } } else if (memcmp(pLine, HOSTNAME, strlen(HOSTNAME) ) == 0 && iFound == 0) { pLine += strlen( HOSTNAME); memset(HitTab [i].Hostname, '\0', sizeof(HitTab[i].Hostname) ); memcpy(HitTab [i].Hostname, pLine, strlen(pLine) ); i++; } else if (memcmp(pLine, ZEIT, strlen(ZEIT) ) == 0) { pLine = strchr(chOutput, ','); pLine += 2; if (memcmp(&Month[0], pLine, 3) != 0 && i > 1) { // another month! Write content of HitTab to client, reset everything WriteMonth (); i = 0; iPerCounter = 0; } memcpy(&Month[0], pLine, 3); iFound = 0; } } if (i >= MAXHIT) { printf("

Sorry but the <HitTab>-struct is too small for the existing" "ammount of data! The output will be stopped now!
Please inform " "Siffi and try later
" "


Thanks a lot!", SIFFISMAIL, chTime); fclose(fp); return; } } fclose(fp); WriteMonth(); printf("
MonthHostnameIP-Address# of Hits
\n"); printf("
Overall Counts: %i

", iAllCounter); return; } /********************************************/ /* write one month to clients browser */ /********************************************/ void WriteMonth(void) { int iCount = 0; printf("
" "%s
", Month); while ( iCount < i) { printf("%s", HitTab[iCount].Hostname); printf("%s", HitTab[iCount].IPAddress); if (HitTab[iCount].hits >= 10) { printf("
%i
", HitTab[iCount].hits); } else { printf("
%i
", HitTab[iCount].hits); } iCount++; } printf("Total in %s: %i", Month, iPerCounter); return; }