From 904eae0b917617bf0604c57998db5b9be98a3bb4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 29 Jan 2021 11:01:54 +0000 Subject: [PATCH 01/50] Purple theme newswire separator --- theme/purple/icons/separator_right.png | Bin 0 -> 1272 bytes theme/purple/theme.json | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 theme/purple/icons/separator_right.png diff --git a/theme/purple/icons/separator_right.png b/theme/purple/icons/separator_right.png new file mode 100644 index 0000000000000000000000000000000000000000..3f31f0fce4a0af81811c5785648734030ae63f70 GIT binary patch literal 1272 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3sqmgFW3h5xgPSpt#}63f9n&dCn4{JCJNx@x+U z%p>L)Q$h&&eliut-+#^U4Hv~2LsIixa>h8Ok_uN0Jl}46va4W{PTS4}i-TX|5kz3-XD+n&EqlL4j-5Nfl?lNJOa8Hif1CW37UpbABHDuT z)(Uy?5*%qPa;t|IfY3bLbPN1w2Y-AiER-q;>XzB@f;C=uh)e0Cwq$b__$i+ES3$x0 z2>^+(w;~yoeWI92lrrJmU?YN#4nP%|vn0MifK<67Nlqe}gR%448*7ZVFDqwWW}Hm` zp_0YGrbq>>loa)2$x%a9MU$##HT9rHYnGg{=A13BL#~=wGPP`GZpEsLCs)sI?q0kW zE`l>qODfM;UdZ)~3ufb>?Z)XPNa$?NI&Het{YtYP?A;KYLPxHJCj@&^k_Z zF#|D91md;`prCm%i%u!=BDa{u!uTkZk)$p*q0=G;glQ1#q$j%%azDi_sQ(l<{x5Q2 zq5D6`1)%%P?F(vs{m->c?EVUurcvL4<-TiYTFi2<8a3PgKDO<~3E+PQ zuJo3_TnA=8Nw2lE@Db3r4P0EeG-VIC+yMrj4B3<&$xkKZa=`l;eNzVLzXiJ2+_^Q+ zarywHXjX|E;NTD#%~STe$Gf}Q=l1WN=KOvD+w*eK0y}b;00006VoOIv00000008+z zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru}OFbbz+eQN*!01-( Date: Fri, 29 Jan 2021 11:28:17 +0000 Subject: [PATCH 02/50] Left column image for purple theme --- theme/purple/left_col_image.png | Bin 0 -> 1271 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 theme/purple/left_col_image.png diff --git a/theme/purple/left_col_image.png b/theme/purple/left_col_image.png new file mode 100644 index 0000000000000000000000000000000000000000..268bbd86f1128d4c66153e4c99e2365029206a62 GIT binary patch literal 1271 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3sqmgFW3h5xgPSpt#}63f9n&dCn4{JBuLx@x+U z%p>L)Q$h&&eliut-+#^U4Hv~2LsIixa>h8Ok_uN0JU*_ndx~lI`!YUr^llILATmaR zrXJs$FdmieZZzn&odTKp~X%f|A|h~FnJe&+N^fr?-G!Hl30^jZ6k1vIVQUyWXGCN+d#_JK{Qu?SZ*_;J_is$32pkVz3 zfJE3^kqpW{QOqPtnQ(5f5kW@>po+{{5?>%ds@#zzC&AYejGfosSYxz(Svm7E<7@&5 zl`IA}MJiyWq^KWDjvA^enp8EbsRu1uv*eUD=WKZ$a@E9=sbw>BD^^`Rxq5bU_u{p1 z5uAZqalut`dTW;38l~y}<={P2O?$*7R zUI&GNlVYTyBM%!s%BT~yHf5%%Gf$g7%dAgohw7*H3)JXP<4tP$*^?Tq!R!t}>p0QH z48%AQh}$B7g6736I;F&m++r3BPBT$PlDgQ0PKy{2ra`Qep6ouz{S>#L{!`rezsQA! z?*AYcfbKK5FR1nPKi4*~$5*&Cje@UljNzywuj@ap@}E9`D-iN4;XB-!#KH0Wd2av! z0flKpLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~mUQY#K-km8V`I$01E5nQwiMW_&J zg;pKRN57y+Lz3d+D7Y3J{8+3yxH#+T;3^1$A0SSSPKqv4;{TFDix>}%`|wi{pF@1EF1@S$CZ8W5;Qp0KsSA zN^kqC4Pg3{^m<#19RdB@z{Pc2llOqj9boXukW9&yf;7280eC;7Z^{7!w?KH!>#enq z(+40!U8Qb-gF|4XNZIQ?@9ydB?cX!4{(b Date: Fri, 29 Jan 2021 11:38:29 +0000 Subject: [PATCH 03/50] Time vertical alignment --- theme/purple/theme.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/theme/purple/theme.json b/theme/purple/theme.json index 4b7095d82..00fb693d2 100644 --- a/theme/purple/theme.json +++ b/theme/purple/theme.json @@ -1,4 +1,6 @@ { + "time-vertical-align": "0%", + "time-vertical-align-mobile": "1.5%", "post-separator-margin-top": "10px", "post-separator-margin-bottom": "10px", "column-left-header-background": "#35244d", From 2de0f83f5ce28ace248b95a2168ce3d7236b24f6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 29 Jan 2021 11:41:17 +0000 Subject: [PATCH 04/50] Default time alignment --- epicyon-profile.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index 7e1fd85e4..0d1212795 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -51,8 +51,8 @@ --font-size-tox: 16px; --font-size-tox2: 18px; --time-color: #aaa; - --time-vertical-align: 4px; - --time-vertical-align-mobile: 25px; + --time-vertical-align: 0%; + --time-vertical-align-mobile: 1.5%; --publish-button-text: #FFFFFF; --button-margin: 5px; --button-left-margin: none; From 9195e57c139b3045b6277ea0f358cca564a7d31d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 29 Jan 2021 21:33:23 +0000 Subject: [PATCH 05/50] Fallback mentions replacement --- content.py | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/content.py b/content.py index fef7d66e9..edfc173e0 100644 --- a/content.py +++ b/content.py @@ -14,6 +14,7 @@ from utils import getImageExtensions from utils import loadJson from utils import fileLastModified from utils import getLinkPrefixes +from petnames import getPetName def removeHtmlTag(htmlStr: str, tag: str) -> str: @@ -489,7 +490,7 @@ def tagExists(tagType: str, tagName: str, tags: {}) -> bool: return False -def _addMention(wordStr: str, httpPrefix: str, following: str, +def _addMention(wordStr: str, httpPrefix: str, following: str, petnames: str, replaceMentions: {}, recipients: [], tags: {}) -> bool: """Detects mentions and adds them to the replacements dict and recipients list @@ -501,9 +502,12 @@ def _addMention(wordStr: str, httpPrefix: str, following: str, # if no domain was specified. eg. @nick possibleNickname = possibleHandle for follow in following: - if follow.startswith(possibleNickname + '@'): - replaceDomain = \ - follow.replace('\n', '').replace('\r', '').split('@')[1] + if '@' not in follow: + continue + followNick = follow.split('@')[0] + if possibleNickname == followNick: + followStr = follow.replace('\n', '').replace('\r', '') + replaceDomain = followStr.split('@')[1] recipientActor = httpPrefix + "://" + \ replaceDomain + "/users/" + possibleNickname if recipientActor not in recipients: @@ -519,6 +523,33 @@ def _addMention(wordStr: str, httpPrefix: str, following: str, "\" class=\"u-url mention\">@" + possibleNickname + \ "" return True + # try replacing petnames with mentions + followCtr = 0 + for follow in following: + if '@' not in follow: + continue + pet = petnames[followCtr].replace('\n', '') + if pet: + if possibleNickname == pet: + followStr = follow.replace('\n', '').replace('\r', '') + replaceNickname = followStr.split('@')[0] + replaceDomain = followStr.split('@')[1] + recipientActor = httpPrefix + "://" + \ + replaceDomain + "/users/" + replaceNickname + if recipientActor not in recipients: + recipients.append(recipientActor) + tags[wordStr] = { + 'href': recipientActor, + 'name': wordStr, + 'type': 'Mention' + } + replaceMentions[wordStr] = \ + "@" + \ + replaceNickname + "" + return True + followCtr += 1 return False possibleNickname = None possibleDomain = None @@ -752,10 +783,14 @@ def addHtmlTags(baseDir: str, httpPrefix: str, # read the following list so that we can detect just @nick # in addition to @nick@domain following = None + petnames = None if '@' in words: if os.path.isfile(followingFilename): with open(followingFilename, "r") as f: following = f.readlines() + for handle in following: + pet = getPetName(baseDir, nickname, domain, handle) + petnames.append(pet + '\n') # extract mentions and tags from words longWordsList = [] @@ -769,7 +804,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str, longWordsList.append(wordStr) firstChar = wordStr[0] if firstChar == '@': - if _addMention(wordStr, httpPrefix, following, + if _addMention(wordStr, httpPrefix, following, petnames, replaceMentions, recipients, hashtags): prevWordStr = '' continue From bdfeb8f99364558db45435989936c4ac060d67e1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 29 Jan 2021 21:34:08 +0000 Subject: [PATCH 06/50] Increment follow counter --- content.py | 1 + 1 file changed, 1 insertion(+) diff --git a/content.py b/content.py index edfc173e0..28a2ac531 100644 --- a/content.py +++ b/content.py @@ -527,6 +527,7 @@ def _addMention(wordStr: str, httpPrefix: str, following: str, petnames: str, followCtr = 0 for follow in following: if '@' not in follow: + followCtr += 1 continue pet = petnames[followCtr].replace('\n', '') if pet: From 8299b77942c3edb601fca2514fdf1225df289fdf Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 11:47:09 +0000 Subject: [PATCH 07/50] Check for dangerout markup in downloaded announces --- daemon.py | 77 +++++++++++++++++++++++++++++++------------ inbox.py | 20 +++++++---- posts.py | 29 +++++++++------- webapp_confirm.py | 5 +-- webapp_frontscreen.py | 8 +++-- webapp_moderation.py | 5 +-- webapp_post.py | 14 ++++++-- webapp_profile.py | 14 +++++--- webapp_search.py | 8 +++-- webapp_timeline.py | 70 ++++++++++++++++++++++++++------------- 10 files changed, 173 insertions(+), 77 deletions(-) diff --git a/daemon.py b/daemon.py index 5ad42d349..03b84ca40 100644 --- a/daemon.py +++ b/daemon.py @@ -2614,7 +2614,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.projectVersion, self.server.YTReplacementDomain, self.server.showPublishedDateOnly, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) if hashtagStr: msg = hashtagStr.encode('utf-8') msglen = len(msg) @@ -2666,7 +2667,8 @@ class PubServer(BaseHTTPRequestHandler): port, self.server.YTReplacementDomain, self.server.showPublishedDateOnly, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) if historyStr: msg = historyStr.encode('utf-8') msglen = len(msg) @@ -2733,6 +2735,8 @@ class PubServer(BaseHTTPRequestHandler): return else: showPublishedDateOnly = self.server.showPublishedDateOnly + allowLocalNetworkAccess = \ + self.server.allowLocalNetworkAccess profileStr = \ htmlProfileAfterSearch(self.server.cssCache, self.server.recentPostsCache, @@ -2753,7 +2757,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.YTReplacementDomain, showPublishedDateOnly, self.server.defaultTimeline, - self.server.peertubeInstances) + self.server.peertubeInstances, + allowLocalNetworkAccess) if profileStr: msg = profileStr.encode('utf-8') msglen = len(msg) @@ -5674,7 +5679,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.projectVersion, self.server.YTReplacementDomain, self.server.showPublishedDateOnly, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) if hashtagStr: msg = hashtagStr.encode('utf-8') msglen = len(msg) @@ -6636,7 +6642,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, callingDomain, self.server.YTReplacementDomain, self.server.showPublishedDateOnly, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) if deleteStr: deleteStrLen = len(deleteStr) self._set_headers('text/html', deleteStrLen, @@ -6840,7 +6847,8 @@ class PubServer(BaseHTTPRequestHandler): projectVersion, ytDomain, self.server.showPublishedDateOnly, - peertubeInstances) + peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -6926,7 +6934,8 @@ class PubServer(BaseHTTPRequestHandler): projectVersion, ytDomain, self.server.showPublishedDateOnly, - peertubeInstances) + peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7013,6 +7022,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + self.server.allowLocalNetworkAccess, actorJson['roles'], None, None) msg = msg.encode('utf-8') @@ -7077,6 +7087,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.showPublishedDateOnly iconsAsButtons = \ self.server.iconsAsButtons + allowLocalNetworkAccess = \ + self.server.allowLocalNetworkAccess msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -7097,6 +7109,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + allowLocalNetworkAccess, actorJson['skills'], None, None) msg = msg.encode('utf-8') @@ -7208,6 +7221,8 @@ class PubServer(BaseHTTPRequestHandler): peertubeInstances = \ self.server.peertubeInstances cssCache = self.server.cssCache + allowLocalNetworkAccess = \ + self.server.allowLocalNetworkAccess msg = \ htmlIndividualPost(cssCache, recentPostsCache, @@ -7227,7 +7242,8 @@ class PubServer(BaseHTTPRequestHandler): likedBy, ytDomain, showPublishedDateOnly, - peertubeInstances) + peertubeInstances, + allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7329,6 +7345,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.showPublishedDateOnly peertubeInstances = \ self.server.peertubeInstances + allowLocalNetworkAccess = \ + self.server.allowLocalNetworkAccess msg = \ htmlIndividualPost(self.server.cssCache, recentPostsCache, @@ -7348,7 +7366,8 @@ class PubServer(BaseHTTPRequestHandler): likedBy, ytDomain, showPublishedDateOnly, - peertubeInstances) + peertubeInstances, + allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7481,7 +7500,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) if GETstartTime: self._benchmarkGETtimings(GETstartTime, GETtimings, 'show status done', @@ -7608,7 +7628,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.rssIconAtTop, self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7728,7 +7749,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.rssIconAtTop, self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7849,7 +7871,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7970,7 +7993,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8100,7 +8124,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8226,7 +8251,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8313,7 +8339,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.rssIconAtTop, self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8417,7 +8444,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8541,7 +8569,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8657,7 +8686,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8763,7 +8793,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, moderationActionStr, self.server.themeName, - self.server.peertubeInstances) + self.server.peertubeInstances, + self.server.allowLocalNetworkAccess) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8863,6 +8894,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + self.server.allowLocalNetworkAccess, shares, pageNumber, sharesPerPage) msg = msg.encode('utf-8') @@ -8959,6 +8991,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + self.server.allowLocalNetworkAccess, following, pageNumber, followsPerPage).encode('utf-8') @@ -9055,6 +9088,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + self.server.allowLocalNetworkAccess, followers, pageNumber, followsPerPage).encode('utf-8') @@ -9174,6 +9208,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.dormantMonths, self.server.peertubeInstances, + self.server.allowLocalNetworkAccess, None, None).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, diff --git a/inbox.py b/inbox.py index b572a3043..1dbf18af1 100644 --- a/inbox.py +++ b/inbox.py @@ -151,7 +151,8 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, postJsonObject: {}, allowDeletion: bool, boxname: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> None: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> None: """Converts the json post into html and stores it in a cache This enables the post to be quickly displayed later """ @@ -168,7 +169,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, avatarUrl, True, allowDeletion, httpPrefix, __version__, boxname, None, showPublishedDateOnly, - peertubeInstances, + peertubeInstances, allowLocalNetworkAccess, not isDM(postJsonObject), True, True, False, True) @@ -1259,7 +1260,8 @@ def _receiveAnnounce(recentPostsCache: {}, sendThreads: [], postLog: [], cachedWebfingers: {}, personCache: {}, messageJson: {}, federationList: [], debug: bool, translate: {}, - YTReplacementDomain: str) -> bool: + YTReplacementDomain: str, + allowLocalNetworkAccess: bool) -> bool: """Receives an announce activity within the POST section of HTTPServer """ if messageJson['type'] != 'Announce': @@ -1338,7 +1340,8 @@ def _receiveAnnounce(recentPostsCache: {}, postJsonObject = downloadAnnounce(session, baseDir, httpPrefix, nickname, domain, messageJson, __version__, translate, - YTReplacementDomain) + YTReplacementDomain, + allowLocalNetworkAccess) if not postJsonObject: if domain not in messageJson['object'] and \ onionDomain not in messageJson['object']: @@ -2119,7 +2122,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, messageJson, federationList, debug, translate, - YTReplacementDomain): + YTReplacementDomain, + allowLocalNetworkAccess): if debug: print('DEBUG: Announce accepted from ' + actor) @@ -2299,7 +2303,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, if isImageMedia(session, baseDir, httpPrefix, nickname, domain, postJsonObject, - translate, YTReplacementDomain): + translate, YTReplacementDomain, + allowLocalNetworkAccess): # media index will be updated updateIndexList.append('tlmedia') if isBlogPost(postJsonObject): @@ -2349,7 +2354,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, allowDeletion, boxname, showPublishedDateOnly, - peertubeInstances) + peertubeInstances, + allowLocalNetworkAccess) if debug: timeDiff = \ str(int((time.time() - htmlCacheStartTime) * diff --git a/posts.py b/posts.py index 6dd6c7e31..73e16d236 100644 --- a/posts.py +++ b/posts.py @@ -57,6 +57,7 @@ from utils import votesOnNewswireItem from utils import removeHtml from media import attachMedia from media import replaceYouTube +from content import dangerousMarkup from content import tagExists from content import removeLongWords from content import addHtmlTags @@ -2908,7 +2909,8 @@ def isDM(postJsonObject: {}) -> bool: def isImageMedia(session, baseDir: str, httpPrefix: str, nickname: str, domain: str, postJsonObject: {}, translate: {}, - YTReplacementDomain: str) -> bool: + YTReplacementDomain: str, + allowLocalNetworkAccess: bool) -> bool: """Returns true if the given post has attached image media """ if postJsonObject['type'] == 'Announce': @@ -2916,7 +2918,8 @@ def isImageMedia(session, baseDir: str, httpPrefix: str, downloadAnnounce(session, baseDir, httpPrefix, nickname, domain, postJsonObject, __version__, translate, - YTReplacementDomain) + YTReplacementDomain, + allowLocalNetworkAccess) if postJsonAnnounce: postJsonObject = postJsonAnnounce if postJsonObject['type'] != 'Create': @@ -3831,7 +3834,8 @@ def _rejectAnnounce(announceFilename: str): def downloadAnnounce(session, baseDir: str, httpPrefix: str, nickname: str, domain: str, postJsonObject: {}, projectVersion: str, - translate: {}, YTReplacementDomain: str) -> {}: + translate: {}, YTReplacementDomain: str, + allowLocalNetworkAccess: bool) -> {}: """Download the post referenced by an announce """ if not postJsonObject.get('object'): @@ -3919,12 +3923,11 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str, return None if not announcedJson.get('type'): _rejectAnnounce(announceFilename) - # pprint(announcedJson) return None if announcedJson['type'] != 'Note' and \ announcedJson['type'] != 'Article': + # You can only announce Note or Article types _rejectAnnounce(announceFilename) - # pprint(announcedJson) return None if not announcedJson.get('content'): _rejectAnnounce(announceFilename) @@ -3935,16 +3938,20 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str, if not validPostDate(announcedJson['published']): _rejectAnnounce(announceFilename) return None - if isFiltered(baseDir, nickname, domain, announcedJson['content']): + + # Check the content of the announce + contentStr = announcedJson['content'] + if dangerousMarkup(contentStr, allowLocalNetworkAccess): + _rejectAnnounce(announceFilename) + return None + if isFiltered(baseDir, nickname, domain, contentStr): _rejectAnnounce(announceFilename) return None # remove any long words - announcedJson['content'] = \ - removeLongWords(announcedJson['content'], 40, []) + announcedJson['content'] = removeLongWords(contentStr, 40, []) # remove text formatting, such as bold/italics - announcedJson['content'] = \ - removeTextFormatting(announcedJson['content']) + announcedJson['content'] = removeTextFormatting(contentStr) # wrap in create to be consistent with other posts announcedJson = \ @@ -3952,8 +3959,8 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str, actorNickname, actorDomain, actorPort, announcedJson) if announcedJson['type'] != 'Create': + # Create wrap failed _rejectAnnounce(announceFilename) - # pprint(announcedJson) return None # labelAccusatoryPost(postJsonObject, translate) diff --git a/webapp_confirm.py b/webapp_confirm.py index 121777268..26b8289b7 100644 --- a/webapp_confirm.py +++ b/webapp_confirm.py @@ -30,7 +30,8 @@ def htmlConfirmDelete(cssCache: {}, callingDomain: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Shows a screen asking to confirm the deletion of a post """ if '/statuses/' not in messageId: @@ -70,7 +71,7 @@ def htmlConfirmDelete(cssCache: {}, httpPrefix, projectVersion, 'outbox', YTReplacementDomain, showPublishedDateOnly, - peertubeInstances, + peertubeInstances, allowLocalNetworkAccess, False, False, False, False, False) deletePostStr += '
' deletePostStr += \ diff --git a/webapp_frontscreen.py b/webapp_frontscreen.py index 473e223a1..97aadb938 100644 --- a/webapp_frontscreen.py +++ b/webapp_frontscreen.py @@ -29,7 +29,8 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, projectVersion: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Shows posts on the front screen of a news instance These should only be public blog posts from the features timeline which is the blog timeline of the news actor @@ -69,6 +70,7 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr @@ -91,6 +93,7 @@ def htmlFrontScreen(rssIconAtTop: bool, showPublishedDateOnly: bool, newswire: {}, theme: str, peertubeInstances: [], + allowLocalNetworkAccess: bool, extraJson=None, pageNumber=None, maxItemsPerPage=None) -> str: """Show the news instance front screen @@ -155,7 +158,8 @@ def htmlFrontScreen(rssIconAtTop: bool, projectVersion, YTReplacementDomain, showPublishedDateOnly, - peertubeInstances) + licenseStr + peertubeInstances, + allowLocalNetworkAccess) + licenseStr # Footer which is only used for system accounts profileFooterStr = ' \n' diff --git a/webapp_moderation.py b/webapp_moderation.py index 0195f1c64..27140ec23 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -42,7 +42,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, moderationActionStr: str, - theme: str, peertubeInstances: []) -> str: + theme: str, peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the moderation feed as html This is what you see when selecting the "mod" timeline """ @@ -57,7 +58,7 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, moderationActionStr, theme, - peertubeInstances) + peertubeInstances, allowLocalNetworkAccess) def htmlAccountInfo(cssCache: {}, translate: {}, diff --git a/webapp_post.py b/webapp_post.py index ee2eab64f..52b5d2f52 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -1081,6 +1081,7 @@ def individualPostAsHtml(allowDownloads: bool, boxName: str, YTReplacementDomain: str, showPublishedDateOnly: bool, peertubeInstances: [], + allowLocalNetworkAccess: bool, showRepeats=True, showIcons=False, manuallyApprovesFollowers=False, @@ -1231,7 +1232,8 @@ def individualPostAsHtml(allowDownloads: bool, downloadAnnounce(session, baseDir, httpPrefix, nickname, domain, postJsonObject, projectVersion, translate, - YTReplacementDomain) + YTReplacementDomain, + allowLocalNetworkAccess) if not postJsonAnnounce: return '' postJsonObject = postJsonAnnounce @@ -1605,7 +1607,8 @@ def htmlIndividualPost(cssCache: {}, projectVersion: str, likedBy: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show an individual post as html """ postStr = '' @@ -1646,6 +1649,7 @@ def htmlIndividualPost(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, authorized, False, False, False) messageId = removeIdEnding(postJsonObject['id']) @@ -1672,6 +1676,7 @@ def htmlIndividualPost(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, authorized, False, False, False) + postStr @@ -1701,6 +1706,7 @@ def htmlIndividualPost(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, authorized, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' @@ -1721,7 +1727,8 @@ def htmlPostReplies(cssCache: {}, httpPrefix: str, projectVersion: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the replies to an individual post as html """ repliesStr = '' @@ -1739,6 +1746,7 @@ def htmlPostReplies(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, False, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' diff --git a/webapp_profile.py b/webapp_profile.py index a439d38d8..91c4a7906 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -63,7 +63,8 @@ def htmlProfileAfterSearch(cssCache: {}, YTReplacementDomain: str, showPublishedDateOnly: bool, defaultTimeline: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show a profile page after a search for a fediverse address """ if hasUsersPath(profileHandle) or '/@' in profileHandle: @@ -292,7 +293,7 @@ def htmlProfileAfterSearch(cssCache: {}, httpPrefix, projectVersion, 'inbox', YTReplacementDomain, showPublishedDateOnly, - peertubeInstances, + peertubeInstances, allowLocalNetworkAccess, False, False, False, False, False) i += 1 if i >= 20: @@ -468,6 +469,7 @@ def htmlProfile(rssIconAtTop: bool, showPublishedDateOnly: bool, newswire: {}, theme: str, dormantMonths: int, peertubeInstances: [], + allowLocalNetworkAccess: bool, extraJson=None, pageNumber=None, maxItemsPerPage=None) -> str: """Show the profile page as html @@ -487,6 +489,7 @@ def htmlProfile(rssIconAtTop: bool, YTReplacementDomain, showPublishedDateOnly, newswire, theme, extraJson, + allowLocalNetworkAccess, pageNumber, maxItemsPerPage) domain, port = getDomainFromActor(profileJson['id']) @@ -756,7 +759,8 @@ def htmlProfile(rssIconAtTop: bool, projectVersion, YTReplacementDomain, showPublishedDateOnly, - peertubeInstances) + licenseStr + peertubeInstances, + allowLocalNetworkAccess) + licenseStr elif selected == 'following': profileStr += \ _htmlProfileFollowing(translate, baseDir, httpPrefix, @@ -805,7 +809,8 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, projectVersion: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Shows posts on the profile screen These should only be public posts """ @@ -844,6 +849,7 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr diff --git a/webapp_search.py b/webapp_search.py index 858cedec5..a574cb31b 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -520,7 +520,8 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, port: int, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show a page containing search results for your post history """ if historysearch.startswith('!'): @@ -596,6 +597,7 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, showIndividualPostIcons, showIndividualPostIcons, False, False, False) @@ -617,7 +619,8 @@ def htmlHashtagSearch(cssCache: {}, httpPrefix: str, projectVersion: str, YTReplacementDomain: str, showPublishedDateOnly: bool, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show a page containing search results for a hashtag """ if hashtag.startswith('#'): @@ -766,6 +769,7 @@ def htmlHashtagSearch(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, showRepeats, showIcons, manuallyApprovesFollowers, showPublicOnly, diff --git a/webapp_timeline.py b/webapp_timeline.py index 21c029e7b..c14d7c805 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -63,7 +63,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, authorized: bool, moderationActionStr: str, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the timeline as html """ enableTimingLog = False @@ -574,6 +575,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, + allowLocalNetworkAccess, boxName != 'dm', showIndividualPostIcons, manuallyApproveFollowers, @@ -730,7 +732,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the shares timeline as html """ manuallyApproveFollowers = \ @@ -750,7 +753,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInbox(cssCache: {}, defaultTimeline: str, @@ -770,7 +774,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the inbox as html """ manuallyApproveFollowers = \ @@ -790,7 +795,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlBookmarks(cssCache: {}, defaultTimeline: str, @@ -810,7 +816,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the bookmarks as html """ manuallyApproveFollowers = \ @@ -830,7 +837,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlEvents(cssCache: {}, defaultTimeline: str, @@ -850,7 +858,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the events as html """ manuallyApproveFollowers = \ @@ -870,7 +879,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxDMs(cssCache: {}, defaultTimeline: str, @@ -890,7 +900,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the DM timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -905,7 +916,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxReplies(cssCache: {}, defaultTimeline: str, @@ -925,7 +937,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the replies timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -941,7 +954,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxMedia(cssCache: {}, defaultTimeline: str, @@ -961,7 +975,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the media timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -977,7 +992,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, @@ -997,7 +1013,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the blogs timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1013,7 +1030,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, @@ -1034,7 +1052,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the features timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1050,7 +1069,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlInboxNews(cssCache: {}, defaultTimeline: str, @@ -1070,7 +1090,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the news timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1086,7 +1107,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) def htmlOutbox(cssCache: {}, defaultTimeline: str, @@ -1106,7 +1128,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + allowLocalNetworkAccess: bool) -> str: """Show the Outbox as html """ manuallyApproveFollowers = \ @@ -1123,4 +1146,5 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, newswire, False, False, positiveVoting, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, - authorized, None, theme, peertubeInstances) + authorized, None, theme, peertubeInstances, + allowLocalNetworkAccess) From 5c5b715bbe7fef97c4e8f8540da60fb9fb924557 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 11:59:26 +0000 Subject: [PATCH 08/50] Tidying --- posts.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/posts.py b/posts.py index 73e16d236..f80b2a919 100644 --- a/posts.py +++ b/posts.py @@ -3944,14 +3944,19 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str, if dangerousMarkup(contentStr, allowLocalNetworkAccess): _rejectAnnounce(announceFilename) return None + if isFiltered(baseDir, nickname, domain, contentStr): _rejectAnnounce(announceFilename) return None + # remove any long words - announcedJson['content'] = removeLongWords(contentStr, 40, []) + contentStr = removeLongWords(contentStr, 40, []) # remove text formatting, such as bold/italics - announcedJson['content'] = removeTextFormatting(contentStr) + contentStr = removeTextFormatting(contentStr) + + # set the content after santitization + announcedJson['content'] = contentStr # wrap in create to be consistent with other posts announcedJson = \ From 9950f42c86bd3af37b191d8d76124ed1ce127e65 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 12:48:08 +0000 Subject: [PATCH 09/50] Tidying --- posts.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/posts.py b/posts.py index f80b2a919..5c976a20f 100644 --- a/posts.py +++ b/posts.py @@ -3915,10 +3915,7 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str, if '/statuses/' not in announcedJson['id']: _rejectAnnounce(announceFilename) return None - if '/users/' not in announcedJson['id'] and \ - '/accounts/' not in announcedJson['id'] and \ - '/channel/' not in announcedJson['id'] and \ - '/profile/' not in announcedJson['id']: + if not hasUsersPath(announcedJson['id']): _rejectAnnounce(announceFilename) return None if not announcedJson.get('type'): From 0c0706ef83c9acd95134bc7aeb2cb5daba9ff59e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 13:40:42 +0000 Subject: [PATCH 10/50] Top margin of left column --- epicyon-profile.css | 2 ++ theme/purple/theme.json | 1 + 2 files changed, 3 insertions(+) diff --git a/epicyon-profile.css b/epicyon-profile.css index 0d1212795..636f382af 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -96,6 +96,7 @@ --column-right-width: 10vw; --column-left-mobile-margin: 2%; --column-left-top-margin: 0; + --column-right-top-margin: 0; --column-left-header-style: uppercase; --column-left-header-background: #555; --column-left-header-color: #fff; @@ -1133,6 +1134,7 @@ div.container { overflow: hidden; } .col-right { + margin-top: var(--column-right-top-margin); border: var(--column-right-border-width) solid var(--column-left-border-color); background-color: var(--column-left-color); color: var(--column-left-fg-color); diff --git a/theme/purple/theme.json b/theme/purple/theme.json index 00fb693d2..3f38346c3 100644 --- a/theme/purple/theme.json +++ b/theme/purple/theme.json @@ -1,4 +1,5 @@ { + "column-left-top-margin": "12px", "time-vertical-align": "0%", "time-vertical-align-mobile": "1.5%", "post-separator-margin-top": "10px", From 53961bc2d003174d67e65ed0d2a0d3bcfdee1f5a Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 13:44:51 +0000 Subject: [PATCH 11/50] Right column top margin --- epicyon-profile.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index 636f382af..f97f70677 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -1134,7 +1134,6 @@ div.container { overflow: hidden; } .col-right { - margin-top: var(--column-right-top-margin); border: var(--column-right-border-width) solid var(--column-left-border-color); background-color: var(--column-left-color); color: var(--column-left-fg-color); @@ -1158,7 +1157,7 @@ div.container { .col-right img.rightColImg { background: var(--column-left-color); width: 100%; - margin: 0 0; + margin-top: var(--column-right-top-margin); padding: 0 0; } .likesCount { From d1e793a847c034d57dca3fd9eaf2b969f2cb53ac Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 14:05:29 +0000 Subject: [PATCH 12/50] Column top margins --- theme/purple/theme.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/theme/purple/theme.json b/theme/purple/theme.json index 3f38346c3..3a1e8582d 100644 --- a/theme/purple/theme.json +++ b/theme/purple/theme.json @@ -1,5 +1,6 @@ { - "column-left-top-margin": "12px", + "column-left-top-margin": "0.4cm", + "column-right-top-margin": "0.8cm", "time-vertical-align": "0%", "time-vertical-align-mobile": "1.5%", "post-separator-margin-top": "10px", From 658ff4a44fb90c4770bee62814a292305c0acf11 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 30 Jan 2021 23:37:34 +0000 Subject: [PATCH 13/50] Double quotes --- deploy/onion | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deploy/onion b/deploy/onion index cf277b4e6..e3bd85d22 100755 --- a/deploy/onion +++ b/deploy/onion @@ -79,6 +79,7 @@ if [ ! -d /etc/torrc.d ]; then fi if ! grep -q '%include /etc/torrc.d' /etc/tor/torrc; then echo '%include /etc/torrc.d' >> /etc/tor/torrc + systemctl restart tor fi if [ ! -f /etc/torrc.d/epicyon ]; then @@ -257,7 +258,7 @@ echo "Creating nginx virtual host for ${ONION_DOMAIN}" echo ' index index.html;'; echo ''; echo ' location /newsmirror {'; - echo ' root /var/www/${ONION_DOMAIN}/htdocs;'; + echo " root /var/www/${ONION_DOMAIN}/htdocs;"; echo ' try_files $uri =404;'; echo ' }'; echo ''; From 8cdcc92763358f84d8f836cc0bc4bb7c28bb330b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 31 Jan 2021 10:48:21 +0000 Subject: [PATCH 14/50] Comment out debug --- webapp_utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp_utils.py b/webapp_utils.py index 5b7bf67e9..ae8b810bd 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -591,24 +591,24 @@ def addEmojiToDisplayName(baseDir: str, httpPrefix: str, displayName = displayName.replace('

', '').replace('

', '') emojiTags = {} - print('TAG: displayName before tags: ' + displayName) +# print('TAG: displayName before tags: ' + displayName) displayName = \ addHtmlTags(baseDir, httpPrefix, nickname, domain, displayName, [], emojiTags) displayName = displayName.replace('

', '').replace('

', '') - print('TAG: displayName after tags: ' + displayName) +# print('TAG: displayName after tags: ' + displayName) # convert the emoji dictionary to a list emojiTagsList = [] for tagName, tag in emojiTags.items(): emojiTagsList.append(tag) - print('TAG: emoji tags list: ' + str(emojiTagsList)) +# print('TAG: emoji tags list: ' + str(emojiTagsList)) if not inProfileName: displayName = \ replaceEmojiFromTags(displayName, emojiTagsList, 'post header') else: displayName = \ replaceEmojiFromTags(displayName, emojiTagsList, 'profile') - print('TAG: displayName after tags 2: ' + displayName) +# print('TAG: displayName after tags 2: ' + displayName) # remove any stray emoji while ':' in displayName: @@ -619,8 +619,8 @@ def addEmojiToDisplayName(baseDir: str, httpPrefix: str, displayName = displayName.replace(':' + emojiStr + ':', '').strip() if prevDisplayName == displayName: break - print('TAG: displayName after tags 3: ' + displayName) - print('TAG: displayName after tag replacements: ' + displayName) +# print('TAG: displayName after tags 3: ' + displayName) +# print('TAG: displayName after tag replacements: ' + displayName) return displayName From 8bbd9b617301e3b083c9c050b9453c9dadfe8d2d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 31 Jan 2021 11:05:17 +0000 Subject: [PATCH 15/50] Check for dangerous markup in display name and clearly indicate adversaries --- content.py | 33 +-------------------------------- daemon.py | 2 +- inbox.py | 2 +- newsdaemon.py | 2 +- outbox.py | 2 +- posts.py | 6 ++++-- tests.py | 2 +- utils.py | 42 +++++++++++++++++++++++++++++++++++++++--- 8 files changed, 49 insertions(+), 42 deletions(-) diff --git a/content.py b/content.py index 28a2ac531..4f20267e8 100644 --- a/content.py +++ b/content.py @@ -14,6 +14,7 @@ from utils import getImageExtensions from utils import loadJson from utils import fileLastModified from utils import getLinkPrefixes +from utils import dangerousMarkup from petnames import getPetName @@ -154,38 +155,6 @@ def htmlReplaceQuoteMarks(content: str) -> str: return newContent -def dangerousMarkup(content: str, allowLocalNetworkAccess: bool) -> bool: - """Returns true if the given content contains dangerous html markup - """ - if '<' not in content: - return False - if '>' not in content: - return False - contentSections = content.split('<') - invalidPartials = () - if not allowLocalNetworkAccess: - invalidPartials = ('localhost', '127.0.', '192.168', '10.0.') - invalidStrings = ('script', 'canvas', 'style', 'abbr', - 'frame', 'iframe', 'html', 'body', - 'hr', 'allow-popups', 'allow-scripts') - for markup in contentSections: - if '>' not in markup: - continue - markup = markup.split('>')[0].strip() - for partialMatch in invalidPartials: - if partialMatch in markup: - return True - if ' ' not in markup: - for badStr in invalidStrings: - if badStr in markup: - return True - else: - for badStr in invalidStrings: - if badStr + ' ' in markup: - return True - return False - - def dangerousCSS(filename: str, allowLocalNetworkAccess: bool) -> bool: """Returns true is the css file contains code which can create security problems diff --git a/daemon.py b/daemon.py index 03b84ca40..6994b8515 100644 --- a/daemon.py +++ b/daemon.py @@ -217,10 +217,10 @@ from utils import urlPermitted from utils import loadJson from utils import saveJson from utils import isSuspended +from utils import dangerousMarkup from manualapprove import manualDenyFollowRequest from manualapprove import manualApproveFollowRequest from announce import createAnnounce -from content import dangerousMarkup from content import replaceEmojiFromTags from content import addHtmlTags from content import extractMediaInFormPOST diff --git a/inbox.py b/inbox.py index 1dbf18af1..c213e0d22 100644 --- a/inbox.py +++ b/inbox.py @@ -54,6 +54,7 @@ from blocking import isBlockedDomain from filters import isFiltered from utils import updateAnnounceCollection from utils import undoAnnounceCollectionEntry +from utils import dangerousMarkup from httpsig import messageContentDigest from posts import validContentWarning from posts import downloadAnnounce @@ -69,7 +70,6 @@ from media import replaceYouTube from git import isGitPatch from git import receiveGitPatch from followingCalendar import receivingCalendarEvents -from content import dangerousMarkup from happening import saveEventPost from delete import removeOldHashtags from follow import isFollowingActor diff --git a/newsdaemon.py b/newsdaemon.py index 0a6a8f5cc..84f2f4bc4 100644 --- a/newsdaemon.py +++ b/newsdaemon.py @@ -23,7 +23,6 @@ from newswire import getDictFromNewswire # from posts import sendSignedJson from posts import createNewsPost from posts import archivePostsForPerson -from content import dangerousMarkup from content import validHashTag from utils import removeHtml from utils import getFullDomain @@ -31,6 +30,7 @@ from utils import loadJson from utils import saveJson from utils import getStatusNumber from utils import clearFromPostCaches +from utils import dangerousMarkup from inbox import storeHashTags from session import createSession diff --git a/outbox.py b/outbox.py index ce0bf15d9..e50000386 100644 --- a/outbox.py +++ b/outbox.py @@ -17,6 +17,7 @@ from posts import sendToNamedAddresses from utils import getFullDomain from utils import removeIdEnding from utils import getDomainFromActor +from utils import dangerousMarkup from blocking import isBlockedDomain from blocking import outboxBlock from blocking import outboxUndoBlock @@ -36,7 +37,6 @@ from bookmarks import outboxUndoBookmark from delete import outboxDelete from shares import outboxShareUpload from shares import outboxUndoShareUpload -from content import dangerousMarkup def postMessageToOutbox(messageJson: {}, postToNickname: str, diff --git a/posts.py b/posts.py index 5c976a20f..eeaecbbe4 100644 --- a/posts.py +++ b/posts.py @@ -55,9 +55,9 @@ from utils import locateNewsVotes from utils import locateNewsArrival from utils import votesOnNewswireItem from utils import removeHtml +from utils import dangerousMarkup from media import attachMedia from media import replaceYouTube -from content import dangerousMarkup from content import tagExists from content import removeLongWords from content import addHtmlTags @@ -292,7 +292,9 @@ def getPersonBox(baseDir: str, session, wfRequest: {}, avatarUrl = personJson['icon']['url'] displayName = None if personJson.get('name'): - displayName = removeHtml(personJson['name']) + displayName = personJson['name'] + if dangerousMarkup(personJson['name'], False): + displayName = '*ADVERSARY*' # have they moved? if personJson.get('movedTo'): displayName += ' ⌂' diff --git a/tests.py b/tests.py index f2ef8b22d..3ff5eb714 100644 --- a/tests.py +++ b/tests.py @@ -49,6 +49,7 @@ from utils import saveJson from utils import getStatusNumber from utils import getFollowersOfPerson from utils import removeHtml +from utils import dangerousMarkup from follow import followerOfPerson from follow import unfollowAccount from follow import unfollowerOfAccount @@ -77,7 +78,6 @@ from inbox import validInboxFilenames from categories import guessHashtagCategory from content import htmlReplaceEmailQuote from content import htmlReplaceQuoteMarks -from content import dangerousMarkup from content import dangerousCSS from content import addWebLinks from content import replaceEmojiFromTags diff --git a/utils.py b/utils.py index 76e02f8ac..df27780b3 100644 --- a/utils.py +++ b/utils.py @@ -554,6 +554,38 @@ def urlPermitted(url: str, federationList: []): return False +def dangerousMarkup(content: str, allowLocalNetworkAccess: bool) -> bool: + """Returns true if the given content contains dangerous html markup + """ + if '<' not in content: + return False + if '>' not in content: + return False + contentSections = content.split('<') + invalidPartials = () + if not allowLocalNetworkAccess: + invalidPartials = ('localhost', '127.0.', '192.168', '10.0.') + invalidStrings = ('script', 'canvas', 'style', 'abbr', + 'frame', 'iframe', 'html', 'body', + 'hr', 'allow-popups', 'allow-scripts') + for markup in contentSections: + if '>' not in markup: + continue + markup = markup.split('>')[0].strip() + for partialMatch in invalidPartials: + if partialMatch in markup: + return True + if ' ' not in markup: + for badStr in invalidStrings: + if badStr in markup: + return True + else: + for badStr in invalidStrings: + if badStr + ' ' in markup: + return True + return False + + def getDisplayName(baseDir: str, actor: str, personCache: {}) -> str: """Returns the display name for the given actor """ @@ -561,9 +593,10 @@ def getDisplayName(baseDir: str, actor: str, personCache: {}) -> str: actor = actor.split('/statuses/')[0] if not personCache.get(actor): return None + nameFound = None if personCache[actor].get('actor'): if personCache[actor]['actor'].get('name'): - return personCache[actor]['actor']['name'] + nameFound = personCache[actor]['actor']['name'] else: # Try to obtain from the cached actors cachedActorFilename = \ @@ -572,8 +605,11 @@ def getDisplayName(baseDir: str, actor: str, personCache: {}) -> str: actorJson = loadJson(cachedActorFilename, 1) if actorJson: if actorJson.get('name'): - return(actorJson['name']) - return None + nameFound = actorJson['name'] + if nameFound: + if dangerousMarkup(nameFound, False): + nameFound = "*ADVERSARY*" + return nameFound def getNicknameFromActor(actor: str) -> str: From 00b7cf430f40544ff07b0b0b3c804b8428e6690c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 31 Jan 2021 11:22:19 +0000 Subject: [PATCH 16/50] Apply filters to display name lookups --- posts.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/posts.py b/posts.py index eeaecbbe4..8cbcede47 100644 --- a/posts.py +++ b/posts.py @@ -295,6 +295,10 @@ def getPersonBox(baseDir: str, session, wfRequest: {}, displayName = personJson['name'] if dangerousMarkup(personJson['name'], False): displayName = '*ADVERSARY*' + elif isFiltered(baseDir, + nickname, domain, + displayName): + displayName = '*FILTERED*' # have they moved? if personJson.get('movedTo'): displayName += ' ⌂' From 6d2ecf32ffe6dec6eb90bf6be63c11ebe97850a3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 31 Jan 2021 22:01:02 +0000 Subject: [PATCH 17/50] Replace the tor daemon on debian --- deploy/onion | 81 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/deploy/onion b/deploy/onion index e3bd85d22..2cd2bcf5f 100755 --- a/deploy/onion +++ b/deploy/onion @@ -16,10 +16,10 @@ if [[ "$1" == 'remove' ]]; then rm "/etc/nginx/sites-availale/${username}" rm -rf ${install_destination} if [ -d /var/www/cache ]; then - rm -rf /var/www/cache + rm -rf /var/www/cache fi if [ -d /srv/http/cache ]; then - rm -rf /srv/http/cache + rm -rf /srv/http/cache fi userdel -r ${username} echo 'Epicyon onion instance removed' @@ -37,18 +37,35 @@ if [ -f /usr/bin/pacman ]; then pacman -Syy pacman -S --noconfirm tor python-pip python-pysocks python-pycryptodome \ imagemagick python-pillow python-requests \ - perl-image-exiftool python-numpy python-dateutil \ - certbot flake8 git qrencode bandit + perl-image-exiftool python-numpy python-dateutil \ + certbot flake8 git qrencode bandit pip3 install pyLD pyqrcode pypng else apt-get update apt-get -y install imagemagick python3-crypto python3-pycryptodome \ - python3-dateutil python3-idna python3-requests \ - python3-numpy python3-pil.imagetk python3-pip \ - python3-setuptools python3-socks python3-idna \ - libimage-exiftool-perl python3-flake8 python3-pyld \ - python3-django-timezone-field tor nginx git qrencode \ - python3-pyqrcode python3-png python3-bandit + python3-dateutil python3-idna python3-requests \ + python3-numpy python3-pil.imagetk python3-pip \ + python3-setuptools python3-socks python3-idna \ + libimage-exiftool-perl python3-flake8 python3-pyld \ + python3-django-timezone-field tor nginx git qrencode \ + python3-pyqrcode python3-png python3-bandit +fi + +if [[ "$(uname -a)" == *'Debian'* ]]; then + echo 'Fixing the tor daemon' + { echo '[Unit]'; + echo 'Description=Anonymizing overlay network for TCP (multi-instance-master)'; + echo ''; + echo '[Service]'; + echo 'Type=simple'; + echo 'User=root'; + echo 'Group=debian-tor'; + echo 'ExecStart=/usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0'; + echo ''; + echo '[Install]'; + echo 'WantedBy=multi-user.target'; } > /lib/systemd/system/tor.service + systemctl daemon-reload + systemctl restart tor fi echo 'Cloning the epicyon repo' @@ -56,8 +73,8 @@ if [ ! -d ${install_destination} ]; then git clone https://gitlab.com/bashrc2/epicyon ${install_destination} if [ ! -d ${install_destination} ]; then - echo 'Epicyon repo failed to clone' - exit 3 + echo 'Epicyon repo failed to clone' + exit 3 fi fi @@ -186,7 +203,7 @@ if [ ! -f /etc/nginx/nginx.conf ]; then echo '}'; } > /etc/nginx/nginx.conf else if ! grep -q 'include /etc/nginx/sites-enabled' /etc/nginx/nginx.conf; then - echo 'include /etc/nginx/sites-enabled/*.conf;' >> /etc/nginx/nginx.conf + echo 'include /etc/nginx/sites-enabled/*.conf;' >> /etc/nginx/nginx.conf fi fi if [ ! -d /etc/nginx/conf.d ]; then @@ -201,25 +218,25 @@ fi if [ -f /usr/bin/pacman ]; then if [ ! -f /lib/systemd/system/nginx.service ]; then - echo 'Creating nginx daemon' - { echo '[Unit]'; - echo 'Description=A high performance web server and a reverse proxy server'; - echo 'Documentation=man:nginx(8)'; - echo 'After=network.target nss-lookup.target'; - echo '' - echo '[Service]'; - echo 'Type=forking'; - echo 'PIDFile=/run/nginx.pid'; - echo "ExecStartPre=$(which nginx) -t -q -g 'daemon on; master_process on;'"; - echo "ExecStart=$(which nginx) -g 'daemon on; master_process on;'"; - echo "ExecReload=$(which nginx) -g 'daemon on; master_process on;' -s reload"; - echo 'ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid'; - echo 'TimeoutStopSec=5'; - echo 'KillMode=mixed'; - echo ''; - echo '[Install]'; - echo 'WantedBy=multi-user.target'; } > /etc/systemd/system/nginx.service - systemctl enable nginx + echo 'Creating nginx daemon' + { echo '[Unit]'; + echo 'Description=A high performance web server and a reverse proxy server'; + echo 'Documentation=man:nginx(8)'; + echo 'After=network.target nss-lookup.target'; + echo '' + echo '[Service]'; + echo 'Type=forking'; + echo 'PIDFile=/run/nginx.pid'; + echo "ExecStartPre=$(which nginx) -t -q -g 'daemon on; master_process on;'"; + echo "ExecStart=$(which nginx) -g 'daemon on; master_process on;'"; + echo "ExecReload=$(which nginx) -g 'daemon on; master_process on;' -s reload"; + echo 'ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid'; + echo 'TimeoutStopSec=5'; + echo 'KillMode=mixed'; + echo ''; + echo '[Install]'; + echo 'WantedBy=multi-user.target'; } > /etc/systemd/system/nginx.service + systemctl enable nginx fi fi From 6bb884795257ebd6ef4b6da28bdc4cd2c19f7af3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 31 Jan 2021 22:04:22 +0000 Subject: [PATCH 18/50] Keep a copy of tor daemon --- deploy/onion | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/onion b/deploy/onion index 2cd2bcf5f..ea99ffea4 100755 --- a/deploy/onion +++ b/deploy/onion @@ -64,6 +64,7 @@ if [[ "$(uname -a)" == *'Debian'* ]]; then echo ''; echo '[Install]'; echo 'WantedBy=multi-user.target'; } > /lib/systemd/system/tor.service + cp /lib/systemd/system/tor.service /root/tor.service systemctl daemon-reload systemctl restart tor fi From b6ad1895c63186ae3557fa3d9aa2272c115145a7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 12:47:34 +0000 Subject: [PATCH 19/50] Keyboard navigation in shell browsers: skip to the main timeline --- translations/ar.json | 3 ++- translations/ca.json | 3 ++- translations/cy.json | 3 ++- translations/de.json | 3 ++- translations/en.json | 3 ++- translations/es.json | 3 ++- translations/fr.json | 3 ++- translations/ga.json | 3 ++- translations/hi.json | 3 ++- translations/it.json | 3 ++- translations/ja.json | 3 ++- translations/oc.json | 3 ++- translations/pt.json | 3 ++- translations/ru.json | 3 ++- translations/zh.json | 3 ++- webapp_timeline.py | 16 ++++++++++++---- 16 files changed, 42 insertions(+), 19 deletions(-) diff --git a/translations/ar.json b/translations/ar.json index 14c244723..781a839e9 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -363,5 +363,6 @@ "Other accounts": "حسابات أخرى", "Pin this post to your profile.": "تثبيت هذه الوظيفة في ملف التعريف الخاص بك.", "Administered by": "تدار من قبل", - "Version": "الإصدار" + "Version": "الإصدار", + "Skip to timeline": "تخطي إلى الجدول الزمني" } diff --git a/translations/ca.json b/translations/ca.json index 5eb0f01d3..584cda0ff 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -363,5 +363,6 @@ "Other accounts": "Altres comptes", "Pin this post to your profile.": "Fixa aquesta publicació al teu perfil.", "Administered by": "Administrat per", - "Version": "Versió" + "Version": "Versió", + "Skip to timeline": "Ves a la cronologia" } diff --git a/translations/cy.json b/translations/cy.json index 500106838..513477314 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -363,5 +363,6 @@ "Other accounts": "Cyfrifon eraill", "Pin this post to your profile.": "Piniwch y post hwn i'ch proffil.", "Administered by": "Gweinyddir gan", - "Version": "Fersiwn" + "Version": "Fersiwn", + "Skip to timeline": "Neidio i'r llinell amser" } diff --git a/translations/de.json b/translations/de.json index 6da6054c0..c1676aa44 100644 --- a/translations/de.json +++ b/translations/de.json @@ -363,5 +363,6 @@ "Other accounts": "Andere Konten", "Pin this post to your profile.": "Pin diesen Beitrag zu Ihrem Profil.", "Administered by": "Verwaltet von", - "Version": "Ausführung" + "Version": "Ausführung", + "Skip to timeline": "Zur Zeitleiste springen" } diff --git a/translations/en.json b/translations/en.json index 58c97cf3f..8031e0dff 100644 --- a/translations/en.json +++ b/translations/en.json @@ -363,5 +363,6 @@ "Other accounts": "Other accounts", "Pin this post to your profile.": "Pin this post to your profile.", "Administered by": "Administered by", - "Version": "Version" + "Version": "Version", + "Skip to timeline": "Skip to timeline" } diff --git a/translations/es.json b/translations/es.json index ef064cfc4..0908aceb6 100644 --- a/translations/es.json +++ b/translations/es.json @@ -363,5 +363,6 @@ "Other accounts": "Otras cuentas", "Pin this post to your profile.": "Fija esta publicación a tu perfil.", "Administered by": "Administrado por", - "Version": "Versión" + "Version": "Versión", + "Skip to timeline": "Saltar a la línea de tiempo" } diff --git a/translations/fr.json b/translations/fr.json index 6c28048fc..1d03c45e8 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -363,5 +363,6 @@ "Other accounts": "Autres comptes", "Pin this post to your profile.": "Épinglez ce message à votre profil.", "Administered by": "Administré par", - "Version": "Version" + "Version": "Version", + "Skip to timeline": "Passer à la chronologie" } diff --git a/translations/ga.json b/translations/ga.json index 187295784..638ec6488 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -363,5 +363,6 @@ "Other accounts": "Cuntais eile", "Pin this post to your profile.": "Bioráin an post seo le do phróifíl.", "Administered by": "Riartha ag", - "Version": "Leagan" + "Version": "Leagan", + "Skip to timeline": "Scipeáil chuig an amlíne" } diff --git a/translations/hi.json b/translations/hi.json index 0481275c3..16d411c09 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -363,5 +363,6 @@ "Other accounts": "अन्य खाते", "Pin this post to your profile.": "इस पोस्ट को अपनी प्रोफाइल पर पिन करें।", "Administered by": "द्वारा प्रशासित", - "Version": "संस्करण" + "Version": "संस्करण", + "Skip to timeline": "टाइमलाइन पर जाएं" } diff --git a/translations/it.json b/translations/it.json index 255998ad9..ae911ebdb 100644 --- a/translations/it.json +++ b/translations/it.json @@ -363,5 +363,6 @@ "Other accounts": "Altri account", "Pin this post to your profile.": "Metti questo post sul tuo profilo.", "Administered by": "Amministrato da", - "Version": "Versione" + "Version": "Versione", + "Skip to timeline": "Passa alla sequenza temporale" } diff --git a/translations/ja.json b/translations/ja.json index 838169403..e2063b2f2 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -363,5 +363,6 @@ "Other accounts": "その他のアカウント", "Pin this post to your profile.": "この投稿をプロフィールに固定します。", "Administered by": "管理者", - "Version": "バージョン" + "Version": "バージョン", + "Skip to timeline": "タイムラインにスキップ" } diff --git a/translations/oc.json b/translations/oc.json index e6b8813f8..390c12cc3 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -359,5 +359,6 @@ "Other accounts": "Other accounts", "Pin this post to your profile.": "Pin this post to your profile.", "Administered by": "Administered by", - "Version": "Version" + "Version": "Version", + "Skip to timeline": "Skip to timeline" } diff --git a/translations/pt.json b/translations/pt.json index 192d0de42..efa3f9560 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -363,5 +363,6 @@ "Other accounts": "Outras contas", "Pin this post to your profile.": "Fixar esta postagem em seu perfil.", "Administered by": "Administrado por", - "Version": "Versão" + "Version": "Versão", + "Skip to timeline": "Pular para a linha do tempo" } diff --git a/translations/ru.json b/translations/ru.json index bec84afb1..be0241b5f 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -363,5 +363,6 @@ "Other accounts": "Другие аккаунты", "Pin this post to your profile.": "Закрепите это сообщение в своем профиле.", "Administered by": "Под управлением", - "Version": "Версия" + "Version": "Версия", + "Skip to timeline": "Перейти к временной шкале" } diff --git a/translations/zh.json b/translations/zh.json index aa6a65f7c..dc47ef147 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -363,5 +363,6 @@ "Other accounts": "其他账户", "Pin this post to your profile.": "将此帖子固定到您的个人资料。", "Administered by": "由...管理", - "Version": "版" + "Version": "版", + "Skip to timeline": "跳到时间线" } diff --git a/webapp_timeline.py b/webapp_timeline.py index c14d7c805..47344aacb 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -363,12 +363,18 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '' - # This creates a link to the profile page when viewed - # in lynx, but should be invisible in a graphical web browser + # This creates a link to skip to the timeline and change to + # profile view when accessed within lynx, but should be + # invisible in a graphical web browser tlStr += \ - '
' + \ + '
\n' # banner and row of buttons tlStr += \ @@ -418,6 +424,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, leftColumnStr + ' \n' # center column containing posts tlStr += ' \n' + tlStr += '
\n' if not fullWidthTimelineButtonHeader: tlStr += \ @@ -618,6 +625,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, showPublishAsIcon, rssIconAtTop, publishButtonAtTop, authorized, True, theme) + tlStr += '
\n' tlStr += ' ' + \ rightColumnStr + ' \n' tlStr += ' \n' From cf3542df8c56c0d153cf7b3c560ae83ae723cd00 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 13:02:10 +0000 Subject: [PATCH 20/50] Space --- webapp_timeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index 47344aacb..8640df19e 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -370,7 +370,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '
' + \ '' + \ + translate['Skip to timeline'] + ' ' + \ '' + \ From 1af0949f5a81daaf61bc0e6d82ce283053fce88e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 13:02:33 +0000 Subject: [PATCH 21/50] Separator --- webapp_timeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index 8640df19e..5df33749b 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -370,7 +370,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '
' + \ ' ' + \ + translate['Skip to timeline'] + ' | ' + \ '' + \ From ebfaa94c0fb546de0cdf9f01bc7a54cb955fe4ff Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 13:31:49 +0000 Subject: [PATCH 22/50] Skip links to left and right columns --- translations/ar.json | 4 +++- translations/ca.json | 4 +++- translations/cy.json | 4 +++- translations/de.json | 4 +++- translations/en.json | 4 +++- translations/es.json | 4 +++- translations/fr.json | 4 +++- translations/ga.json | 4 +++- translations/hi.json | 4 +++- translations/it.json | 4 +++- translations/ja.json | 4 +++- translations/oc.json | 4 +++- translations/pt.json | 4 +++- translations/ru.json | 4 +++- translations/zh.json | 4 +++- webapp_timeline.py | 12 ++++++++++-- 16 files changed, 55 insertions(+), 17 deletions(-) diff --git a/translations/ar.json b/translations/ar.json index 781a839e9..087f1bc9d 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "تثبيت هذه الوظيفة في ملف التعريف الخاص بك.", "Administered by": "تدار من قبل", "Version": "الإصدار", - "Skip to timeline": "تخطي إلى الجدول الزمني" + "Skip to timeline": "تخطي إلى الجدول الزمني", + "Skip to Newswire": "انتقل إلى Newswire", + "Skip to Links": "تخطي إلى روابط الويب" } diff --git a/translations/ca.json b/translations/ca.json index 584cda0ff..17b1414f4 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Fixa aquesta publicació al teu perfil.", "Administered by": "Administrat per", "Version": "Versió", - "Skip to timeline": "Ves a la cronologia" + "Skip to timeline": "Ves a la cronologia", + "Skip to Newswire": "Vés a Newswire", + "Skip to Links": "Vés als enllaços web" } diff --git a/translations/cy.json b/translations/cy.json index 513477314..26813ecc2 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Piniwch y post hwn i'ch proffil.", "Administered by": "Gweinyddir gan", "Version": "Fersiwn", - "Skip to timeline": "Neidio i'r llinell amser" + "Skip to timeline": "Neidio i'r llinell amser", + "Skip to Newswire": "Neidio i Newswire", + "Skip to Links": "Neidio i Dolenni Gwe" } diff --git a/translations/de.json b/translations/de.json index c1676aa44..cb0fa5c24 100644 --- a/translations/de.json +++ b/translations/de.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Pin diesen Beitrag zu Ihrem Profil.", "Administered by": "Verwaltet von", "Version": "Ausführung", - "Skip to timeline": "Zur Zeitleiste springen" + "Skip to timeline": "Zur Zeitleiste springen", + "Skip to Newswire": "Springe zu Newswire", + "Skip to Links": "Springe zu Weblinks" } diff --git a/translations/en.json b/translations/en.json index 8031e0dff..a79da2fe1 100644 --- a/translations/en.json +++ b/translations/en.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Pin this post to your profile.", "Administered by": "Administered by", "Version": "Version", - "Skip to timeline": "Skip to timeline" + "Skip to timeline": "Skip to timeline", + "Skip to Newswire": "Skip to Newswire", + "Skip to Links": "Skip to Links" } diff --git a/translations/es.json b/translations/es.json index 0908aceb6..602d20746 100644 --- a/translations/es.json +++ b/translations/es.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Fija esta publicación a tu perfil.", "Administered by": "Administrado por", "Version": "Versión", - "Skip to timeline": "Saltar a la línea de tiempo" + "Skip to timeline": "Saltar a la línea de tiempo", + "Skip to Newswire": "Saltar a Newswire", + "Skip to Links": "Saltar a enlaces web" } diff --git a/translations/fr.json b/translations/fr.json index 1d03c45e8..2506982e9 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Épinglez ce message à votre profil.", "Administered by": "Administré par", "Version": "Version", - "Skip to timeline": "Passer à la chronologie" + "Skip to timeline": "Passer à la chronologie", + "Skip to Newswire": "Passer à Newswire", + "Skip to Links": "Passer aux liens Web" } diff --git a/translations/ga.json b/translations/ga.json index 638ec6488..169fd5e3e 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Bioráin an post seo le do phróifíl.", "Administered by": "Riartha ag", "Version": "Leagan", - "Skip to timeline": "Scipeáil chuig an amlíne" + "Skip to timeline": "Scipeáil chuig an amlíne", + "Skip to Newswire": "Scipeáil chuig Newswire", + "Skip to Links": "Scipeáil chuig Naisc Ghréasáin" } diff --git a/translations/hi.json b/translations/hi.json index 16d411c09..def3d5d1f 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "इस पोस्ट को अपनी प्रोफाइल पर पिन करें।", "Administered by": "द्वारा प्रशासित", "Version": "संस्करण", - "Skip to timeline": "टाइमलाइन पर जाएं" + "Skip to timeline": "टाइमलाइन पर जाएं", + "Skip to Newswire": "Newswire पर जाएं", + "Skip to Links": "वेब लिंक पर जाएं" } diff --git a/translations/it.json b/translations/it.json index ae911ebdb..fc13ee792 100644 --- a/translations/it.json +++ b/translations/it.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Metti questo post sul tuo profilo.", "Administered by": "Amministrato da", "Version": "Versione", - "Skip to timeline": "Passa alla sequenza temporale" + "Skip to timeline": "Passa alla sequenza temporale", + "Skip to Newswire": "Passa a Newswire", + "Skip to Links": "Passa a collegamenti Web" } diff --git a/translations/ja.json b/translations/ja.json index e2063b2f2..e5de8f525 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "この投稿をプロフィールに固定します。", "Administered by": "管理者", "Version": "バージョン", - "Skip to timeline": "タイムラインにスキップ" + "Skip to timeline": "タイムラインにスキップ", + "Skip to Newswire": "Newswireにスキップ", + "Skip to Links": "Webリンクにスキップ" } diff --git a/translations/oc.json b/translations/oc.json index 390c12cc3..a6d62a6e0 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -360,5 +360,7 @@ "Pin this post to your profile.": "Pin this post to your profile.", "Administered by": "Administered by", "Version": "Version", - "Skip to timeline": "Skip to timeline" + "Skip to timeline": "Skip to timeline", + "Skip to Newswire": "Skip to Newswire", + "Skip to Links": "Skip to Links" } diff --git a/translations/pt.json b/translations/pt.json index efa3f9560..d0f485ca5 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Fixar esta postagem em seu perfil.", "Administered by": "Administrado por", "Version": "Versão", - "Skip to timeline": "Pular para a linha do tempo" + "Skip to timeline": "Pular para a linha do tempo", + "Skip to Newswire": "Pular para Newswire", + "Skip to Links": "Pular para links da web" } diff --git a/translations/ru.json b/translations/ru.json index be0241b5f..14eb8b5db 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "Закрепите это сообщение в своем профиле.", "Administered by": "Под управлением", "Version": "Версия", - "Skip to timeline": "Перейти к временной шкале" + "Skip to timeline": "Перейти к временной шкале", + "Skip to Newswire": "Перейти к ленте новостей", + "Skip to Links": "Перейти к веб-ссылкам" } diff --git a/translations/zh.json b/translations/zh.json index dc47ef147..b75b33b3f 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -364,5 +364,7 @@ "Pin this post to your profile.": "将此帖子固定到您的个人资料。", "Administered by": "由...管理", "Version": "版", - "Skip to timeline": "跳到时间线" + "Skip to timeline": "跳到时间线", + "Skip to Newswire": "跳到新闻专线", + "Skip to Links": "跳到网页链接" } diff --git a/webapp_timeline.py b/webapp_timeline.py index 5df33749b..4a2a1edb6 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -372,6 +372,12 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '' + \ translate['Skip to timeline'] + ' | ' + \ ' | ' + \ + ' | ' + \ + '' + \ '
\n' @@ -420,7 +426,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, httpPrefix, translate, editor, False, None, rssIconAtTop, True, False, theme) - tlStr += ' ' + \ + tlStr += ' ' + \ leftColumnStr + ' \n' # center column containing posts tlStr += ' \n' @@ -626,7 +633,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, rssIconAtTop, publishButtonAtTop, authorized, True, theme) tlStr += ' \n' - tlStr += ' ' + \ + tlStr += ' ' + \ rightColumnStr + ' \n' tlStr += ' \n' From fc0ab024d9164d249ac72625392b6ef4fd0afd78 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 17:21:33 +0000 Subject: [PATCH 23/50] Keyboard navigation from profile screen --- webapp_profile.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/webapp_profile.py b/webapp_profile.py index 91c4a7906..3ff55116f 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -705,7 +705,17 @@ def htmlProfile(rssIconAtTop: bool, movedTo, alsoKnownAs, pinnedContent) - profileStr = profileHeaderStr + donateSection + profileStr = \ + '\n' + + profileStr += profileHeaderStr + donateSection profileStr += '
\n' profileStr += '
' profileStr += \ From 701ca8372b3deba9f0fe767ee16018b916311910 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 17:32:05 +0000 Subject: [PATCH 24/50] Sequence of skip links --- webapp_profile.py | 9 +++++---- webapp_timeline.py | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/webapp_profile.py b/webapp_profile.py index 3ff55116f..9d56310ff 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -705,14 +705,15 @@ def htmlProfile(rssIconAtTop: bool, movedTo, alsoKnownAs, pinnedContent) + # Links for keyboard navigation profileStr = \ '
' + \ ' | ' + \ - '' + \ + translate['Switch to timeline view'] + ' | ' + \ + '' + \ '
\n' profileStr += profileHeaderStr + donateSection diff --git a/webapp_timeline.py b/webapp_timeline.py index 4a2a1edb6..8fb46aa52 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -369,6 +369,9 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, tlStr += \ '
' + \ ' | ' + \ + ' | ' + \ ' | ' + \ ' | ' + \ - '' + \ + translate['Skip to Links'] + '' + \ '
\n' # banner and row of buttons From 203d628c5a701476d7cfcf6b1fdd50a3a126af41 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 17:35:14 +0000 Subject: [PATCH 25/50] Briefer --- translations/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/en.json b/translations/en.json index a79da2fe1..bdf30b608 100644 --- a/translations/en.json +++ b/translations/en.json @@ -48,7 +48,7 @@ "Location": "Location", "Login": "Login", "Edit": "Edit", - "Switch to timeline view": "Switch to timeline view", + "Switch to timeline view": "Timeline view", "Approve": "Approve", "Deny": "Deny", "Posts": "Posts", @@ -63,7 +63,7 @@ "Your browser does not support the video element.": "Your browser does not support the video element.", "Create a new post": "New post", "Create a new DM": "Create a new DM", - "Switch to profile view": "Switch to profile view", + "Switch to profile view": "Profile view", "Inbox": "Inbox", "Outbox": "Outbox", "Search and follow": "Search/follow", From f767eb17964ca963a8e2f08b4e0d6e09db327f84 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 18:38:08 +0000 Subject: [PATCH 26/50] Alt text for images --- webapp_column_left.py | 1 + webapp_column_right.py | 1 + webapp_profile.py | 4 ++++ webapp_timeline.py | 5 +++-- webapp_utils.py | 4 ++-- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/webapp_column_left.py b/webapp_column_left.py index ee7a6de77..7f87b1208 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -90,6 +90,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += \ '\n
\n' + \ ' \n' + \ '
\n' diff --git a/webapp_column_right.py b/webapp_column_right.py index 2a5b778d0..3c9d46e45 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -92,6 +92,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += \ '\n
\n' + \ ' \n' + \ '
\n' diff --git a/webapp_profile.py b/webapp_profile.py index 9d56310ff..1729c336a 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -324,6 +324,7 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' htmlStr += ' \n' htmlStr += '
\n' htmlStr += \ @@ -331,6 +332,7 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' + \ ' \n' htmlStr += '

