| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 # coding: utf-8 | 
|  | 2 | 
|  | 3 # This file is part of the Adblock Plus web scripts, | 
|  | 4 # Copyright (C) 2006-2015 Eyeo GmbH | 
|  | 5 # | 
|  | 6 # Adblock Plus is free software: you can redistribute it and/or modify | 
|  | 7 # it under the terms of the GNU General Public License version 3 as | 
|  | 8 # published by the Free Software Foundation. | 
|  | 9 # | 
|  | 10 # Adblock Plus is distributed in the hope that it will be useful, | 
|  | 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 13 # GNU General Public License for more details. | 
|  | 14 # | 
|  | 15 # You should have received a copy of the GNU General Public License | 
|  | 16 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 17 | 
|  | 18 import json | 
|  | 19 import os | 
|  | 20 import tempfile | 
|  | 21 import time | 
|  | 22 import traceback | 
|  | 23 from datetime import datetime | 
|  | 24 from errno import EEXIST | 
|  | 25 | 
|  | 26 import MySQLdb | 
|  | 27 | 
|  | 28 from sitescripts.web import url_handler | 
|  | 29 from sitescripts.utils import get_config, setupStderr | 
|  | 30 from sitescripts.filterhits import db, geometrical_mean | 
|  | 31 from sitescripts.filterhits.web import common | 
|  | 32 | 
|  | 33 def log_filterhits(data, basepath, query_string): | 
|  | 34   """ | 
|  | 35   This logs the provided filterhits data as JSON to a file named after | 
|  | 36   the current timestamp in a directory named after the current date. | 
|  | 37   """ | 
|  | 38   now = time.gmtime() | 
|  | 39 | 
|  | 40   dir_name = time.strftime("%Y-%m-%d", now) | 
|  | 41   path = os.path.join(basepath, dir_name) | 
|  | 42   try: | 
|  | 43     os.makedirs(path) | 
|  | 44   except OSError as e: | 
|  | 45     if e.errno != EEXIST: | 
|  | 46       raise | 
|  | 47 | 
|  | 48   with tempfile.NamedTemporaryFile( | 
|  | 49     prefix = str(int(time.mktime(now))) + "-", | 
|  | 50     suffix = ".log", | 
|  | 51     dir = path, | 
|  | 52     delete = False | 
|  | 53   ) as f: | 
|  | 54     print >> f, "[%s] %s" % (time.strftime("%d/%b/%Y:%H:%M:%S", now), query_stri
     ng) | 
|  | 55     json.dump(data, f) | 
|  | 56     return f.name | 
|  | 57 | 
|  | 58 @url_handler("/submit") | 
|  | 59 def submit(environ, start_response): | 
|  | 60   setupStderr(environ["wsgi.errors"]) | 
|  | 61   config = get_config() | 
|  | 62 | 
|  | 63   # Check that this is a POST request | 
|  | 64   if environ["REQUEST_METHOD"] != "POST": | 
|  | 65     return common.show_error("Unsupported request method", start_response) | 
|  | 66 | 
|  | 67   # Parse the submitted JSON | 
|  | 68   try: | 
|  | 69     data = json.loads(environ["wsgi.input"].read(int(environ["CONTENT_LENGTH"]))
     ) | 
|  | 70   except (KeyError, IOError, ValueError): | 
|  | 71     return common.show_error("Error while parsing JSON data.", start_response) | 
|  | 72 | 
|  | 73   # Make sure the submitted data was contained within an object at least | 
|  | 74   if not isinstance(data, dict): | 
|  | 75     return common.show_error("Error, data must be contained within an object.", 
     start_response) | 
|  | 76 | 
|  | 77   # Log the data to a file | 
|  | 78   log_dir = config.get("filterhitstats", "log_dir") | 
|  | 79   try: | 
|  | 80     log_file = log_filterhits(data, log_dir, environ.get("QUERY_STRING", "")) | 
|  | 81   except (OSError, IOError): | 
|  | 82     traceback.print_exc() | 
|  | 83     return common.show_error("Failed to write data to log file!", start_response
     , | 
|  | 84                              "500 Logging error") | 
|  | 85 | 
|  | 86   # Update the geometrical_mean aggregations in the database | 
|  | 87   interval = config.get("filterhitstats", "interval") | 
|  | 88   try: | 
|  | 89     db_connection = db.connect() | 
|  | 90     try: | 
|  | 91       db.write(db_connection, geometrical_mean.update(interval, data)) | 
|  | 92     finally: | 
|  | 93       db_connection.close() | 
|  | 94   except: | 
|  | 95     # Updating the aggregations in the database failed for whatever reason, | 
|  | 96     # log the details but continue to return 204 to the client to avoid the | 
|  | 97     # re-transmission of data. | 
|  | 98     processing_error_log = os.path.join(config.get("filterhitstats", "log_dir"), | 
|  | 99                                         "processing-errors.log") | 
|  | 100     with open(processing_error_log, "a+") as f: | 
|  | 101       message = "Problem processing data file %s:\n%s" % ( | 
|  | 102         log_file, traceback.format_exc() | 
|  | 103       ) | 
|  | 104       print >> f, "[%s] %s" % (datetime.now().strftime("%d/%b/%Y:%H:%M:%S %z"), 
     message) | 
|  | 105 | 
|  | 106   # Send back a 204 No Content | 
|  | 107   start_response("204 No Content", []) | 
|  | 108   return [] | 
| OLD | NEW | 
|---|