#include #include #include #include #include #include /***************************************************************************** * TextCounter (C++ Version) Version 1.3.1 * * Copyright 1996-98 Matt Wright mattw@scriptarchive.com * * Created 03/14/96 Last Modified 06/24/98 * * Matt's Script Archive, Inc. http://www.scriptarchive.com/ * * Perl Version also available at Matt's Script Archive. * ****************************************************************************** * COPYRIGHT NOTICE * * Copyright 1996-98 Matthew M. Wright All Rights Reserved. * * * * TextCounter may be used and modified free of charge by anyone so long as * * this copyright notice and the comments above remain intact. By using this * * code you agree to indemnify Matthew M. Wright from any liability that * * might arise from it's use. * * * * Selling the code for this program without prior written consent is * * expressly forbidden. In other words, please ask first before you try and * * make money off of my program. * * * * Obtain permission before redistributing this software over the Internet or * * in any other medium. In all cases copyright and header must remain intact.* *****************************************************************************/ // Define Variables // Data Dir is the directory on your server that you wish to store the // count files in. Each page that has the counter on it will have it's own // file and a lock file will also be created in this directory. const char data_dir[] = "/path/to/data/"; // Valid-URI allows you to set up the counter to only work under specific // directories on your server. Include any of these directories as they // appear in a URI, into this array. More information on URI's available in // README. num_valid_uri is the number of valid URI's you have in the array. // As it is currently set, both valid uri and invalid uri blank, all pages // will be allowed. const int num_valid_uri = 0; const char valid_uri[num_valid_uri][128] = { }; // Invalid-URI allows the owner of this script to set up the counter so // that certain portions of the web server that may be included in Valid-URI // cannot use the program. Set num_invalid_uri to 0 and clear the array if // you don't want to use this. const int num_invalid_uri = 0; const char invalid_uri[num_invalid_uri][128] = { }; /****************************************************************************/ // Set Options // Show Link allows you to add a link around the counter to point to // either instructions explaining to users how to set this up on the system // (useful if a system administrator wants to allow anyone to set things up // themselves). Setting it to "" will make no link, otherwise put the URL // you want linked to the count here. const char show_link[] = "http://www.scriptarchive.com/"; // When Auto-Create is enabled, users will be able to auto-create the // count on their home pages by simply imbedding the Server Side Includes // call. Setting auto_create to 1 enables it, 0 will disable it. Only // users in @valid_uri will be allowed to auto create. const int auto_create = 1; // Show Date will show the date of when the count began if you set this // option to 1. It will appear in yor document as [Count] hits since [Date]. // Set this to 0 and it will simply return the [Count]. const int show_date = 1; // Lock Seconds will define the number of seconds the script should sit // and wait for the lock file to be gone before it will overwrite it if it // is still there. Every now and then a user will interrupt a page, causing // the script to halt and leave a lock file in place before the lock file // could be removed. This defines how long it waits. Nothing more than // 2 or 3 seconds should be needed. const int lock_sec = 2; // Padding Size define how many numbers will be shown as your count. For // instance, if you want your count to say 00065 and have the zeros padded // up to five digits, then set pad_size = 5; If the number goes higher // than the pad_size, don't worry, there just won't be any zero's tacked // onto the front. const int pad_size = 5; /****************************************************************************/ void main() { // Declare variables and subroutines char *count_page, *count_file, *lock_file; char c, date[32]; int i, count, count_page_len; ifstream count_in; ofstream count_out; int check_uri(char []); void error(char [], char []); void check_lock(char []); void create(char []); void print_count(int); // Print Content-type header for browser cout << "Content-type: text/html\n\n"; // Get the page location from the DOCUMENT_URI or QUERY_STRING // environment variables. if (!getenv("DOCUMENT_URI") && !getenv("QUERY_STRING")) error("no_uri","X"); // Get the count page's length and store the page name into count_page if (strlen(getenv("QUERY_STRING")) > 0) { count_page_len = strlen(getenv("QUERY_STRING")); count_page = new char[count_page_len]; strcat(count_page,getenv("QUERY_STRING")); } else { count_page_len = strlen(getenv("DOCUMENT_URI")); count_page = new char[count_page_len]; strcat(count_page,getenv("DOCUMENT_URI")); } // Check Valid-URI to make sure user can use this program. if (!check_uri(count_page)) error("bad_uri","X"); // Convert all non-alpha characters to _ to avoid security risks. for (i = 0; i < count_page_len; i++) if (!((count_page[i] > 96 && count_page[i] < 123) || (count_page[i] > 64 && count_page[i] < 91) || (count_page[i] > 47 && count_page[i] < 58))) count_page[i] = '_'; // Generate the lock filename. lock_file = new char[count_page_len + 4]; strcat(lock_file,data_dir); strcat(lock_file,count_page); strcat(lock_file,".lck"); // Check to see if file is locked by program already in use. check_lock(lock_file); // Generate the filename for the count page's data file. count_file = new char[count_page_len + strlen(data_dir)]; strcat(count_file,data_dir); strcat(count_file,count_page); // If the file exists, get the date and count out of it. Otherwise, if // auto_create is allowed, create a new account. If neither of these are // true, return an error. count_in.open(count_file); if (!count_in.fail()) { // Read in the current count. count_in >> count; // Skip a character and read in next one to begin loop. count_in.get(c); count_in.get(c); // Read in the date until the end of file or a new line. i = 0; while (!count_in.eof() && c != '\n') { date[i] = c; count_in.get(c); i++; } } else if (auto_create) { count_in.close(); create(count_file); } else { count_in.close(); error("page_not_found","X"); } // If the program got this far, close the file, since it hasn't been yet. count_in.close(); // Increment Count. count++; // Print the Count, Link and Date depending on what user has specified // they wish to print. if (strlen(show_link) > 0) cout << ""; print_count(count); if (strlen(show_link) > 0) cout << ""; if (show_date) cout << " hits since " << date; // Open the count file and write the new count that has been incremented. count_out.open(count_file); if (count_out.fail()) error("could_not_increment",count_file); else count_out << count << " " << date; count_out.close(); // Remove Lock File for next time script is run on that HTML page. unlink(lock_file); delete count_page; delete count_file; delete lock_file; exit(0); } int check_uri(char uri[]) { // Declare variables int st = 0, uri_check = 0; int valid_uri_len, invalid_uri_len, i, j; // For each valid URI, check to see if the current uri is included in that // valid URI. If so, set the uri check flag to 1 and break out of loop. for (i = 0; i < num_valid_uri; i++) { valid_uri_len = strlen(valid_uri[i]); for (j = 0; j < valid_uri_len; j++) { if (valid_uri[i][j] == uri[st]) st++; else st = 0; if (st == valid_uri_len) { uri_check = 1; break; } } } // Reset counter st. st = 0; // For each invalid URI, check to see if current uri is included in that // invalid URI. If so, set the uri check flag to 0 and break out of loop. for (i = 0; i < num_invalid_uri; i++) { invalid_uri_len = strlen(invalid_uri[i]); for (j = 0; j < invalid_uri_len; j++) { if (invalid_uri[i][j] == uri[st]) st++; else st = 0; if (st == invalid_uri_len) { uri_check = 0; break; } } } // If both num_valid_uri and num_invalid_uri are set to 0, set the uri // check flag to 1, because it is possible QUERY_STRING is being used. if (!num_valid_uri && !num_invalid_uri) uri_check = 1; // Return the uri check flag value. return uri_check; } void create(char count_file[]) { // Declare variables and subroutines. char *date; char months[12][10] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; tm *ptm; time_t *cur_time; ofstream count_out; void error(char [], char []); void print_count(int); // Set up the memory for the time and time time struct. cur_time = new time_t; ptm = new tm; // Get the time, then create the struct with time values. time(cur_time); ptm = localtime(cur_time); // Write to the file, sending back an error if it fails. count_out.open(count_file); if (count_out.fail()) error("count_not_created",count_file); else count_out << 1 << " " << months[ptm->tm_mon] << " " << ptm->tm_mday << ", " << ptm->tm_year + 1900; count_out.close(); // Print the Count, Link and Date depending on what user has specified // they wish to print. if (strlen(show_link) > 0) cout << ""; print_count(1); if (strlen(show_link) > 0) cout << ""; if (show_date) cout << " hits since " << months[ptm->tm_mon] << " " << ptm->tm_mday << ", " << ptm->tm_year + 1900; ; delete date; delete ptm; delete cur_time; exit(0); } void print_count(int count) { // Declare variables. int i, size = 0; float count_tmp = count; // This determines the size of the count integer by divinding by 10 until // the result is less than 1. while (count_tmp >= 1) { count_tmp /= 10; size++; } // Pad the number with 0's if pad_size is greater than the count size. for (i = 0; i < (pad_size - size); i++) cout << 0; // Print the count. cout << count; } void error(char error[], char opt_file[]) { // Determine which flag was set and output appropriate error. if (strcmp(error,"page_not_found") == 0) cout << "[TextCounter Fatal Error: This Page Not Found; Auto-Create Option Disabled]"; else if (strcmp(error,"no_uri") == 0) cout << "[TextCounter Fatal Error: No Document URI or File Flag specified]"; else if (strcmp(error,"bad_uri") == 0) cout << "[TextCounter Fatal Error: This Page Not In Valid URI]"; else if (strcmp(error,"count_not_created") == 0) cout << "[TextCounter Fatal Error: Could Not Write to File " << opt_file << "]"; else if (strcmp(error,"could_not_increment") == 0) cout << "[TextCounter Fatal Error: Could Not Increment Counter File " << opt_file << "]"; exit(0); } void check_lock(char lock_file[]) { // Declare variables. int i; ifstream test_in; ofstream test_out; // For the number of seconds defined in lock_sec... for (i = 1; i <= lock_sec; i++) { // Open the file for reading. test_in.open(lock_file); // If that fails, the lock file doesn't exis. We create the lock file // and exit the loop. Otherwise sleep for a second. if (test_in.fail()) { test_out.open(lock_file); test_out << 0; test_out.close(); break; } else sleep(1); // Close the file if it is still open. test_in.close(); } }