' + displayName + '

\n' htmlStr += \ @@ -403,6 +405,7 @@ def _getProfileHeaderAfterSearch(baseDir: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' htmlStr += ' \n' htmlStr += '
\n' if avatarUrl: @@ -411,6 +414,7 @@ def _getProfileHeaderAfterSearch(baseDir: str, translate['Switch to timeline view'] + '">\n' htmlStr += \ ' \n' htmlStr += '

' + displayName + '

\n' htmlStr += \ diff --git a/webapp_timeline.py b/webapp_timeline.py index 8fb46aa52..17b88ff3d 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -388,8 +388,9 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '\n' - tlStr += '\n' + \ + tlStr += '\n' + \ '\n' if fullWidthTimelineButtonHeader: diff --git a/webapp_utils.py b/webapp_utils.py index ae8b810bd..1531c912f 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -838,8 +838,8 @@ def htmlPostSeparator(baseDir: str, column: str) -> str: if os.path.isfile(separatorImageFilename): separatorStr = \ '
' + \ - '' + \ - '
\n' + '
\n' return separatorStr From a8c31297650f74d8fc91ef1c394f474275fb6d8c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 18:42:39 +0000 Subject: [PATCH 27/50] alt text for qrcode --- webapp_profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_profile.py b/webapp_profile.py index 1729c336a..8307078ba 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -375,8 +375,8 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, ' ' + \ - '

