def send(self): """ Sends a message. :since: v1.0.0 """ if (self._log_handler is not None): self._log_handler.debug("#echo(__FILEPATH__)# -{0!r}.send()- (#echo(__LINE__)#)", self, context = "pas_email") if (self.message is None): raise IOException("No message defined to be send") if (not self.message.is_recipient_set): raise ValueException("No recipients defined for e-mail") if (not self.message.is_subject_set): raise IOException("No subject defined for e-mail") bcc_list = self.message.bcc cc_list = self.message.cc to_list = self.message.to rcpt_list = to_list if (len(bcc_list) > 0): rcpt_list = Client._filter_unique_list(rcpt_list, bcc_list) if (len(cc_list) > 0): rcpt_list = Client._filter_unique_list(rcpt_list, cc_list) is_auth_possible = False smtp_user = None smtp_password = None if (Settings.is_defined("pas_smtp_client_user") and Settings.is_defined("pas_smtp_client_password")): is_auth_possible = True smtp_user = Settings.get("pas_smtp_client_user") smtp_password = Settings.get("pas_smtp_client_password") # smtp_connection = None try: smtp_connection = (self._get_lmtp_connection() if (Settings.is_defined("pas_smtp_client_lmtp_host") or Settings.is_defined("pas_smtp_client_lmtp_path_name") ) else self._get_smtp_connection() ) if (is_auth_possible): smtp_connection.login(smtp_user, smtp_password) if (not self.message.is_sender_set): self.message.sender = (Settings.get("pas_email_sender_public") if (Settings.is_defined("pas_email_sender_public")) else Settings.get("pas_email_address_public") ) # sender = self.message.sender smtp_connection.sendmail(sender, rcpt_list, self.message.as_string()) self.message = None finally: try: if (smtp_connection is not None): smtp_connection.quit() except SMTPServerDisconnected: pass
def is_available(): """ True if a persistent tasks executing scheduler is available. :return: (bool) True if available :since: v0.2.00 """ if (not Settings.is_defined("pas_tasks_daemon_listener_address")): Settings.read_file("{0}/settings/pas_tasks_daemon.json".format(Settings.get("path_data"))) # return Settings.is_defined("pas_tasks_daemon_listener_address")
def execute_logout(self): """ Action for "logout" :since: v0.2.00 """ source_iline = InputFilter.filter_control_chars(self.request.get_dsd("source", "")).strip() target_iline = InputFilter.filter_control_chars(self.request.get_dsd("target", "")).strip() if (target_iline == ""): if (Settings.is_defined("pas_http_user_logout_default_target_lang_{0}".format(self.request.get_lang()))): target_iline = Settings.get("pas_http_user_logout_default_target_lang_{0}".format(self.request.get_lang())) elif (Settings.is_defined("pas_http_user_logout_default_target")): target_iline = Settings.get("pas_http_user_logout_default_target") else: target_iline = source_iline # L10n.init("pas_http_user") if (self.response.is_supported("html_css_files")): self.response.add_theme_css_file("mini_default_sprite.min.css") Link.set_store("servicemenu", Link.TYPE_RELATIVE_URL, L10n.get("core_back"), { "__query__": re.sub("\\_\\_\\w+\\_\\_", "", source_iline) }, icon = "mini-default-back", priority = 7 ) if (not self.request.is_supported("session")): raise TranslatableError("core_unknown_error", 500) session = Session.load(session_create = False) if (session is not None): session.delete() self.request.set_session(None) # Link.clear_store("servicemenu") target_iline = re.sub("\\_\\_\\w+\\_\\_", "", target_iline) redirect_request = PredefinedHttpRequest() redirect_request.set_module("output") redirect_request.set_service("http") redirect_request.set_action("done") redirect_request.set_parameter_chained("title", L10n.get("pas_http_user_logout")) redirect_request.set_parameter_chained("message", L10n.get("pas_http_user_done_logout")) redirect_request.set_parameter_chained("target_iline", target_iline) self.request.redirect(redirect_request)
def get_user_agent_identifiers(user_agent): """ Returns a UPnP client based on the given HTTP or SSDP user agent value. :param user_agent: HTTP or SSDP user agent value :return: (object) UPnP client; None on error :since: v0.2.00 """ _return = "" if (not Settings.is_defined("pas_upnp_client_replacement_list")): Settings.read_file("{0}/settings/pas_upnp.json".format(Settings.get("path_data"))) replacement_list = Settings.get("pas_upnp_client_replacement_list", None) if (type(replacement_list) is dict): replacement_list_keys = sorted(replacement_list.keys(), reverse = True) for upnp_value in replacement_list_keys: user_agent = user_agent.replace(upnp_value, replacement_list[upnp_value]) # for re_result in re.finditer("([\\d\\w\\.]+/([0-9\\.]+(\\W|$))+)", user_agent): if (_return != ""): _return += "_" _return += re.sub("\\W+", "_", re_result.group(1)).strip("_") # if (_return == ""): _return = re.sub("\\W+", "_", user_agent).lower() else: _return = _return.lower() return _return
def __init__(self, scheme = None, host = None, port = None, path = None): """ Constructor __init__(Link) :param scheme: URL scheme :param host: URL host :param port: URL port :param path: URL path :since: v0.2.00 """ self.host = host """ Override for the URL host """ self.path = path """ Override for the URL path """ self.port = port """ Override for the URL port """ self.scheme = scheme """ Override for the URL scheme """ if (not Settings.is_defined("pas_http_site_preferred_url_base")): Settings.read_file("{0}/settings/pas_http.json".format(Settings.get("path_data")))
def _is_file_access_allowed(self, file_path_name): """ Checks if the file access is allowed for streaming. :param file_path_name: Path to the requested file :return: (bool) True if allowed :since: v0.2.00 """ _return = False if Settings.is_defined("pas_streamer_file_basedir_list"): basedir_list = Settings.get("pas_streamer_file_basedir_list") if type(basedir_list) is list: file_absolute_path_name = path.abspath(file_path_name) for basedir in basedir_list: if file_absolute_path_name.startswith(basedir): _return = True break # # if (not _return) and self.log_handler is not None: self.log_handler.warning( "streamer.File denied access to {0}", file_path_name, context="pas_streamer" ) # else: _return = True return _return
def _ensure_settings(): """ Check and read settings if needed. :since: v1.0.0 """ if (not Connection._settings_initialized): with Connection._serialized_lock: # Thread safety if (not Connection._settings_initialized): Settings.read_file("{0}/settings/pas_database.json".format(Settings.get("path_data")), True) if (not Settings.is_defined("pas_database_url")): raise ValueException("Minimum database configuration missing") url = Settings.get("pas_database_url").replace("__path_base__", path.abspath(Settings.get("path_base"))) if (not Settings.is_defined("pas_database_table_prefix")): Settings.set("pas_database_table_prefix", "pas") Connection._serialized = (not Settings.get("pas_database_threaded", True)) if (Connection._serialized): LogLine.debug("pas.database access is serialized", context = "pas_database") Connection._serialized_lock.timeout = Settings.get("pas_database_lock_timeout", 30) # url_elements = urlsplit(url) Settings.set("x_pas_database_backend_name", url_elements.scheme.split("+")[0]) if (url_elements.username is None and url_elements.password is None and Settings.is_defined("pas_database_user") and Settings.is_defined("pas_database_password") ): url = "{0}://{1}:{2}@{3}{4}".format(url_elements.scheme, Settings.get("pas_database_user"), Settings.get("pas_database_password"), url_elements.hostname, url_elements.path ) if (url_elements.query != ""): url += "?{0}".format(url_elements.query) if (url_elements.fragment != ""): url += "#{0}".format(url_elements.fragment) # Settings.set("pas_database_sqlalchemy_url", url) Connection._settings_initialized = True
def _get_lmtp_connection(self): """ Returns an established LMTP connection. :return: (object) LMTP connection :since: v1.0.0 """ smtp_options = { } if (Settings.is_defined("pas_smtp_client_sender_hostname")): smtp_options['local_hostname'] = Settings.get("pas_smtp_client_sender_hostname") _return = (LMTP(Settings.get("pas_smtp_client_lmtp_host"), int(Settings.get("pas_smtp_client_lmtp_port", 24))) if (Settings.is_defined("pas_smtp_client_lmtp_host")) else LMTP(Settings.get("pas_smtp_client_lmtp_path_name")) ) return _return
def execute_index(self): """ Action for "index" :since: v0.2.00 """ if (self.request.is_dsd_set("cdid")): self.execute_view() elif (self.request.is_dsd_set("ccid") or Settings.is_defined("pas_http_contentor_category_default")): self.execute_list()
def execute_index(self): # """ Action for "index" :since: v0.1.00 """ if (self.request.is_dsd_set("dtid")): self.execute_topic() elif (self.request.is_dsd_set("dpid")): self.execute_post() elif (self.request.is_dsd_set("dlid") or Settings.is_defined("pas_http_discuss_list_default")): self.execute_list()
def _on_run(self, args): """ Callback for execution. :param args: Parsed command line arguments :since: v0.2.00 """ # pylint: disable=attribute-defined-outside-init Settings.read_file("{0}/settings/pas_global.json".format(Settings.get("path_data"))) Settings.read_file("{0}/settings/pas_core.json".format(Settings.get("path_data")), True) Settings.read_file("{0}/settings/pas_tasks_daemon.json".format(Settings.get("path_data")), True) if (args.additional_settings is not None): Settings.read_file(args.additional_settings, True) if (not Settings.is_defined("pas_tasks_daemon_listener_address")): raise IOException("No listener address defined for the TasksDaemon") if (args.reload_plugins): client = BusClient("pas_tasks_daemon") client.request("dNG.pas.Plugins.reload") elif (args.stop): client = BusClient("pas_tasks_daemon") pid = client.request("dNG.pas.Status.getOSPid") client.request("dNG.pas.Status.stop") self._wait_for_os_pid(pid) else: self.cache_instance = NamedLoader.get_singleton("dNG.data.cache.Content", False) if (self.cache_instance is not None): Settings.set_cache_instance(self.cache_instance) self.log_handler = NamedLoader.get_singleton("dNG.data.logging.LogHandler", False) if (self.log_handler is not None): Hook.set_log_handler(self.log_handler) NamedLoader.set_log_handler(self.log_handler) # Hook.load("tasks") Hook.register("dNG.pas.Status.getOSPid", self.get_os_pid) Hook.register("dNG.pas.Status.getTimeStarted", self.get_time_started) Hook.register("dNG.pas.Status.getUptime", self.get_uptime) Hook.register("dNG.pas.Status.stop", self.stop) self.server = BusServer("pas_tasks_daemon") self._set_time_started(time()) if (self.log_handler is not None): self.log_handler.info("TasksDaemon starts listening", context = "pas_tasks") Hook.call("dNG.pas.Status.onStartup") Hook.call("dNG.pas.tasks.Daemon.onStartup") self.set_mainloop(self.server.run)
def _get_smtp_connection(self): """ Returns an established SMTP connection. :return: (object) SMTP connection :since: v1.0.0 """ smtp_host = Settings.get("pas_smtp_client_host", "localhost") smtp_port = int(Settings.get("pas_smtp_client_port", 25)) smtp_options = { } is_tls_connection = Settings.get("pas_smtp_client_tls", False) ssl_cert_file_path_name = "" ssl_key_file_path_name = "" if (Settings.is_defined("pas_smtp_client_ssl_cert_file") and Settings.is_defined("pas_smtp_client_ssl_key_file")): ssl_cert_file_path_name = Settings.get("pas_smtp_client_ssl_cert_file") ssl_key_file_path_name = Settings.get("pas_smtp_client_ssl_key_file") if (ssl_cert_file_path_name + ssl_key_file_path_name == ""): raise IOException("TLS requested for incomplete configuration") # if (ssl_cert_file_path_name + ssl_key_file_path_name != "" and (not is_tls_connection)): smtp_options['certfile'] = ssl_cert_file_path_name smtp_options['keyfile'] = ssl_key_file_path_name # if (Settings.is_defined("pas_smtp_client_sender_hostname")): smtp_options['local_hostname'] = Settings.get("pas_smtp_client_sender_hostname") _return = (SMTP_SSL(smtp_host, smtp_port, timeout = self.timeout, **smtp_options) if ("keyfile" in smtp_options) else SMTP(smtp_host, smtp_port, timeout = self.timeout, **smtp_options) ) if (is_tls_connection): _return.starttls(ssl_key_file_path_name, ssl_cert_file_path_name) return _return
def get_preferred(context = None): """ Returns a "Link" instance based on the defined preferred URL. :param context: Context for the preferred link :return: (object) Link instance :since: v0.2.00 """ if (not Settings.is_defined("pas_http_site_preferred_url_base")): Settings.read_file("{0}/settings/pas_http.json".format(Settings.get("path_data"))) url = None if (context is not None): url = Settings.get("pas_http_site_preferred_url_base_{0}".format(re.sub("\\W+", "_", context))) if (url is None): url = Settings.get("pas_http_site_preferred_url_base") if (url is None): raise ValueException("Preferred URL base setting is not defined") url_elements = urlsplit(url) return Link(url_elements.scheme, url_elements.hostname, url_elements.port, url_elements.path)
def get_executing_class(is_not_implemented_class_aware = False): """ Returns the persistent tasks implementation class responsible for scheduling and execution based on the configuration set. :param is_not_implemented_class_aware: True to return "dNG.runtime.NotImplementedClass" instead of None :return: (object) Tasks implementation class; None if not available :since: v0.2.00 """ if (not Settings.is_defined("pas_tasks_daemon_listener_address")): Settings.read_file("{0}/settings/pas_tasks_daemon.json".format(Settings.get("path_data"))) # implementation_class_name = Settings.get("pas_tasks_persistent_implementation", "Database") _return = NamedLoader.get_class("dNG.data.tasks.{0}".format(implementation_class_name)) if (_return is None and is_not_implemented_class_aware): _return = NotImplementedClass return _return
def __init__(self): """ Constructor __init__(ControlPoint) :since: v0.2.00 """ AbstractTimed.__init__(self) self.bootid = 0 """ UPnP bootId value (bootid.upnp.org); nextbootid.upnp.org += 1 """ self.configid = 0 """ UPnP configId value (configid.upnp.org) """ self.devices = { } """ List of devices with its services """ self.gena = None """ UPnP GENA manager """ self.http_host = None """ HTTP Accept-Language value """ self.http_language = (L10n.get("lang_rfc_region") if (L10n.is_defined("lang_rfc_region")) else None) """ HTTP Accept-Language value """ self.http_port = None """ HTTP Accept-Language value """ self.listener_ipv4 = None """ Unicast IPv4 listener """ self.listener_port = int(Settings.get("pas_upnp_device_port", 1900)) """ Unicast port in the range 49152-65535 (searchport.upnp.org) """ self.listeners_multicast = { } """ Multicast listeners """ self.listeners_multicast_ipv4 = 0 """ Number of IPv4 multicast listeners """ self.listeners_multicast_ipv6 = 0 """ Number of IPv6 multicast listeners """ self.managed_devices = { } """ List of managed devices """ self.rootdevices = [ ] """ List of UPnP root devices """ self.tasks = [ ] """ List of tasks (e.g. timed out services) to run """ self.upnp_desc = { } """ Received UPnP descriptions """ self.upnp_desc_unread = { } """ Unread UPnP description URLs """ self.usns = { } """ List of devices with its services """ Settings.read_file("{0}/settings/pas_upnp.json".format(Settings.get("path_data"))) self.log_handler = NamedLoader.get_singleton("dNG.data.logging.LogHandler", False) if (self.http_language is None): system_language = getlocale()[0] http_language = (Settings.get("core_lang", "en_US") if (system_language is None or system_language == "c") else system_language ) http_language = http_language.replace("_", "") http_language = re.sub("\\W", "", http_language) else: http_language = self.http_language.replace("_", "") if (Settings.is_defined("core_lang_{0}".format(http_language))): http_language = Settings.get("core_lang_{0}".format(http_language)) elif (Settings.is_defined("core_lang_{0}".format(http_language[:2]))): http_language = Settings.get("core_lang_{0}".format(http_language[:2])) lang_iso_domain = http_language[:2] if (len(http_language) > 2): self.http_language = "{0}-{1}".format(http_language[:2], http_language[2:]) else: self.http_language = http_language self.http_language += ", {0}".format(lang_iso_domain) if (lang_iso_domain != "en"): self.http_language += ", en-US, en"
def start(self, params = None, last_return = None): """ Starts all UPnP listeners and announces itself. :param params: Parameter specified :param last_return: The return value from the last hook called. :since: v0.2.00 """ # pylint: disable=broad-except if (self.log_handler is not None): self.log_handler.debug("#echo(__FILEPATH__)# -{0!r}.start()- (#echo(__LINE__)#)", self, context = "pas_upnp") # Set bootid and configid to a value between 0 and 16777215 startupid = int(time()) % 16777216 self.bootid = startupid self.configid = startupid preferred_host = Settings.get("pas_upnp_server_preferred_host") preferred_port = Settings.get("pas_upnp_server_preferred_port") upnp_http_host = (Hook.call("dNG.pas.http.Server.getHost") if (preferred_host is None) else preferred_host ) if (Settings.get("pas_upnp_server_bind_host_to_ipv4", False)): try: upnp_http_host = socket.gethostbyname(upnp_http_host) except socket.error as handled_exception: if (self.log_handler is not None): self.log_handler.debug(handled_exception) # # self.http_host = upnp_http_host self.http_port = (Hook.call("dNG.pas.http.Server.getPort") if (preferred_port is None) else preferred_port ) if (self.http_host is None or self.http_port is None): raise ValueException("HTTP server must provide the hostname and port for the UPnP ControlPoint") if (not Settings.is_defined("pas_http_site_preferred_url_base_upnp")): Settings.set("pas_http_site_preferred_url_base_upnp", "http://{0}:{1:d}".format(self.http_host, self.http_port) ) # Hook.load("upnp") is_ipv6_supported = getattr(socket, "has_ipv6", False) with self.lock: self.bootid += 1 ip_addresses = Settings.get("pas_upnp_bind_network_addresses", [ ]) if (type(ip_addresses) is not list): ip_addresses = [ ] listener_addresses = 0 if (len(ip_addresses) < 1 and Settings.get("pas_upnp_bind_network_addresses_detect", True)): ip_address_list = socket.getaddrinfo(None, self.listener_port, socket.AF_UNSPEC, 0, socket.IPPROTO_UDP) ip_address_list += socket.getaddrinfo(self.http_host, self.http_port, socket.AF_UNSPEC, 0, socket.IPPROTO_TCP) for ip_address_data in ip_address_list: if ((ip_address_data[0] == socket.AF_INET or (is_ipv6_supported and ip_address_data[0] == socket.AF_INET6) ) and ip_address_data[4][0] not in ip_addresses ): ip_addresses.append(ip_address_data[4][0]) # if (self.log_handler is not None and len(ip_addresses) < 1): self.log_handler.warning("pas.upnp.ControlPoint was unable to find available networks", context = "pas_upnp") # for ip_address in ip_addresses: if (ip_address[:4] != "127." and ip_address != "::1"): # Accept user defined or discovered list of IP addresses to listen on to fail on startup try: self._activate_multicast_listener(ip_address) listener_addresses += 1 except Exception: pass # # if (listener_addresses < 1): if (self.log_handler is not None): self.log_handler.debug("{0!r} will bind to all interfaces", self, context = "pas_upnp") self._activate_multicast_listener("0.0.0.0") if (is_ipv6_supported): self._activate_multicast_listener("::0") # # AbstractTimed.start(self) Hook.call("dNG.pas.upnp.ControlPoint.onStartup") if (self.log_handler is not None): self.log_handler.info("pas.upnp.ControlPoint starts with bootId '{0:d}' and configId '{1:d}'", self.bootid, self.configid, context = "pas_upnp") return last_return
def execute_login_alternatives_list(self): """ Action for "login-alternatives-list" :since: v0.2.00 """ source_iline = InputFilter.filter_control_chars(self.request.get_dsd("source", "")).strip() target_iline = InputFilter.filter_control_chars(self.request.get_dsd("target", "")).strip() source = source_iline if (source_iline == ""): source_iline = "m=user;s=status;a=login" target = target_iline if (target_iline == ""): if (Settings.is_defined("pas_http_user_login_default_target_lang_{0}".format(self.request.get_lang()))): target_iline = Settings.get("pas_http_user_login_default_target_lang_{0}".format(self.request.get_lang())) elif (Settings.is_defined("pas_http_user_login_default_target")): target_iline = Settings.get("pas_http_user_login_default_target") else: target_iline = source_iline # L10n.init("pas_http_user") if (not self.request.is_supported("session")): raise TranslatableError("core_unknown_error", 500) services_list = Settings.get("pas_http_user_alternative_login_services_list") if ((not Settings.get("pas_http_site_cookies_supported", True)) or type(services_list) is not list ): raise TranslatableError("pas_http_user_alternative_login_methods_disabled", 403) if (self.response.is_supported("html_css_files")): self.response.add_theme_css_file("mini_default_sprite.min.css") Link.set_store("servicemenu", Link.TYPE_RELATIVE_URL, L10n.get("core_back"), { "__query__": re.sub("\\_\\_\\w+\\_\\_", "", source_iline) }, icon = "mini-default-back", priority = 7 ) extended_services_list = [ ] for service in services_list: if ("id" in service and "parameters" in service): extended_service = service.copy() extended_service['type'] = Link.TYPE_RELATIVE_URL if ("dsd" not in extended_service['parameters']): extended_service['parameters']['dsd'] = { } extended_service['parameters']['dsd']['usid'] = service['id'] extended_service['parameters']['dsd']['source'] = source extended_service['parameters']['dsd']['target'] = target extended_services_list.append(extended_service) # # content = { "title": L10n.get("pas_http_user_alternative_login_services"), "service_list": { "entries": extended_services_list } } self.response.init() self.response.set_title(content['title']) self.response.add_oset_content("core.service_list", content)
def execute_login(self, is_save_mode = False): """ Action for "login" :since: v0.2.00 """ source_iline = InputFilter.filter_control_chars(self.request.get_dsd("source", "")).strip() target_iline = InputFilter.filter_control_chars(self.request.get_dsd("target", "")).strip() source = source_iline if (source_iline == ""): source_iline = "m=user;a=services" target = target_iline if (target_iline == ""): if (Settings.is_defined("pas_http_user_login_default_target_lang_{0}".format(self.request.get_lang()))): target_iline = Settings.get("pas_http_user_login_default_target_lang_{0}".format(self.request.get_lang())) elif (Settings.is_defined("pas_http_user_login_default_target")): target_iline = Settings.get("pas_http_user_login_default_target") elif (source == ""): target_iline = "m=user;a=services;lang=__lang__;theme=__theme__" else: target_iline = source_iline # L10n.init("pas_http_core_form") L10n.init("pas_http_user") if (self.response.is_supported("html_css_files")): self.response.add_theme_css_file("mini_default_sprite.min.css") Link.set_store("servicemenu", Link.TYPE_RELATIVE_URL, L10n.get("core_back"), { "__query__": re.sub("\\_\\_\\w+\\_\\_", "", source_iline) }, icon = "mini-default-back", priority = 7 ) if (not self.request.is_supported("session")): raise TranslatableError("core_unknown_error", 500) is_cookie_supported = Settings.get("pas_http_site_cookies_supported", True) if (is_cookie_supported and type(Settings.get("pas_http_user_alternative_login_services_list")) is list ): Link.set_store("servicemenu", Link.TYPE_RELATIVE_URL, L10n.get("pas_http_user_alternative_login_methods_view"), { "__request__": True, "a": "login-alternatives-list", "dsd": { "source": source, "target": target } }, icon = "mini-default-option", priority = 3 ) # form_id = InputFilter.filter_control_chars(self.request.get_parameter("form_id")) form = FormProcessor(form_id) if (is_save_mode): form.set_input_available() field = TextField("uusername") field.set_title(L10n.get("pas_core_username")) field.set_placeholder(L10n.get("pas_http_core_form_case_sensitive_placeholder")) field.set_required() field.set_limits(int(Settings.get("pas_http_core_username_min", 3)), 100) field.set_size(TextField.SIZE_SMALL) form.add(field) field = PasswordField("upassword") field.set_title(L10n.get("pas_http_user_password")) field.set_required() field.set_limits(int(Settings.get("pas_http_user_password_min", 6))) field.set_mode(PasswordField.PASSWORD_CLEARTEXT) form.add(field) if (is_cookie_supported): cookie_choices = [ { "value": "1", "title": L10n.get("core_yes") }, { "value": "0", "title": L10n.get("core_no") } ] field = RadioField("ucookie") field.set_title(L10n.get("pas_http_user_login_use_cookie")) field.set_value("1") field.set_choices(cookie_choices) field.set_required() form.add(field) # if (is_save_mode and form.check()): username = InputFilter.filter_control_chars(form.get_value("uusername")) password = InputFilter.filter_control_chars(form.get_value("upassword")) user_profile_class = NamedLoader.get_class("dNG.data.user.Profile") if (user_profile_class is None): raise TranslatableException("core_unknown_error") try: user_profile = user_profile_class.load_username(username) except NothingMatchedException as handled_exception: raise TranslatableError("pas_http_user_username_or_password_invalid", 403, _exception = handled_exception) user_profile_data = user_profile.get_data_attributes("id", "lang", "theme") if (user_profile.is_banned()): raise TranslatableError("pas_http_user_profile_banned", 403) if (user_profile.is_locked()): raise TranslatableError("pas_http_user_profile_locked", 403) if (user_profile.is_type("ex")): raise TranslatableError("pas_http_user_feature_not_available_for_external_verified_member", 403) if ((not user_profile.is_valid()) or (not user_profile.is_password_valid(password)) ): raise TranslatableError("pas_http_user_username_or_password_invalid", 403) session = Session.load() session.set("session.user_id", user_profile_data['id']) session.set_cookie(is_cookie_supported and form.get_value("ucookie") == "1") session.save() self.request.set_session(session) target_iline = target_iline.replace("__lang__", user_profile_data['lang']) target_iline = target_iline.replace("__theme__", user_profile_data['theme']) target_iline = re.sub("\\_\\_\\w+\\_\\_", "", target_iline) NotificationStore.get_instance().add_completed_info(L10n.get("pas_http_user_done_login")) Link.clear_store("servicemenu") redirect_request = PredefinedHttpRequest() redirect_request.set_iline(target_iline) self.request.redirect(redirect_request) else: content = { "title": L10n.get("pas_http_user_title_login") } content['form'] = { "object": form, "url_parameters": { "__request__": True, "a": "login-save", "dsd": { "source": source, "target": target } }, "button_title": "pas_core_login" } self.response.init() self.response.set_title(content['title']) self.response.add_oset_content("user.status.login", content)
def _execute_register(self, username = None, email = None, ex_type = None, source_iline = "", target_iline = "", is_save_mode = False): """ Action for "register" :param username: User name to be used :param email: Verified e-mail address to be used :param ex_type: Externally verified service identifier string :param source_iline: Source URI query string :param target_iline: Target URI query string :param is_save_mode: True if the form is submitted :since: v0.2.00 """ # pylint: disable=star-args source = source_iline if (source_iline == ""): source_iline = "m=user;a=services" target = target_iline if (target_iline == ""): if (Settings.is_defined("pas_http_user_register_default_target_lang_{0}".format(self.request.get_lang()))): target_iline = Settings.get("pas_http_user_register_default_target_lang_{0}".format(self.request.get_lang())) elif (Settings.is_defined("pas_http_user_register_default_target")): target_iline = Settings.get("pas_http_user_register_default_target") else: target_iline = source_iline # L10n.init("pas_http_core_form") L10n.init("pas_http_user") if (not Settings.get("pas_http_user_registration_allowed", True)): raise TranslatableError("pas_http_user_registration_disabled", 403) if (self.response.is_supported("html_css_files")): self.response.add_theme_css_file("mini_default_sprite.min.css") Link.set_store("servicemenu", Link.TYPE_RELATIVE_URL, L10n.get("core_back"), { "__query__": re.sub("\\_\\_\\w+\\_\\_", "", source_iline) }, icon = "mini-default-back", priority = 7 ) if (not DatabaseTasks.is_available()): raise TranslatableException("pas_core_tasks_daemon_not_available") form_id = InputFilter.filter_control_chars(self.request.get_parameter("form_id")) form = FormProcessor(form_id) if (is_save_mode): form.set_input_available() is_email_verified = (email is not None) if (not is_email_verified): field = EMailField("uemail") field.set_title(L10n.get("pas_http_user_email")) field.set_required() field.set_limits(_max = 255) field.set_validators([ self._check_email_not_registered ]) form.add(field) # if (username is None): field = TextField("uusername") field.set_required() field.set_limits(int(Settings.get("pas_http_core_username_min", 3)), 100) field.set_size(TextField.SIZE_SMALL) else: field = InfoField("uusername") field.set_value(username) # field.set_title(L10n.get("pas_core_username")) field.set_validators([ self._check_username_not_registered ]) form.add(field) if (is_email_verified): field = InfoField("uemail") field.set_title(L10n.get("pas_http_user_email")) field.set_value(email) field.set_validators([ self._check_email_not_registered ]) form.add(field) # if (ex_type is None): field = PasswordField("upassword") field.set_title(L10n.get("pas_http_user_password")) field.set_required() field.set_limits(int(Settings.get("pas_http_user_password_min", 6))) field.set_mode(PasswordField.PASSWORD_CLEARTEXT | PasswordField.PASSWORD_WITH_REPETITION) form.add(field) # tos_filepath = Settings.get_lang_associated("pas_http_user_tos_filepath", self.request.get_lang(), "{0}/settings/pas_user_tos.ftg".format(Settings.get("path_data")) ) field = FormTagsFileField("utos") field.set_title(L10n.get("pas_http_user_tos")) field.set_required() field.set_formtags_filepath(tos_filepath) form.add(field) tos_choices = [ { "title": L10n.get("core_yes"), "value": "accepted" }, { "title": L10n.get("core_no"), "value": "denied" } ] field = RadioField("utos_accepted") field.set_title(L10n.get("pas_http_user_tos_accepted")) field.set_choices(tos_choices) field.set_required() field.set_validators([ self._check_tos_accepted ]) form.add(field) if (is_save_mode and form.check()): if (not is_email_verified): email = InputFilter.filter_email_address(form.get_value("uemail")) if (username is None): username = InputFilter.filter_control_chars(form.get_value("uusername")) user_profile_class = NamedLoader.get_class("dNG.data.user.Profile") if (user_profile_class is None): raise TranslatableException("core_unknown_error") user_profile = user_profile_class() user_profile_data = { "name": username, "lang": self.request.get_lang(), "email": email } if (ex_type is None): password = InputFilter.filter_control_chars(form.get_value("upassword")) user_profile.set_password(password) else: user_profile_data['type'] = user_profile_class.TYPE_EXTERNAL_VERIFIED_MEMBER user_profile_data['type_ex'] = ex_type # with TransactionContext(): user_profile.set_data_attributes(**user_profile_data) if (not is_email_verified): user_profile.lock() else: user_profile.unlock() user_profile.save() # user_id = user_profile.get_id() if (not is_email_verified): cleanup_timeout_days = int(Settings.get("pas_http_user_registration_days", 28)) cleanup_timeout = (cleanup_timeout_days * 86400) vid = Md5.hash(urandom(32)) database_tasks = DatabaseTasks.get_instance() database_tasks.add("dNG.pas.user.Profile.delete.{0}".format(username), "dNG.pas.user.Profile.delete", cleanup_timeout, username = username ) database_tasks.add("dNG.pas.user.Profile.sendRegistrationEMail.{0}".format(username), "dNG.pas.user.Profile.sendRegistrationEMail", 1, username = username, vid = vid, vid_timeout_days = cleanup_timeout_days ) database_tasks.register_timeout(vid, "dNG.pas.user.Profile.registrationValidated", cleanup_timeout, username = username, vid = vid ) self._on_pending_registration(user_id, source_iline, target_iline) else: self._on_registration_completed(user_id, source_iline, target_iline) else: content = { "title": L10n.get("pas_http_user_registration") } content['form'] = { "object": form, "url_parameters": { "__request__": True, "a": "register-save", "dsd": { "source": source, "target": target } }, "button_title": "core_continue" } self.response.init() self.response.set_title(content['title']) self.response.add_oset_content("core.form", content)