//=-- AFStandard.cpp - Standard Access Filter Plugins ------------------------= // // AFUnEscape Class: // // This class provides the Unescape plugin that is used to remove the // escape codes from the URL that the browser references. // // AFRemoveIndexFilename Class: // // This class defines the RemoveIndexFilename plugin. Many servers respond // to queries for a directory by responding with an "index" file. For // example, if the "/" document is requested, typically /index.html is // returned. Unfortunately, without this plugin, the requests for those two // URLs are seperated. If "index.html" is specified to this plugin, then it // removes it so the statistics are combined. // // AFMask Class: // // This class masks off accesses by their URL so that people may get better // usage from the free version of MagicStats. // // AFTruncate Class: // // This class chops off the URL and Referrer fields of an access to a // specified length, if they are longer. This prevents huge URLs. // //=---------------------------------------------------------------------------= // This file is copyright (c) 1997-2000 Chris Lattner //=---------------------------------------------------------------------------= #include "LinkedList.h" #include "AccessFilterPlugin.h" #include "AccessFormatPlugin.h" #include "FilterManager.h" #include "VarTable.h" // AFUnEscape Class: // // This class provides the Unescape plugin that is used to remove the // escape codes from the URL that the browser references. Also fixes up // the referrer information. // class AFUnEscape : public PluginTemplate { public: inline AFUnEscape(int &CE) { CE = 0; } inline static unsigned int GetCurrentVersion() { return 100; // Version 1.00 } inline static const char *GetPluginName() { return "UnEscape"; } // The Filter method does the actual filtering for each Access. If it // returns a true value, the access is discarded. virtual int FilterAccess(AccessFormatPlugin &A) { String &Referrer = A.GetReferrer(); DoFilter(A.GetURL()); DoFilter(Referrer); // Some browsers emit "[unknown origin]" instead of - if (Referrer.Length() == 16) { if (Referrer == String("[unknown origin]")) Referrer = ""; } return 0; } void DoFilter(String &URL) { int i, j = 0, Len = URL.Length(); for (i = 0; i < Len; i++) { if (URL[i] == '%') { URL[i] = 16*String::Hex2Int(URL[i+1]) + String::Hex2Int(URL[i+2]); i += 2; } else if (URL[i] == '+') { URL[j] = ' '; } else { if (URL[i] == '/' && j > 0 && URL[j-1] == '/') { if (j <= 1 || URL[j-2] != ':') // Don't kill http:// or ftp:// i++; // Skip extra /'s } URL[j] = URL[i]; } j++; } URL.Left(j); // Trim URL to shortened length... } }; class AFTruncate : public PluginTemplate { private: int Length; public: inline AFTruncate(int &CE) { CE = 0; Length = 100; } inline static unsigned GetCurrentVersion() { return 100; // Version 1.00 } inline static const char *GetPluginName() { return "Truncate"; } virtual int Initialize(const VTListExp *Params) { // Get param 1: 0 is the plugin name const VTExp *Exp = Params->GetListElement(1); if (Exp && Exp->GetExpType() == VTExp::StringTy) Length = Exp->GetStringValue().atoi(); return 0; } // The Filter method does the actual filtering for each Access. If it // returns a true value, the access is discarded. virtual int FilterAccess(AccessFormatPlugin &A) { A.GetURL().Left(Length); A.GetReferrer().Left(Length); return 0; } }; // AFRemoveIndexFilename Class: // // This class defines the RemoveIndexFilename plugin. Many servers respond // to queries for a directory by responding with an "index" file. For // example, if the "/" document is requested, typically /index.html is // returned. Unfortunately, without this plugin, the requests for those two // URLs are seperated. If "index.html" is specified to this plugin, then it // removes it so the statistics are combined. // class AFRemoveIndexFilename : public PluginTemplate { public: inline AFRemoveIndexFilename(int &CE) { CE = 0; } inline static unsigned int GetCurrentVersion() { return 100; // Version 1.00 } inline static const char *GetPluginName() { return "RemoveIndexFilename"; } virtual int Initialize(const VTListExp *Params) { const VTExp *Exp; int Index = 1; // 0 = PluginName while ((Exp = Params->GetListElement(Index++))) { if (Exp->GetExpType() != VTExp::StringTy) { cout << "RemoveIndexFilename AccessFilter does not recognize " "argument '" << Exp << "'"; if (Exp->GetLineNo() != -1) cout << " from line #" << Exp->GetLineNo(); cout << endl; } else { IndexList.AddToTail(Exp->GetStringValue()); } } return 0; } virtual int FilterAccess(AccessFormatPlugin &A) { DoFilter(A.GetURL()); if (A.GetReferrer().Length() != 0) DoFilter(A.GetReferrer()); // Careful not to turn "" into "/" return 0; } void DoFilter(String &URL) { LLLink *Node = IndexList.GetHead(); while (Node) { if (Node->Data == URL) { URL = "/"; return; } String Temp(URL); Temp.Right(Node->Data.Length()); if (Temp == Node->Data) { URL.Left(URL.Length()-Node->Data.Length()); } Node = Node->GetNext(); } if (URL.Length() == 0) URL = "/"; } private: LinkedList IndexList; }; // AFMask Class: // // This class masks off accesses by their URL so that people may get better // usage from the free version of MagicStats. // class AFMask : public PluginTemplate { public: inline AFMask(int &CE) { CE = 0; } inline static unsigned int GetCurrentVersion() { return 100; // Version 1.00 } inline static const char *GetPluginName() { return "Mask"; } virtual int Initialize(const VTListExp *Params) { const VTExp *I, *E; if (Params->GetNumElements() != 3) { cout << "'Mask' AccessFilter expects two parameters!\n"; return 1; } // Get the include and exclude portions of the parameter... I = Params->GetListElement(1); // Param 1 (0 = PluginName) E = Params->GetListElement(2); // Param 2 if (!I || !E || I->GetExpType() != VTExp::StringTy || E->GetExpType() != VTExp::StringTy) { cout << "Mask AccessFilter expects two string parameters"; if (I->GetLineNo() != -1) cout << " from line #" << I->GetLineNo(); cout << "!\n"; return 1; } Mask = FilterManager::GetFilter(I->GetStringValue(), E->GetStringValue()); return 0; } virtual int FilterAccess(AccessFormatPlugin &A) { if (Mask.Match(A)) return 0; return 1; } private: FilterHandle Mask; }; // INIT_PLUGIN includes the plugins into the internal list of available ones INIT_PLUGIN(AFUnEscape); INIT_PLUGIN(AFTruncate); INIT_PLUGIN(AFRemoveIndexFilename); INIT_PLUGIN(AFMask);