\n' + '' + translate['QR Code'] + \
+        '

\n' htmlStr += '

' + profileDescriptionShort + '

\n' htmlStr += loginButton if pinnedContent: From 4827ae93ac8403b2b88710808a9d0cf4f78ce5a2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 18:58:24 +0000 Subject: [PATCH 28/50] Alt text on images --- webapp_column_right.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/webapp_column_right.py b/webapp_column_right.py index 3c9d46e45..ac27ab10e 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -242,6 +242,7 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool, if faviconUrl: faviconLink = \ '' moderatedItem = item[5] htmlStr += separatorStr @@ -266,6 +267,7 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool, '/newswireunvote=' + dateStrLink + '" ' + \ 'title="' + translate['Remove Vote'] + '">' htmlStr += '

\n' else: htmlStr += ' ' @@ -291,8 +293,9 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool, htmlStr += '' - htmlStr += '' + htmlStr += '' htmlStr += '

\n' else: htmlStr += '

' + \ @@ -355,7 +358,9 @@ def htmlCitations(baseDir: str, nickname: str, domain: str, '\n' - htmlStr += '\n' htmlStr += \ @@ -465,6 +470,7 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str, htmlStr += \ '' + \ '\n' htmlStr += '

\n' @@ -532,8 +538,8 @@ def htmlEditNewswire(cssCache: {}, translate: {}, baseDir: str, path: str, translate['Switch to timeline view'] + '" alt="' + \ translate['Switch to timeline view'] + '">\n' editNewswireForm += '\n' + \ - '' + '/users/' + nickname + '/' + bannerFile + '" ' + \ + 'alt="" />\n' editNewswireForm += \ '
Date: Mon, 1 Feb 2021 19:28:07 +0000 Subject: [PATCH 29/50] Separators --- webapp_column_left.py | 2 +- webapp_column_right.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/webapp_column_left.py b/webapp_column_left.py index 7f87b1208..1555a5d3e 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -116,7 +116,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, '/users/' + nickname + '/editlinks">' + \ '' + \
-            translate['Edit Links'] + '\n' diff --git a/webapp_column_right.py b/webapp_column_right.py index ac27ab10e..25d02129e 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -124,7 +124,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, '/users/' + nickname + '/editnewswire">' + \ '' + \
-                translate['Edit newswire'] + '\n' else: @@ -143,14 +143,14 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, ' ' + \ '' + \
-        translate['Hashtag Categories RSS Feed'] + '\n' rssIconStr += \ ' ' + \ '' + \
-        translate['Newswire RSS Feed'] + '\n' if rssIconAtTop: From 67b8c58b0af25c3639d9435aae6ced20eb5d4fc4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 19:32:33 +0000 Subject: [PATCH 30/50] Separator --- webapp_column_right.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_column_right.py b/webapp_column_right.py index 25d02129e..de0e6c866 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -134,7 +134,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, '/users/' + nickname + '/editnewswire">' + \ '' + \
-                translate['Edit newswire'] + '\n' From 5387df1c09b009e95ad753d3eb3f97e3e1d40092 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 19:48:46 +0000 Subject: [PATCH 31/50] Remove alt descriptions on images --- webapp_column_left.py | 7 ++++--- webapp_column_right.py | 6 ++---- webapp_timeline.py | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/webapp_column_left.py b/webapp_column_left.py index 1555a5d3e..14651564f 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -90,8 +90,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += \ '\n
\n' + \ ' \n' + \ '
\n' @@ -269,6 +268,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str, htmlStr += \ '' + \ '\n' htmlStr += '
\n' @@ -334,7 +334,8 @@ def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str, '\n' - editLinksForm += '\n' + \ '\n' diff --git a/webapp_column_right.py b/webapp_column_right.py index de0e6c866..b245a5c6e 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -92,8 +92,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += \ '\n
\n' + \ ' \n' + \ '
\n' @@ -359,8 +358,7 @@ def htmlCitations(baseDir: str, nickname: str, domain: str, translate['Go Back'] + '" alt="' + \ translate['Go Back'] + '">\n' htmlStr += '\n' htmlStr += \ diff --git a/webapp_timeline.py b/webapp_timeline.py index 17b88ff3d..419a58381 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -389,7 +389,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, translate['Switch to profile view'] + '" alt="' + \ translate['Switch to profile view'] + '">\n' tlStr += '\n' + \ '\n' From a5b60d7fce768cc53b0f652cc223f152277a920b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 19:53:41 +0000 Subject: [PATCH 32/50] Remove alt text for cleaner look in shell browser --- webapp_profile.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/webapp_profile.py b/webapp_profile.py index 8307078ba..92d4dff48 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -324,7 +324,7 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' htmlStr += ' \n' htmlStr += '
\n' htmlStr += \ @@ -332,8 +332,7 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' + \ ' \n' + 'alt="" class="title">\n' htmlStr += '

