@@ -1033,6 +1116,112 @@ def SettingsPage(server):
send(server, html, 200)
+def EditorPage(server):
+
+ user = validate(server.cookie)
+
+ # Authorization check
+ if not user:
+ AccessDenied(server)
+ return
+
+ config = Set.Load()
+
+ Tabs = tabs()
+ f = Set.Folder()
+
+ # Generating
+ html = head(title = "Editor",
+ description = "Editor",
+ config = config
+ )
+
+ html = html + Button(config.get("title", "My Website"), "/", image=config.get("favicon", "/icon/internet"))
+
+ tab = server.parsed.get("tab", [""])[0]
+ name = server.parsed.get("name", [""])[0]
+
+ if tab in Tabs:
+ Articles = articles(tab)
+ else:
+ Articles = {}
+
+ url = tab+"/"+name
+ article = Articles.get(name, {})
+
+ if article:
+ try:
+ text = open(f+"/tabs/"+tab+"/"+name+"/text.md")
+ text = text.read()
+ except:
+ text = ""
+ else:
+ text = ""
+
+ html = html + """
+
+
+
+
+
+ """
+
+ html = html + LoginButton(server)
+
+ send(server, html, 200)
###
@@ -1623,7 +1812,82 @@ def UpdateAccount(server):
json.dump(user, save, indent=4)
Redirect(server, "/settings")
+
+def UpdatePublicationRights(server):
+
+ user = validate(server.cookie)
+
+ # Authorization check
+ if not user:
+ AccessDenied(server)
+ return
+
+ Accounts = accounts()
+
+ account = server.parsed.get("account", [""])[0]
+
+ if account not in Accounts:
+ NotFound(server)
+ return
+
+ if not moderates(user.get("username", ""), account):
+ AccessDenied(server)
+ return
+
+ Tabs = tabs()
+ Account = Accounts[account]
+ if "editsIn" not in Account:
+ Account["editsIn"] = []
+
+ granted = []
+ revoked = []
+ for tab in Tabs:
+
+ if not editsIn(user.get("username", ""), tab):
+ AccessDenied(server)
+ return
+
+ tabOn = server.parsed.get(tab, [""])[0]
+ if tabOn and tab not in Account["editsIn"]:
+ Account["editsIn"].append(tab)
+ granted.append(tab)
+
+ elif not tabOn and tab in Account["editsIn"]:
+ Account["editsIn"].remove(tab)
+ revoked.append(tab)
+
+ f = Set.Folder()
+ folder = f+"/accounts"
+ with open(folder+"/"+account+".json", "w") as save:
+ json.dump(Account, save, indent=4)
+
+ Redirect(server, "/account/"+account)
+
+ # Notification
+
+ text = "@"+user.get("username", "")+" "
+ if granted:
+ text = text + "granted you publication rights in: "
+ for n, i in enumerate(granted):
+ text = text + i
+ if n != len(granted)-1:
+ text = text + ", "
+
+ if revoked:
+ text = text + " and "
+
+ if revoked:
+ text = text + "revoked your publication rights in: "
+ for n, i in enumerate(revoked):
+ text = text + i
+ if n != len(revoked)-1:
+ text = text + ", "
+
+ text = text + ".
"
+
+ Notify(account, "/account/"+account, text)
+
def DoComment(server):
user = validate(server.cookie)
@@ -1744,6 +2008,102 @@ def DoComment(server):
url+placeRedirect+str(number),
"@"+Safe(username)+" mentioned you:
"+article.get("title", "")+""+Safe(text[:200])+"")
+def Publish(server):
+
+ user = validate(server.cookie)
+
+ # Authorization check
+ if not user:
+ AccessDenied(server)
+ return
+
+ config = Set.Load()
+ Tabs = tabs()
+
+ f = Set.Folder()
+
+ # Getting data to create
+ tab = server.parsed.get("tab", [""])[0]
+ name = server.parsed.get("name", [""])[0]
+ text = server.parsed.get("text", [""])[0]
+ title = server.parsed.get("title", [""])[0]
+ description = server.parsed.get("description", [""])[0]
+ thumbnail = server.parsed.get("thumbnail", [""])[0]
+ License = server.parsed.get("license", [""])[0]
+ recording = server.parsed.get("recording", [""])[0]
+
+ # If this tab doesn't exist, this is an error.
+ if tab not in Tabs:
+ AccessDenied(server)
+ return
+
+ # Checking if the user has rights to post in here.
+ if not editsIn(user.get("username"), tab):
+ AccessDenied(server)
+ return
+
+ Articles = articles(tab)
+
+ if not name:
+ name = Simplify(title)
+
+ # Reading the file
+
+ if name in Articles:
+ metadata = Articles[name]
+
+ else:
+ metadata = {
+ "title":"",
+ "timestamp":time.time(),
+ "description":"",
+ "author":user.get("username", ""),
+ "thumbnail":"",
+ "license":"",
+ "views":{
+ "amount":0,
+ "viewers":[],
+ "dates":{}
+ },
+ "recording":"",
+ "comments":{
+ "comments":[],
+ "requests":[]
+ }
+ }
+
+ # Checking if the user can edit the posts of the
+ # author of this article.
+
+ if not moderates(user.get("username"), metadata.get("author", "")):
+ AccessDenied(server)
+ return
+
+ metadata["title"] = title
+ metadata["description"] = description
+ metadata["license"] = License
+ metadata["recording"] = recording
+ metadata["thumbnail"] = thumbnail
+
+ # Save the changes
+
+ try:
+ os.makedirs(f+"/tabs/"+tab+"/"+name)
+ except:pass
+
+ with open(f+"/tabs/"+tab+"/"+name+"/metadata.json", "w") as save:
+ json.dump(metadata, save, indent=4)
+
+ with open(f+"/tabs/"+tab+"/"+name+"/text.md", "w") as save:
+
+ # Enabling HTML embedding only for the owner
+ if rank(user.get("username", "")) == 0:
+ save.write(text)
+ else:
+ save.write(Safe(text))
+
+ Redirect(server, "/"+tab+"/"+name)
+
def DeleteComment(server):
diff --git a/modules/Run.py b/modules/Run.py
index b6d7a64..9beb367 100644
--- a/modules/Run.py
+++ b/modules/Run.py
@@ -28,7 +28,6 @@ class handler(BaseHTTPRequestHandler):
q = clr["tbbl"]
b = clr["tbbl"]
- #print(dir(self))
try:
if self.newview:
@@ -57,15 +56,64 @@ class handler(BaseHTTPRequestHandler):
logfile = open(filename, "ab")
logfile.write((toprint+"\n").encode('utf-8'))
logfile.close()
-
+
+ def do_POST(self):
+
+ self.path = self.path.replace("/..", "/")
+ self.path = self.path.replace("%27", "'")
+
+ self.cookie = self.headers.get("Cookie")
+ self.newview = False
+ if self.cookie: self.cookie = self.cookie[-50:]
+
+ # Failing early to make sure that nobody will
+ # try attacking this part of the server.
+
+ commands = ["do_edit"]
+ found = False
+ for i in commands:
+ if i in self.path:
+ found = True
+ break
+ if not found:
+ Render.AccessDenied(self)
+ return
+
+
+ # Not allowing more than 1 MB for the sake of
+ # network. A full book of Sheiny The Hacker
+ # which was posted on blenderdumbass.org is
+ # only about 160 KB. 1MB should be plenty.
+
+ length = int(self.headers["Content-Length"])
+ if length < 1000000:
+ try:
+ text = self.rfile.read(length).decode("utf-8")
+ except:
+ Render.AccessDenied(self)
+ return
+
+ else:
+ Render.AccessDenied(self)
+ return
+
+ #parsed_url = urllib.parse.urlparse(text)
+ self.parsed = urllib.parse.parse_qs(text)
+
+ if self.path[1:].startswith("do_edit"):
+ Render.Publish(self)
+
+ else:
+ Render.NotFound(self)
+
def do_GET(self):
self.path = self.path.replace("/..", "/")
self.path = self.path.replace("%27", "'")
parsed_url = urllib.parse.urlparse(self.path)
-
self.parsed = urllib.parse.parse_qs(parsed_url.query)
+
self.cookie = self.headers.get("Cookie")
if self.cookie: self.cookie = self.cookie[-50:]
@@ -100,9 +148,12 @@ class handler(BaseHTTPRequestHandler):
elif self.path[1:].startswith("login"):
Render.LoginPage(self)
+ elif self.path[1:].startswith("editor"):
+ Render.EditorPage(self)
+
elif self.path[1:].startswith("register"):
Render.RegisterPage(self)
-
+
elif self.path[1:].startswith("settings"):
Render.SettingsPage(self)
@@ -115,6 +166,9 @@ class handler(BaseHTTPRequestHandler):
elif self.path[1:].startswith("update_account"):
Render.UpdateAccount(self)
+ elif self.path[1:].startswith("grant_publication_rights"):
+ Render.UpdatePublicationRights(self)
+
elif self.path[1:].startswith("create_invite"):
Render.CreateInvite(self)