def guess_plugin(self, plugin_name):
     """Check for the existence of the named plugin"""
     path_nodes, version_nodes, all_versions = \
         wadt.loadTables(wac.getDbPath(self.app_name, plugin_name), False)
     self.error_page_fingerprint = wafu.identify_error_page(self.url)
     
     for file in wafu.pick_indicator_files(version_nodes, all_versions):
         try:
             #TODO: factor out construction of path to plugin files... 
             #not all plugin dirs can be found simple appending
             url = self.url + plugin_name + file
             #self.logger.logExtraInfo("    Trying " + url + "...")
             data = wafu.urlread_spoof_ua(url)
             #Check for custom 404
             if wafu.compare_to_error_page(self.error_page_fingerprint, data):
                 return False                
             #self.logger.logExtraInfo("found!")
             return True
             break
         except urllib2.URLError, e:
             #self.logger.logExtraInfo("URLError: %s" % e)
             pass
         except HTTPException, e2:
             #self.logger.logExtraInfo("HTTPError: %s" % e2)
             pass
 def fingerprint_file(self, path):
     """Fingerprint a single file given the path, and return a list
     possible versions implied by the result, or None if no information
     could be gleaned.
     """
     try:
         url = self.url + (path if path.startswith("/") else "/"+path)
         data = wafu.urlread_spoof_ua(url)
         self._host_down_errors = 0
         hash = hashlib.md5(data + path).hexdigest()
         
         if self.path_nodes.has_key(hash):
             possible_vers = self.path_nodes[path][hash]
             self.logger.logFileHit(path, possible_vers, None, None, False)
             return possible_vers
         else:
             #HACKHACK TODO: Implement proper solution to small modifications of
             #source files
             ms = wafm.MASSAGERS
             
             #run all combinations of massagers to see if they can change the 
             #remote file into something we expect
             for i in range(1, len(ms)+1):
                 for massagersTpl in itertools.combinations(ms, i):
                     massagedData = data
                     for m in massagersTpl:
                         massagedData = m(massagedData)
                     massagedhash = hashlib.md5(massagedData + path).hexdigest()
                     if self.path_nodes[path].has_key(massagedhash):
                         possible_vers = self.path_nodes[path][massagedhash]
                         self.logger.logFileHit(path, possible_vers, "", None, False) #TODO: log massager use
                         return possible_vers
             
             #massagers turned up nothing, maybe it's a custom 404 page
             if wafu.compare_to_error_page(self.error_page_fingerprint, data):
                 self.logger.logFileHit(path, None, None, 'Detected Custom 404', True)
                 return None
             #give up and throw KeyError afterall
             possible_vers = self.path_nodes[path][hash]
             
     except IOError, e:
         if hasattr(e, 'reason'):
             self.logger.logFileHit(path, None, None, 
                 "Failed to reach a server: %s" % e.reason, True)
             self._host_down_errors += 1
         elif hasattr(e, 'code'):
             self.logger.logFileHit(path, None, None, 
                 'Error code: %s (%s)' % (e.code, BaseHTTPServer.BaseHTTPRequestHandler.responses[e.code][0]), 
                 True)