' + displayName + '

\n' htmlStr += \ '

@' + nickname + '@' + domainFull + '
\n' @@ -405,7 +404,7 @@ def _getProfileHeaderAfterSearch(baseDir: str, nickname + '/' + defaultTimeline + '" title="' + \ translate['Switch to timeline view'] + '">\n' htmlStr += ' \n' htmlStr += '

\n' if avatarUrl: @@ -414,8 +413,7 @@ def _getProfileHeaderAfterSearch(baseDir: str, translate['Switch to timeline view'] + '">\n' htmlStr += \ ' \n' + 'alt="" class="title">\n' htmlStr += '

' + displayName + '

\n' htmlStr += \ '

@' + searchNickname + '@' + searchDomainFull + '
\n' From 05d99c8933f25ea02c1bf56592131013382abf64 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 19:59:18 +0000 Subject: [PATCH 33/50] Clear alt text for login image Not needed in a shell browser --- webapp_login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_login.py b/webapp_login.py index cb640135a..859b10871 100644 --- a/webapp_login.py +++ b/webapp_login.py @@ -140,7 +140,7 @@ def htmlLogin(cssCache: {}, translate: {}, loginForm += '

\n' loginForm += \ ' login image\n' + '" alt="" class="loginimage">\n' loginForm += loginText + TOSstr + '\n' loginForm += '
\n' loginForm += '\n' From e5516eda9f1879adbbcad75cd01833f8f6eaefc9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 20:03:07 +0000 Subject: [PATCH 34/50] No alt for person options avatar image --- webapp_person_options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 2e13c3d0a..3dc819f7b 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -120,7 +120,7 @@ def htmlPersonOptions(defaultTimeline: str, optionsStr += '
\n' optionsStr += ' \n' optionsStr += ' \n' + '" alt="" ' + getBrokenLinkSubstitute() + '/>\n' handle = getNicknameFromActor(optionsActor) + '@' + optionsDomain handleShown = handle if lockedAccount: From cfe8d9b5e6f80382848b4c5b763089848d025477 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 20:20:13 +0000 Subject: [PATCH 35/50] Clear alt text on search screen --- webapp_search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_search.py b/webapp_search.py index a574cb31b..af512fe38 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -348,7 +348,7 @@ def htmlSearch(cssCache: {}, translate: {}, translate['Switch to timeline view'] + '" alt="' + \ translate['Switch to timeline view'] + '">\n' followStr += '\n' + \ + usersPath + '/' + searchBannerFile + '" alt="" />\n' + \ '\n' # show the search box @@ -496,7 +496,7 @@ def htmlSkillsSearch(actor: str, actor + '/skills">' skillSearchForm += \ '' + actorName + \ + '" alt="" />' + actorName + \ '
' ctr += 1 if ctr >= postsPerPage: From 13e3def4b320b4e783c5f585e0ed2fb69dcc3457 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 1 Feb 2021 20:26:52 +0000 Subject: [PATCH 36/50] Clear alt text on category screen --- webapp_hashtagswarm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_hashtagswarm.py b/webapp_hashtagswarm.py index 076e54108..ebb9aa2cc 100644 --- a/webapp_hashtagswarm.py +++ b/webapp_hashtagswarm.py @@ -263,7 +263,7 @@ def htmlSearchHashtagCategory(cssCache: {}, translate: {}, if os.path.isfile(searchBannerFilename): htmlStr += '\n' htmlStr += '\n' + actor + '/' + searchBannerFile + '" alt="" />\n' htmlStr += '