예제 #1
0
파일: client.py 프로젝트: dNG-git/pas_email
    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
예제 #2
0
    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")
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
    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")))
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
파일: client.py 프로젝트: dNG-git/pas_email
    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
예제 #9
0
    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()
예제 #10
0
	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()
예제 #11
0
    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)
예제 #12
0
파일: client.py 프로젝트: dNG-git/pas_email
    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
예제 #13
0
    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)
예제 #14
0
    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
예제 #15
0
    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"
예제 #16
0
    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
예제 #17
0
    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)
예제 #18
0
    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)
예제 #19
0
    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)