class YuLinkStats(object): """ Class to represent the link specific stats """ def __init__(self, shorthash): self._db = YuDatabase() if shorthash is not None and self._db is not None: link_details = self._db.get_link_details(shorthash) if link_details: if link_details[5]: self.creation_time = '%s (UTC)' % (link_details[5]) else: self.creation_time = 'Unknown' self.link_address = link_details[3] self.first_redirect = self._db.get_date_of_first_entry( 'hashredirect', shorthash)[0] self.last_redirect = self._db.get_date_of_last_entry( 'hashredirect', shorthash)[0] self.number_of_redirects = self._db.get_statistics_for_hash( shorthash) return self.link_address = None self.creation_time = None self.first_redirect = None self.last_redirect = None self.number_of_redirects = None
def get_connection_pool(self): """ Return the status of the SQLAlchemy connection pool | **return** status (str) """ connection_pool = YuDatabase.get_connection_pool() return connection_pool.status() if connection_pool else None
def __init__(self): self.create_time_stamp = None self.links_today = None self.links_this_week = None self.links_this_month = None self.links_this_year = None self.links_all = None self.redirect_today = None self.redirect_this_week = None self.redirect_this_month = None self.redirect_this_year = None self.redirect_per_week = None self.redirect_all = None self.date_of_first_redirect = None self.date_of_first_link = None self._db = YuDatabase() self._update()
class YuLinkStats(object): """ Class to represent the link specific stats """ def __init__(self, shorthash): self._db = YuDatabase() if shorthash is not None and self._db is not None: link_details = self._db.get_link_details(shorthash) if link_details: if link_details[5]: self.creation_time = '%s (UTC)' % (link_details[5]) else: self.creation_time = 'Unknown' self.link_address = link_details[3] self.first_redirect = self._db.get_date_of_first_entry('hashredirect', shorthash)[0] self.last_redirect = self._db.get_date_of_last_entry('hashredirect', shorthash)[0] self.number_of_redirects = self._db.get_statistics_for_hash(shorthash) return self.link_address = None self.creation_time = None self.first_redirect = None self.last_redirect = None self.number_of_redirects = None
def __init__(self, request, client_address, server): self._db = YuDatabase() self._logger = get_logger() self._header_only = False BaseHTTPRequestHandler.__init__(self, request, client_address, server)
class YuRequestHandler(BaseHTTPRequestHandler): """ Custom request handler to process HEAD, GET and POST requests """ server_version = '%s/%s' % (SERVER_NAME, SERVER_VERSION) #---------------------------------------------------------------------- def __init__(self, request, client_address, server): self._db = YuDatabase() self._logger = get_logger() self._header_only = False BaseHTTPRequestHandler.__init__(self, request, client_address, server) #---------------------------------------------------------------------- def __del__(self): self._db.close() #---------------------------------------------------------------------- def _get_config_value(self, section, key): """ Convenience function to retrieve config settings | **param** section (str) | **param** key (str) | **return** value (str) """ return config.get(section, key) #---------------------------------------------------------------------- def _get_config_template(self, key): """ Convenience function to retrieve a template filename from the config | **param** key (str) | **return** value (str) """ tmp_path = self._get_config_value('templates', 'path') + key return tmp_path #---------------------------------------------------------------------- def address_string(self): """ Return the client address formatted for logging. Only lookup the hostname if really requested. | **return** hostname (str) """ if self.server.log_ip_activated: host = self.client_address[0] else: host = '127.0.0.1' if self.server.resolve_clients: return socket.getfqdn(host) else: return host #---------------------------------------------------------------------- def log_request(self, code='-', size='-'): """ Overwrite the default log_request() method to make it a no-op. We call the original method ourselves to pass also the response size. """ pass #---------------------------------------------------------------------- def send_response(self, code, message=None, size='-'): """ Send the response header and log the response code. Also send two standard headers with the server software version and the current date. | **param** code (int) | **param** message (str) | **param** size (str) """ BaseHTTPRequestHandler.send_response(self, code, message) BaseHTTPRequestHandler.log_request(self, code, size) #---------------------------------------------------------------------- def log_message(self, msg_format, *args): """ Overwrite the default log_message() method which prints for some reason to stderr which we don't want. Instead, we use a logger. | **param** msg_format (str) | **return** args (seq of mixed) """ try: useragent = self.headers['User-Agent'] except KeyError: useragent = '-' try: referrer = self.headers['Referer'] except KeyError: referrer = '-' values = dict(client=self.address_string(), identity='-', user='******', timestr=time.strftime('%d/%a/%Y:%H:%M:%S %z'), request=msg_format % args, referrer='"%s"' % referrer, useragent='"%s"' % useragent) msg_format = '%(client)s %(identity)s %(user)s [%(timestr)s] %(request)s %(referrer)s %(useragent)s' access_logger = get_access_logger() access_logger.info(msg_format % values) #---------------------------------------------------------------------- def _send_head(self, text, code): """ Send common headers | **param** text (str) | **param** code (int) """ size = len(text) self.send_response(code, None, size) # Trying to figure out what we are going to send out. # Maybe this could be improved a bit further but should do # it for now. extension_start = self.path.rfind('.') extension = self.path[extension_start:] try: self.send_header('Content-Type', CONTENT_TYPES[extension]) except KeyError: self.send_header('Content-Type', 'text/html') self.send_header("Content-Length", size) self.end_headers() #------------------------------------------------------------------- def _send_homepage(self, message=''): """ Sends the default startpage. |**param** message (str) Optional message that should appear on startpage """ template_filename = self._get_config_template('homepage') text = read_template(template_filename, title=SERVER_NAME, header=SERVER_NAME, msg=message) self._send_response(text, 200) #------------------------------------------------------------------- def _send_blocked_page(self, reason): """ Send a block page which tells the user that the URL has been blocked for some reason. | **param** reason Reason, why page has been blocked (str) """ template_filename = self._get_config_template('blocked') text = read_template(template_filename, title=SERVER_NAME, header=SERVER_NAME, comment=reason) self._send_response(text, 200) #------------------------------------------------------------------- def _send_return_page(self, shorthash): """ Send the result page for a new created short URL. | **param** shorthash - new shorthash for URL """ template_filename = self._get_config_template('return') if shorthash == '1337': messagetext = '<p>Hey, you are 1337!</p>' else: messagetext = '' text = read_template(template_filename, message=messagetext, title='%s - Short URL Result' % SERVER_NAME, header='new URL', path=shorthash, hostname=self.server.hostname) self._send_response(text, 200) #------------------------------------------------------------------- def _send_response(self, content, code=200): """ This function is to be intended to consolidate the sending responses to on function. TODO: Sync with self.send_response() function which is already talking with HTTPServer-interface. | **param** content - text of page (str) | **param** code - response code e.g. 404 (int) """ if content: self._send_head(content, code) if not self._header_only: try: self.wfile.write(content) except socket.error: # clients like to stop reading after they got a 404 pass else: self._send_internal_server_error() #------------------------------------------------------------------- def _send_301(self, new_url): """ Send HTTP status code 301 | **param** new_url (str) """ try: self.send_response(301) self.send_header('Location', new_url) self.send_header('Content-type', 'text/html') self.end_headers() except UnicodeEncodeError: self._send_internal_server_error() #---------------------------------------------------------------------- def _send_404(self): """ Send HTTP status code 404 """ template_filename = self._get_config_template('404') text = read_template(template_filename, title='%s - 404' % SERVER_NAME, header='404 — Page not found', URL="Nothing") self._send_response(text, 404) #---------------------------------------------------------------------- def _send_internal_server_error(self): """ Send HTTP status code 500 """ template_filename = self._get_config_template('500') text = read_template(template_filename, title='%s - Internal Error' % SERVER_NAME, header='Internal error') if not text: # fallback to hard-coded template text = TEMPLATE_500 self._send_head(text, 500) if not self._header_only: self.wfile.write(text) #---------------------------------------------------------------------- def _send_database_problem(self): """ Send HTTP status code 500 due to a database connection error | **param** header_only (bool) """ template_filename = self._get_config_template('databaseerror') text = read_template(template_filename, title='%s - Datebase error' % SERVER_NAME, header='Database error') if not text: self._send_internal_server_error() return self._send_head(text, 500) if not self._header_only: self.wfile.write(text) #---------------------------------------------------------------------- def _send_mail(self, subject, content, email): """ Send a mail | **param** subject (str) | **param** content (str) | **param** email (str) """ msg = MIMEText(content, 'plain', 'utf-8') msg['Subject'] = '%s' % (subject) msg['From'] = email msg['To'] = self._get_config_value('email', 'toemail') try: smtp_conn = SMTP('localhost') smtp_conn.sendmail(msg['From'], [msg['To']], msg.as_string()) smtp_conn.quit() except (socket.error, SMTPException), e: self._logger.error('Mail could not be sent (%s)' % e) return False return True
class YuStats(object): """ A class to represent some statistic data for yaturl """ def __init__(self): self.create_time_stamp = None self.links_today = None self.links_this_week = None self.links_this_month = None self.links_this_year = None self.links_all = None self.redirect_today = None self.redirect_this_week = None self.redirect_this_month = None self.redirect_this_year = None self.redirect_per_week = None self.redirect_all = None self.date_of_first_redirect = None self.date_of_first_link = None self._db = YuDatabase() self._update() #------------------------------------------------------------------- def _update(self): """ Updates the values of the stats object. """ self.create_time_stamp = time() self.links_today = self._get_links_from_db_today() self.links_this_week = self._get_links_from_db_this_week() self.links_this_month = self._get_links_from_db_this_month() self.links_this_year = self._get_links_from_db_this_year() self.links_all = self._get_links_from_db_all() self.redirect_today = self._get_redirects_today() self.redirect_this_week = self._get_redirects_this_week() self.redirect_this_month = self._get_redirects_this_month() self.redirect_this_year = self._get_redirects_this_year() # self.redirect_per_week = self._get_redirects_per_week() self.redirect_all = self._get_redirects_all() self.date_of_first_redirect = self._get_date_of_first_redirect() self.date_of_first_link = self._get_date_of_first_link_entry() #------------------------------------------------------------------- def _get_links_from_db_today(self): """ Collecting statistics about links added today from database. """ try: return self._db.get_statistics_for_general_links('today')[1] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_week(self): """ Collecting statistics about links added this week from database. """ try: return self._db.get_statistics_for_general_links('this_week')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_month(self): """ Collecting statistics about links added this month from database. """ try: return self._db.get_statistics_for_general_links('this_month')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_year(self): """ Collecting statistics about links added this year from database. """ try: return self._db.get_statistics_for_general_links('this_year')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_all(self): """ Collecting statistics about links added all time from database. """ try: return self._db.get_statistics_for_general_links('all')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_today(self): """ Collecting statistics about done redirects of today from database. """ try: return self._db.get_statistics_for_general_redirects('today')[1] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_week(self): """ Collecting statistics about done redirects of this week from database. """ try: return self._db.get_statistics_for_general_redirects('this_week')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_month(self): """ Collecting statistics about done redirects of this month from database. """ try: return self._db.get_statistics_for_general_redirects('this_month')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_year(self): """ Collecting statistics about done redirects of this year from database. """ try: return self._db.get_statistics_for_general_redirects('this_year')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_per_week(self): """ Collecting statistics about done redirects groupd by week and year from database. """ try: return self._db.get_statistics_for_general_redirects('per_week') except TypeError: return None #------------------------------------------------------------------- def _get_redirects_all(self): """ Collecting statistics about done redirects ever from database. """ try: return self._db.get_statistics_for_general_redirects('all')[0] except TypeError: return None #------------------------------------------------------------------- def _get_date_of_first_redirect(self): """ Get timestamp of first redirect logged from database. """ try: return self._db.get_date_of_first_entry('redirect')[0] except TypeError: return None #------------------------------------------------------------------- def _get_date_of_first_link_entry(self): """ Get timestamp of time of first inserted link from database. """ try: return self._db.get_date_of_first_entry('link')[0] except TypeError: return None #------------------------------------------------------------------- def update_stats(self): """ Public method to perform update on stats date """ self._update()
class YuStats(object): """ A class to represent some statistic data for yaturl """ def __init__(self): self.create_time_stamp = None self.links_today = None self.links_this_week = None self.links_this_month = None self.links_this_year = None self.links_all = None self.redirect_today = None self.redirect_this_week = None self.redirect_this_month = None self.redirect_this_year = None self.redirect_per_week = None self.redirect_all = None self.date_of_first_redirect = None self.date_of_first_link = None self._db = YuDatabase() self._update() #------------------------------------------------------------------- def _update(self): """ Updates the values of the stats object. """ self.create_time_stamp = time() self.links_today = self._get_links_from_db_today() self.links_this_week = self._get_links_from_db_this_week() self.links_this_month = self._get_links_from_db_this_month() self.links_this_year = self._get_links_from_db_this_year() self.links_all = self._get_links_from_db_all() self.redirect_today = self._get_redirects_today() self.redirect_this_week = self._get_redirects_this_week() self.redirect_this_month = self._get_redirects_this_month() self.redirect_this_year = self._get_redirects_this_year() # self.redirect_per_week = self._get_redirects_per_week() self.redirect_all = self._get_redirects_all() self.date_of_first_redirect = self._get_date_of_first_redirect() self.date_of_first_link = self._get_date_of_first_link_entry() #------------------------------------------------------------------- def _get_links_from_db_today(self): """ Collecting statistics about links added today from database. """ try: return self._db.get_statistics_for_general_links('today')[1] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_week(self): """ Collecting statistics about links added this week from database. """ try: return self._db.get_statistics_for_general_links('this_week')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_month(self): """ Collecting statistics about links added this month from database. """ try: return self._db.get_statistics_for_general_links('this_month')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_this_year(self): """ Collecting statistics about links added this year from database. """ try: return self._db.get_statistics_for_general_links('this_year')[0] except TypeError: return None #------------------------------------------------------------------- def _get_links_from_db_all(self): """ Collecting statistics about links added all time from database. """ try: return self._db.get_statistics_for_general_links('all')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_today(self): """ Collecting statistics about done redirects of today from database. """ try: return self._db.get_statistics_for_general_redirects('today')[1] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_week(self): """ Collecting statistics about done redirects of this week from database. """ try: return self._db.get_statistics_for_general_redirects( 'this_week')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_month(self): """ Collecting statistics about done redirects of this month from database. """ try: return self._db.get_statistics_for_general_redirects( 'this_month')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_this_year(self): """ Collecting statistics about done redirects of this year from database. """ try: return self._db.get_statistics_for_general_redirects( 'this_year')[0] except TypeError: return None #------------------------------------------------------------------- def _get_redirects_per_week(self): """ Collecting statistics about done redirects groupd by week and year from database. """ try: return self._db.get_statistics_for_general_redirects('per_week') except TypeError: return None #------------------------------------------------------------------- def _get_redirects_all(self): """ Collecting statistics about done redirects ever from database. """ try: return self._db.get_statistics_for_general_redirects('all')[0] except TypeError: return None #------------------------------------------------------------------- def _get_date_of_first_redirect(self): """ Get timestamp of first redirect logged from database. """ try: return self._db.get_date_of_first_entry('redirect')[0] except TypeError: return None #------------------------------------------------------------------- def _get_date_of_first_link_entry(self): """ Get timestamp of time of first inserted link from database. """ try: return self._db.get_date_of_first_entry('link')[0] except TypeError: return None #------------------------------------------------------------------- def update_stats(self): """ Public method to perform update on stats date """ self._update()
class YuRequestHandler(BaseHTTPRequestHandler): """ Custom request handler to process HEAD, GET and POST requests """ server_version = "%s/%s" % (SERVER_NAME, SERVER_VERSION) # ---------------------------------------------------------------------- def __init__(self, request, client_address, server): self._db = YuDatabase() self._logger = get_logger() self._header_only = False BaseHTTPRequestHandler.__init__(self, request, client_address, server) # ---------------------------------------------------------------------- def __del__(self): self._db.close() # ---------------------------------------------------------------------- def _get_config_value(self, section, key): """ Convenience function to retrieve config settings | **param** section (str) | **param** key (str) | **return** value (str) """ return config.get(section, key) # ---------------------------------------------------------------------- def _get_config_template(self, key): """ Convenience function to retrieve a template filename from the config | **param** key (str) | **return** value (str) """ tmp_path = self._get_config_value("templates", "path") + key return tmp_path # ---------------------------------------------------------------------- def address_string(self): """ Return the client address formatted for logging. Only lookup the hostname if really requested. | **return** hostname (str) """ if self.server.log_ip_activated: host = self.client_address[0] else: host = "127.0.0.1" if self.server.resolve_clients: return socket.getfqdn(host) else: return host # ---------------------------------------------------------------------- def log_request(self, code="-", size="-"): """ Overwrite the default log_request() method to make it a no-op. We call the original method ourselves to pass also the response size. """ pass # ---------------------------------------------------------------------- def send_response(self, code, message=None, size="-"): """ Send the response header and log the response code. Also send two standard headers with the server software version and the current date. | **param** code (int) | **param** message (str) | **param** size (str) """ BaseHTTPRequestHandler.send_response(self, code, message) BaseHTTPRequestHandler.log_request(self, code, size) # ---------------------------------------------------------------------- def log_message(self, msg_format, *args): """ Overwrite the default log_message() method which prints for some reason to stderr which we don't want. Instead, we use a logger. | **param** msg_format (str) | **return** args (seq of mixed) """ try: useragent = self.headers["User-Agent"] except KeyError: useragent = "-" try: referrer = self.headers["Referer"] except KeyError: referrer = "-" values = dict( client=self.address_string(), identity="-", user="******", timestr=time.strftime("%d/%a/%Y:%H:%M:%S %z"), request=msg_format % args, referrer='"%s"' % referrer, useragent='"%s"' % useragent, ) msg_format = "%(client)s %(identity)s %(user)s [%(timestr)s] %(request)s %(referrer)s %(useragent)s" access_logger = get_access_logger() access_logger.info(msg_format % values) # ---------------------------------------------------------------------- def _send_head(self, text, code): """ Send common headers | **param** text (str) | **param** code (int) """ size = len(text) self.send_response(code, None, size) # Trying to figure out what we are going to send out. # Maybe this could be improved a bit further but should do # it for now. extension_start = self.path.rfind(".") extension = self.path[extension_start:] try: self.send_header("Content-Type", CONTENT_TYPES[extension]) except KeyError: self.send_header("Content-Type", "text/html") self.send_header("Content-Length", size) self.end_headers() # ------------------------------------------------------------------- def _send_homepage(self, message=""): """ Sends the default startpage. |**param** message (str) Optional message that should appear on startpage """ template_filename = self._get_config_template("homepage") text = read_template(template_filename, title=SERVER_NAME, header=SERVER_NAME, msg=message) self._send_response(text, 200) # ------------------------------------------------------------------- def _send_blocked_page(self, reason): """ Send a block page which tells the user that the URL has been blocked for some reason. | **param** reason Reason, why page has been blocked (str) """ template_filename = self._get_config_template("blocked") text = read_template(template_filename, title=SERVER_NAME, header=SERVER_NAME, comment=reason) self._send_response(text, 200) # ------------------------------------------------------------------- def _send_return_page(self, shorthash): """ Send the result page for a new created short URL. | **param** shorthash - new shorthash for URL """ template_filename = self._get_config_template("return") if shorthash == "1337": messagetext = "<p>Hey, you are 1337!</p>" else: messagetext = "" text = read_template( template_filename, message=messagetext, title="%s - Short URL Result" % SERVER_NAME, header="new URL", path=shorthash, hostname=self.server.hostname, ) self._send_response(text, 200) # ------------------------------------------------------------------- def _send_response(self, content, code=200): """ This function is to be intended to consolidate the sending responses to on function. TODO: Sync with self.send_response() function which is already talking with HTTPServer-interface. | **param** content - text of page (str) | **param** code - response code e.g. 404 (int) """ if content: self._send_head(content, code) if not self._header_only: try: self.wfile.write(content) except socket.error: # clients like to stop reading after they got a 404 pass else: self._send_internal_server_error() # ------------------------------------------------------------------- def _send_301(self, new_url): """ Send HTTP status code 301 | **param** new_url (str) """ try: self.send_response(301) self.send_header("Location", new_url) self.send_header("Content-type", "text/html") self.end_headers() except UnicodeEncodeError: self._send_internal_server_error() # ---------------------------------------------------------------------- def _send_404(self): """ Send HTTP status code 404 """ template_filename = self._get_config_template("404") text = read_template( template_filename, title="%s - 404" % SERVER_NAME, header="404 — Page not found", URL="Nothing" ) self._send_response(text, 404) # ---------------------------------------------------------------------- def _send_internal_server_error(self): """ Send HTTP status code 500 """ template_filename = self._get_config_template("500") text = read_template(template_filename, title="%s - Internal Error" % SERVER_NAME, header="Internal error") if not text: # fallback to hard-coded template text = TEMPLATE_500 self._send_head(text, 500) if not self._header_only: self.wfile.write(text) # ---------------------------------------------------------------------- def _send_database_problem(self): """ Send HTTP status code 500 due to a database connection error | **param** header_only (bool) """ template_filename = self._get_config_template("databaseerror") text = read_template(template_filename, title="%s - Datebase error" % SERVER_NAME, header="Database error") if not text: self._send_internal_server_error() return self._send_head(text, 500) if not self._header_only: self.wfile.write(text) # ---------------------------------------------------------------------- def _send_mail(self, subject, content, email): """ Send a mail | **param** subject (str) | **param** content (str) | **param** email (str) """ msg = MIMEText(content, "plain", "utf-8") msg["Subject"] = "%s" % (subject) msg["From"] = email msg["To"] = self._get_config_value("email", "toemail") try: smtp_conn = SMTP("localhost") smtp_conn.sendmail(msg["From"], [msg["To"]], msg.as_string()) smtp_conn.quit() except (socket.error, SMTPException), e: self._logger.error("Mail could not be sent (%s)" % e) return False return True