def actionCertAdd(self, to, domain, auth_type, auth_user_name, cert): try: res = self.user.addCert(self.user.getAuthAddress(self.site.address), domain, auth_type, auth_user_name, cert) if res is True: self.cmd( "notification", ["done", _("{_[New certificate added]:} <b>{auth_type}/{auth_user_name}@{domain}</b>.")] ) self.user.setCert(self.site.address, domain) self.site.updateWebsocket(cert_changed=domain) self.response(to, "ok") elif res is False: # Display confirmation of change cert_current = self.user.certs[domain] body = _("{_[Your current certificate]:} <b>{cert_current[auth_type]}/{cert_current[auth_user_name]}@{domain}</b>") self.cmd( "confirm", [body, _("Change it to {auth_type}/{auth_user_name}@{domain}")], lambda (res): self.cbCertAddConfirm(to, domain, auth_type, auth_user_name, cert) ) else: self.response(to, "Not changed") except Exception, err: self.log.error("CertAdd error: Exception - %s" % err.message) self.response(to, {"error": err.message})
def actionCertSelect(self, to, accepted_domains=[], accept_any=False): accounts = [] accounts.append(["", _["Unique to site"], ""]) # Default option active = "" # Make it active if no other option found # Add my certs auth_address = self.user.getAuthAddress( self.site.address) # Current auth address for domain, cert in self.user.certs.items(): if auth_address == cert["auth_address"]: active = domain title = cert["auth_user_name"] + "@" + domain if domain in accepted_domains or not accepted_domains or accept_any: accounts.append([domain, title, ""]) else: accounts.append([domain, title, "disabled"]) # Render the html body = "<span style='padding-bottom: 5px; display: inline-block'>" + _[ "Select account you want to use in this site:"] + "</span>" # Accounts for domain, account, css_class in accounts: if domain == active: css_class += " active" # Currently selected option title = _(u"<b>%s</b> <small>({_[currently selected]})</small>" ) % account else: title = "<b>%s</b>" % account body += "<a href='#Select+account' class='select select-close cert %s' title='%s'>%s</a>" % ( css_class, domain, title) # More available providers more_domains = [ domain for domain in accepted_domains if domain not in self.user.certs ] # Domains we not displayed yet if more_domains: # body+= "<small style='margin-top: 10px; display: block'>Accepted authorization providers by the site:</small>" body += "<div style='background-color: #F7F7F7; margin-right: -30px'>" for domain in more_domains: body += _(u""" <a href='/{domain}' onclick='wrapper.gotoSite(this)' class='select'> <small style='float: right; margin-right: 40px; margin-top: -1px'>{_[Register]} »</small>{domain} </a> """) body += "</div>" body += """ <script> $(".notification .select.cert").on("click", function() { $(".notification .select").removeClass('active') wrapper.ws.cmd('certSet', [this.title]) return false }) </script> """ # Send the notification self.cmd("notification", ["ask", body])
def actionCertSelect(self, to, accepted_domains=[], accept_any=False, accepted_pattern=None): accounts = [] accounts.append(["", _["No certificate"], ""]) # Default option active = "" # Make it active if no other option found # Add my certs auth_address = self.user.getAuthAddress(self.site.address) # Current auth address site_data = self.user.getSiteData(self.site.address) # Current auth address if not accepted_domains and not accepted_pattern: # Accept any if no filter defined accept_any = True for domain, cert in self.user.certs.items(): if auth_address == cert["auth_address"] and domain == site_data.get("cert"): active = domain title = cert["auth_user_name"] + "@" + domain accepted_pattern_match = accepted_pattern and SafeRe.match(accepted_pattern, domain) if domain in accepted_domains or accept_any or accepted_pattern_match: accounts.append([domain, title, ""]) else: accounts.append([domain, title, "disabled"]) # Render the html body = "<span style='padding-bottom: 5px; display: inline-block'>" + _["Select account you want to use in this site:"] + "</span>" # Accounts for domain, account, css_class in accounts: if domain == active: css_class += " active" # Currently selected option title = _(u"<b>%s</b> <small>({_[currently selected]})</small>") % account else: title = "<b>%s</b>" % account body += "<a href='#Select+account' class='select select-close cert %s' title='%s'>%s</a>" % (css_class, domain, title) # More available providers more_domains = [domain for domain in accepted_domains if domain not in self.user.certs] # Domains we not displayed yet if more_domains: # body+= "<small style='margin-top: 10px; display: block'>Accepted authorization providers by the site:</small>" body += "<div style='background-color: #F7F7F7; margin-right: -30px'>" for domain in more_domains: body += _(u""" <a href='/{domain}' onclick='zeroframe.certSelectGotoSite(this)' class='select'> <small style='float: right; margin-right: 40px; margin-top: -1px'>{_[Register]} »</small>{domain} </a> """) body += "</div>" body += """ <script> $(".notification .select.cert").on("click", function() { $(".notification .select").removeClass('active') zeroframe.response(%s, this.title) return false }) </script> """ % self.next_message_id # Send the notification self.cmd("notification", ["ask", body], lambda domain: self.actionCertSet(to, domain))
def addHomepageNotifications(self): if not(self.hasPlugin("Multiuser")) and not(self.hasPlugin("UiPassword")): bind_ip = getattr(config, "ui_ip", "") whitelist = getattr(config, "ui_restrict", []) # binds to the Internet, no IP whitelist, no UiPassword, no Multiuser if ("0.0.0.0" == bind_ip or "*" == bind_ip) and (not whitelist): self.site.notifications.append([ "error", _(u"You are not going to set up a public gateway. However, <b>your Web UI is<br>" + \ "open to the whole Internet.</b> " + \ "Please check your configuration.") ]) file_server = sys.modules["main"].file_server if file_server.port_opened is True: self.site.notifications.append([ "done", _["Congratulations, your port <b>{0}</b> is opened.<br>You are a full member of the ZeroNet network!"].format(config.fileserver_port), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Successfully started Tor onion hidden services.]} """), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions is not False: self.site.notifications.append([ "error", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Unable to start hidden services, please check your config.]} """), 0 ]) elif file_server.port_opened is False and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Successfully started Tor onion hidden services.]}<br> {_[For faster connections open <b>{0}</b> port on your router.]} """).format(config.fileserver_port), 10000 ]) else: self.site.notifications.append([ "error", _(u""" {_[Your connection is restricted. Please, open <b>{0}</b> port on your router]}<br> {_[or configure Tor to become a full member of the ZeroNet network.]} """).format(config.fileserver_port), 0 ])
def addHomepageNotifications(self): if not(self.hasPlugin("Multiuser")) and not(self.hasPlugin("UiPassword")): bind_ip = getattr(config, "ui_ip", "") whitelist = getattr(config, "ui_restrict", []) # binds to the Internet, no IP whitelist, no UiPassword, no Multiuser if ("0.0.0.0" == bind_ip or "*" == bind_ip) and (not whitelist): self.site.notifications.append([ "error", _(u"You are not going to set up a public gateway. However, <b>your Web UI is<br>" + "open to the whole Internet.</b> " + "Please check your configuration.") ]) file_server = sys.modules["main"].file_server if file_server.port_opened is True: self.site.notifications.append([ "done", _["Congratulations, your port <b>{0}</b> is opened.<br>You are a full member of the ZeroNet network!"].format(config.fileserver_port), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Successfully started Tor onion hidden services.]} """), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions is not False: self.site.notifications.append([ "error", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Unable to start hidden services, please check your config.]} """), 0 ]) elif file_server.port_opened is False and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Successfully started Tor onion hidden services.]}<br> {_[For faster connections open <b>{0}</b> port on your router.]} """).format(config.fileserver_port), 10000 ]) else: self.site.notifications.append([ "error", _(u""" {_[Your connection is restricted. Please, open <b>{0}</b> port on your router]}<br> {_[or configure Tor to become a full member of the ZeroNet network.]} """).format(config.fileserver_port), 0 ])
def actionCertSelect(self, to, accepted_domains=[], accept_any=False, accepted_pattern=None): accounts = [] accounts.append(["", _["No certificate"], ""]) # Default option active = "" # Make it active if no other option found # Add my certs auth_address = self.user.getAuthAddress(self.site.address) # Current auth address site_data = self.user.getSiteData(self.site.address) # Current auth address if not accepted_domains and not accepted_pattern: # Accept any if no filter defined accept_any = True for domain, cert in self.user.certs.items(): if auth_address == cert["auth_address"] and domain == site_data.get("cert"): active = domain title = cert["auth_user_name"] + "@" + domain accepted_pattern_match = accepted_pattern and SafeRe.match(accepted_pattern, domain) if domain in accepted_domains or accept_any or accepted_pattern_match: accounts.append([domain, title, ""]) else: accounts.append([domain, title, "disabled"]) # Render the html body = "<span style='padding-bottom: 5px; display: inline-block'>" + _["Select account you want to use in this site:"] + "</span>" # Accounts for domain, account, css_class in accounts: if domain == active: css_class += " active" # Currently selected option title = _(u"<b>%s</b> <small>({_[currently selected]})</small>") % account else: title = "<b>%s</b>" % account body += "<a href='#Select+account' class='select select-close cert %s' title='%s'>%s</a>" % (css_class, domain, title) # More available providers more_domains = [domain for domain in accepted_domains if domain not in self.user.certs] # Domains we not displayed yet if more_domains: # body+= "<small style='margin-top: 10px; display: block'>Accepted authorization providers by the site:</small>" body += "<div style='background-color: #F7F7F7; margin-right: -30px'>" for domain in more_domains: body += _(u""" <a href='/{domain}' target='_top' class='select'> <small style='float: right; margin-right: 40px; margin-top: -1px'>{_[Register]} »</small>{domain} </a> """) body += "</div>" script = """ $(".notification .select.cert").on("click", function() { $(".notification .select").removeClass('active') zeroframe.response(%s, this.title) return false }) """ % self.next_message_id self.cmd("notification", ["ask", body], lambda domain: self.actionCertSet(to, domain)) self.cmd("injectScript", script)
def actionCertSelect(self, to, accepted_domains=[], accept_any=False): accounts = [] accounts.append(["", _["Unique to site"], ""]) # Default option active = "" # Make it active if no other option found # Add my certs auth_address = self.user.getAuthAddress(self.site.address) # Current auth address site_data = self.user.getSiteData(self.site.address) # Current auth address for domain, cert in self.user.certs.items(): if auth_address == cert["auth_address"] and domain == site_data.get("cert"): active = domain title = cert["auth_user_name"] + "@" + domain if domain in accepted_domains or not accepted_domains or accept_any: accounts.append([domain, title, ""]) else: accounts.append([domain, title, "disabled"]) # Render the html body = "<span style='padding-bottom: 5px; display: inline-block'>" + _["Select account you want to use in this site:"] + "</span>" # Accounts for domain, account, css_class in accounts: if domain == active: css_class += " active" # Currently selected option title = _(u"<b>%s</b> <small>({_[currently selected]})</small>") % account else: title = "<b>%s</b>" % account body += "<a href='#Select+account' class='select select-close cert %s' title='%s'>%s</a>" % (css_class, domain, title) # More available providers more_domains = [domain for domain in accepted_domains if domain not in self.user.certs] # Domains we not displayed yet if more_domains: # body+= "<small style='margin-top: 10px; display: block'>Accepted authorization providers by the site:</small>" body += "<div style='background-color: #F7F7F7; margin-right: -30px'>" for domain in more_domains: body += _(u""" <a href='/{domain}' onclick='wrapper.gotoSite(this)' class='select'> <small style='float: right; margin-right: 40px; margin-top: -1px'>{_[Register]} »</small>{domain} </a> """) body += "</div>" body += """ <script> $(".notification .select.cert").on("click", function() { $(".notification .select").removeClass('active') wrapper.ws.cmd('certSet', [this.title], function() { wrapper.sendInner({"cmd": "response", "to": %s, "result": this.title}) }) return false }) </script> """ % to # Send the notification self.cmd("notification", ["ask", body])
def cbSitePublish(self, to, site, thread, notification=True, callback=True): published = thread.value if published > 0: # Successfully published if notification: # self.cmd("notification", ["done", _["Content published to {0} peers."].format(published), 5000]) site.updateWebsocket() # Send updated site data to local websocket clients if callback: self.response(to, "ok") else: if len(site.peers) == 0: if sys.modules["main"].file_server.port_opened or sys.modules["main"].file_server.tor_manager.start_onions: if notification: self.cmd("notification", ["info", _["No peers found, but your content is ready to access."]]) if callback: self.response(to, "ok") else: if notification: self.cmd("notification", [ "info", _(u"""{_[Your network connection is restricted. Please, open <b>{0}</b> port]}<br> {_[on your router to make your site accessible for everyone.]}""").format(config.fileserver_port) ]) if callback: self.response(to, {"error": "Port not opened."}) else: if notification: self.response(to, {"error": "Content publish failed."})
def hasCmdPermission(self, cmd): flags = flag.db.get(self.getCmdFuncName(cmd), ()) is_public_proxy_user = not config.multiuser_local and self.user.master_address not in local_master_addresses if is_public_proxy_user and "no_multiuser" in flags: self.cmd("notification", ["info", _("This function ({cmd}) is disabled on this proxy!")]) return False else: return super(UiWebsocketPlugin, self).hasCmdPermission(cmd)
def cbCertAddConfirm(self, to, domain, auth_type, auth_user_name, cert): self.user.deleteCert(domain) self.user.addCert(self.user.getAuthAddress(self.site.address), domain, auth_type, auth_user_name, cert) self.cmd( "notification", ["done", _("Certificate changed to: <b>{auth_type}/{auth_user_name}@{domain}</b>.")] ) self.response(to, "ok")
def start(self): ws = self.ws if self.site.address == config.homepage and not self.site.page_requested: # Add open fileserver port message or closed port error to homepage at first request after start self.site.page_requested = True # Dont add connection notification anymore file_server = sys.modules["main"].file_server if file_server.port_opened is None or file_server.tor_manager.start_onions is None: self.site.page_requested = False # Not ready yet, check next time elif file_server.port_opened is True: self.site.notifications.append([ "done", _["Congratulation, your port <b>{0}</b> is opened.<br>You are full member of ZeroNet network!"] .format(config.fileserver_port), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Successfully started Tor onion hidden services.]} """), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions is not False: self.site.notifications.append([ "error", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Unable to start hidden services, please check your config.]} """), 0 ]) elif file_server.port_opened is False and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Successfully started Tor onion hidden services.]}<br> {_[For faster connections open <b>{0}</b> port on your router.]} """).format(config.fileserver_port), 10000 ]) else: self.site.notifications.append([ "error", _(u""" {_[Your connection is restricted. Please, open <b>{0}</b> port on your router]}<br> {_[or configure Tor to become full member of ZeroNet network.]} """).format(config.fileserver_port), 0 ]) for notification in self.site.notifications: # Send pending notification messages self.cmd("notification", notification) self.site.notifications = [] while True: try: message = ws.receive() except Exception, err: return "Bye." # Close connection if message: try: self.handleRequest(message) except Exception, err: if config.debug: # Allow websocket errors to appear on /Debug sys.modules["main"].DebugHook.handleError() self.log.error("WebSocket handleRequest error: %s" % Debug.formatException(err)) self.cmd( "error", "Internal error: %s" % Debug.formatException(err, "html"))
def start(self): ws = self.ws if self.site.address == config.homepage and not self.site.page_requested: # Add open fileserver port message or closed port error to homepage at first request after start self.site.page_requested = True # Dont add connection notification anymore file_server = sys.modules["main"].file_server if file_server.port_opened is None or file_server.tor_manager.start_onions is None: self.site.page_requested = False # Not ready yet, check next time elif file_server.port_opened is True: self.site.notifications.append([ "done", _["Congratulation, your port <b>{0}</b> is opened.<br>You are full member of ZeroNet network!"].format(config.fileserver_port), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Successfully started Tor onion hidden services.]} """), 10000 ]) elif config.tor == "always" and file_server.tor_manager.start_onions is not False: self.site.notifications.append([ "error", _(u""" {_[Tor mode active, every connection using Onion route.]}<br> {_[Unable to start hidden services, please check your config.]} """), 0 ]) elif file_server.port_opened is False and file_server.tor_manager.start_onions: self.site.notifications.append([ "done", _(u""" {_[Successfully started Tor onion hidden services.]}<br> {_[For faster connections open <b>{0}</b> port on your router.]} """).format(config.fileserver_port), 10000 ]) else: self.site.notifications.append([ "error", _(u""" {_[Your connection is restricted. Please, open <b>{0}</b> port on your router]}<br> {_[or configure Tor to become full member of ZeroNet network.]} """).format(config.fileserver_port), 0 ]) for notification in self.site.notifications: # Send pending notification messages self.cmd("notification", notification) self.site.notifications = [] while True: try: message = ws.receive() except Exception, err: return "Bye." # Close connection if message: try: self.handleRequest(message) except Exception, err: if config.debug: # Allow websocket errors to appear on /Debug sys.modules["main"].DebugHook.handleError() self.log.error("WebSocket handleRequest error: %s" % Debug.formatException(err)) self.cmd("error", "Internal error: %s" % Debug.formatException(err, "html"))
def deleteFiles(self): site_title = self.site.content_manager.contents.get( "content.json", {}).get("title", self.site.address) message_id = "delete-%s" % self.site.address self.log.debug("Deleting files from content.json (title: %s)..." % site_title) files = [] # Get filenames content_inner_paths = list(self.site.content_manager.contents.keys()) for i, content_inner_path in enumerate(content_inner_paths): content = self.site.content_manager.contents.get( content_inner_path, {}) files.append(content_inner_path) # Add normal files for file_relative_path in list(content.get("files", {}).keys()): file_inner_path = helper.getDirname( content_inner_path ) + file_relative_path # Relative to site dir files.append(file_inner_path) # Add optional files for file_relative_path in list( content.get("files_optional", {}).keys()): file_inner_path = helper.getDirname( content_inner_path ) + file_relative_path # Relative to site dir files.append(file_inner_path) if i % 100 == 0: num_files = len(files) self.site.messageWebsocket( _("Deleting site <b>{site_title}</b>...<br>Collected {num_files} files" ), message_id, (i / len(content_inner_paths)) * 25) if self.isFile("dbschema.json"): self.log.debug("Deleting db file...") self.closeDb("Deleting site") self.has_db = False try: schema = self.loadJson("dbschema.json") db_path = self.getPath(schema["db_file"]) if os.path.isfile(db_path): os.unlink(db_path) except Exception as err: self.log.error("Db file delete error: %s" % err) num_files = len(files) for i, inner_path in enumerate(files): path = self.getPath(inner_path) if os.path.isfile(path): for retry in range(5): try: os.unlink(path) break except Exception as err: self.log.error("Error removing %s: %s, try #%s" % (inner_path, err, retry)) time.sleep(float(retry) / 10) if i % 100 == 0: self.site.messageWebsocket( _("Deleting site <b>{site_title}</b>...<br>Deleting file {i}/{num_files}" ), message_id, 25 + (i / num_files) * 50) self.onUpdated(inner_path, False) self.log.debug("Deleting empty dirs...") i = 0 for root, dirs, files in os.walk(self.directory, topdown=False): for dir in dirs: path = os.path.join(root, dir) if os.path.isdir(path): try: i += 1 if i % 100 == 0: self.site.messageWebsocket( _("Deleting site <b>{site_title}</b>...<br>Deleting empty directories {i}" ), message_id, 85) os.rmdir(path) except OSError: # Not empty pass if os.path.isdir(self.directory) and os.listdir(self.directory) == []: os.rmdir(self.directory) # Remove sites directory if empty if os.path.isdir(self.directory): self.log.debug( "Some unknown file remained in site data dir: %s..." % self.directory) self.site.messageWebsocket( _("Deleting site <b>{site_title}</b>...<br>Site deleted, but some unknown files left in the directory" ), message_id, 100) return False # Some files not deleted else: self.log.debug("Site %s data directory deleted: %s..." % (site_title, self.directory)) self.site.messageWebsocket( _("Deleting site <b>{site_title}</b>...<br>All files deleted successfully" ), message_id, 100) return True # All clean