diff --git a/announce.py b/announce.py index fc623008e..55349c17e 100644 --- a/announce.py +++ b/announce.py @@ -501,7 +501,7 @@ def sendAnnounceViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newAnnounceJson,[],inboxUrl,headers,"inbox:write") diff --git a/availability.py b/availability.py index 421db8c0a..38920bc2e 100644 --- a/availability.py +++ b/availability.py @@ -130,7 +130,7 @@ def sendAvailabilityViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(Nickname,password) headers = {'host': domain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newAvailabilityJson,[],inboxUrl,headers,"inbox:write") diff --git a/blocking.py b/blocking.py index 34c2506f8..add3a0319 100644 --- a/blocking.py +++ b/blocking.py @@ -214,7 +214,7 @@ def sendBlockViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newBlockJson,[],inboxUrl,headers,"inbox:write") @@ -291,7 +291,7 @@ def sendUndoBlockViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newBlockJson,[],inboxUrl,headers,"inbox:write") diff --git a/daemon.py b/daemon.py index dd9b4541e..795aba598 100644 --- a/daemon.py +++ b/daemon.py @@ -333,7 +333,7 @@ class PubServer(BaseHTTPRequestHandler): wfResult=webfingerMeta(self.server.httpPrefix,self.server.domainFull) if wfResult: msg=wfResult.encode('utf-8') - self._set_headers('application/xrd+xml; charset=utf-8',len(msg),None) + self._set_headers('application/xrd+xml',len(msg),None) self._write(msg) return @@ -341,8 +341,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: WEBFINGER lookup '+self.path+' '+str(self.server.baseDir)) wfResult=webfingerLookup(self.path,self.server.baseDir,self.server.port,self.server.debug) if wfResult: - msg=json.dumps(wfResult, ensure_ascii=False).encode('utf-8') - self._set_headers('application/jrd+json; charset=utf-8',len(msg),None) + msg=json.dumps(wfResult).encode('utf-8') + self._set_headers('application/jrd+json',len(msg),None) self._write(msg) else: if self.server.debug: @@ -706,7 +706,7 @@ class PubServer(BaseHTTPRequestHandler): if self.path=='/logout': msg=htmlLogin(self.server.translate, \ self.server.baseDir,False).encode('utf-8') - self._logout_headers('text/html; charset=utf-8',len(msg)) + self._logout_headers('text/html',len(msg)) self._write(msg) return @@ -785,7 +785,7 @@ class PubServer(BaseHTTPRequestHandler): optionsProfileUrl, \ optionsLink, \ pageNumber,donateUrl).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -807,7 +807,7 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(actor+'/inbox',cookie) self.server.GETbusy=False return - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -816,7 +816,7 @@ class PubServer(BaseHTTPRequestHandler): msg=htmlTermsOfService(self.server.baseDir, \ self.server.httpPrefix, \ self.server.domainFull).encode() - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.GETbusy=False return @@ -825,7 +825,7 @@ class PubServer(BaseHTTPRequestHandler): msg=htmlAbout(self.server.baseDir, \ self.server.httpPrefix, \ self.server.domainFull).encode() - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.GETbusy=False return @@ -884,7 +884,7 @@ class PubServer(BaseHTTPRequestHandler): time.sleep(1) tries+=1 msg=css.encode('utf-8') - self._set_headers('text/css; charset=utf-8',len(msg),cookie) + self._set_headers('text/css',len(msg),cookie) self._write(msg) return @@ -1142,7 +1142,7 @@ class PubServer(BaseHTTPRequestHandler): # request basic auth msg=htmlLogin(self.server.translate, \ self.server.baseDir).encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.GETbusy=False return @@ -1159,7 +1159,7 @@ class PubServer(BaseHTTPRequestHandler): hashtag=hashtag.split('?page=')[0] if isBlockedHashtag(self.server.baseDir,hashtag): msg=htmlHashtagBlocked(self.server.baseDir).encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.GETbusy=False return @@ -1173,7 +1173,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.projectVersion) if hashtagStr: msg=hashtagStr.encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: originPathStr=self.path.split('/tags/')[0] @@ -1188,7 +1188,7 @@ class PubServer(BaseHTTPRequestHandler): # show the search screen msg=htmlSearch(self.server.translate, \ self.server.baseDir,self.path).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -1201,7 +1201,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir,self.path, \ self.server.httpPrefix, \ self.server.domainFull).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -1213,7 +1213,7 @@ class PubServer(BaseHTTPRequestHandler): msg=htmlSearchEmojiTextEntry(self.server.translate, \ self.server.baseDir, \ self.path).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -1515,7 +1515,7 @@ class PubServer(BaseHTTPRequestHandler): __version__,self.server.cachedWebfingers, \ self.server.personCache) if deleteStr: - self._set_headers('text/html; charset=utf-8',len(deleteStr),cookie) + self._set_headers('text/html',len(deleteStr),cookie) self._write(deleteStr.encode()) self.server.GETbusy=False return @@ -1596,7 +1596,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir, \ self.path,self.server.domain, \ self.server.port).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -1615,7 +1615,7 @@ class PubServer(BaseHTTPRequestHandler): replyToList, \ shareDescription, \ replyPageNumber).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -1662,12 +1662,12 @@ class PubServer(BaseHTTPRequestHandler): authorized,postJsonObject, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(postJsonObject, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(postJsonObject,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1727,14 +1727,14 @@ class PubServer(BaseHTTPRequestHandler): repliesJson, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) print('----------------------------------------------------') #pprint(repliesJson) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(repliesJson, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(repliesJson,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1778,12 +1778,12 @@ class PubServer(BaseHTTPRequestHandler): repliesJson, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(repliesJson, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(repliesJson,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1820,12 +1820,12 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, \ actorJson['roles'], \ None,None).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(actorJson['roles'], ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(actorJson['roles'],ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1863,12 +1863,12 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, \ actorJson['skills'], \ None,None).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(actorJson['skills'], ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(actorJson['skills'],ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1919,12 +1919,12 @@ class PubServer(BaseHTTPRequestHandler): authorized,postJsonObject, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(postJsonObject, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(postJsonObject,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -1981,13 +1981,13 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: # don't need authenticated fetch here because there is # already the authorization check - msg=json.dumps(inboxFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(inboxFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) self.server.GETbusy=False return @@ -2051,13 +2051,13 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: # don't need authenticated fetch here because there is # already the authorization check - msg=json.dumps(inboxDMFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(inboxDMFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) self.server.GETbusy=False return @@ -2124,13 +2124,13 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: # don't need authenticated fetch here because there is # already the authorization check - msg=json.dumps(inboxRepliesFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(inboxRepliesFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) self.server.GETbusy=False return @@ -2197,13 +2197,13 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: # don't need authenticated fetch here because there is # already the authorization check - msg=json.dumps(inboxMediaFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(inboxMediaFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) self.server.GETbusy=False return @@ -2247,7 +2247,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return @@ -2303,12 +2303,12 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowDeletion, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(outboxFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(outboxFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -2365,13 +2365,13 @@ class PubServer(BaseHTTPRequestHandler): True, \ self.server.httpPrefix, \ self.server.projectVersion).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: # don't need authenticated fetch here because there is # already the authorization check - msg=json.dumps(moderationFeed, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(moderationFeed,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) self.server.GETbusy=False return @@ -2434,14 +2434,14 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, \ shares, \ pageNumber,sharesPerPage).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return else: if self._fetchAuthenticated(): - msg=json.dumps(shares, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(shares,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -2490,14 +2490,14 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, \ following, \ pageNumber,followsPerPage).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return else: if self._fetchAuthenticated(): - msg=json.dumps(following, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(following,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -2545,14 +2545,14 @@ class PubServer(BaseHTTPRequestHandler): self.server.personCache, \ followers, \ pageNumber,followsPerPage).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.GETbusy=False return else: if self._fetchAuthenticated(): - msg=json.dumps(followers, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(followers,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -2580,12 +2580,12 @@ class PubServer(BaseHTTPRequestHandler): self.server.cachedWebfingers, \ self.server.personCache, \ None,None).encode('utf-8') - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) else: if self._fetchAuthenticated(): - msg=json.dumps(getPerson, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(getPerson,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: self._404() @@ -2610,8 +2610,8 @@ class PubServer(BaseHTTPRequestHandler): with open(filename, 'r', encoding='utf-8') as File: content = File.read() contentJson=json.loads(content) - msg=json.dumps(contentJson, ensure_ascii=False).encode('utf-8') - self._set_headers('application/json; charset=utf-8',len(msg),None) + msg=json.dumps(contentJson,ensure_ascii=False).encode('utf-8') + self._set_headers('application/json',len(msg),None) self._write(msg) else: if self.server.debug: @@ -2620,7 +2620,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.GETbusy=False def do_HEAD(self): - self._set_headers('application/json; charset=utf-8',0,None) + self._set_headers('application/json',0,None) def _receiveNewPostProcess(self,authorized: bool, \ postType: str,path: str,headers: {}) -> int: @@ -2653,10 +2653,18 @@ class PubServer(BaseHTTPRequestHandler): # why don't we just use msg.is_multipart(), rather than splitting? # TL;DR it doesn't work for this use case because we're not using # email style encoding message/rfc822 - messageFields=msg.get_payload(decode=False).split(boundary) + imageBoundary=b'Content-Disposition: form-data; name="attachpic";' + imageLocation=postBytes.find(imageBoundary) + if imageLocation>-1: + # get the first part of the data containing text fields + # If we try to use decode=True on the full data, including images, + # then it will fail + msg = email.parser.BytesParser().parsebytes(postBytes[:imageLocation]) + messageFields=msg.get_payload(decode=True).decode('utf-8').split(boundary) fields={} filename=None attachmentMediaType=None + # get the text fields for f in messageFields: if f=='--': continue @@ -2675,52 +2683,56 @@ class PubServer(BaseHTTPRequestHandler): postValue+='\n' postValue+=postLines[line] fields[postKey]=postValue - else: - # directly search the binary array for the beginning - # of an image - extensionList=['png','jpeg','gif','mp4','webm','ogv','mp3','ogg'] - for extension in extensionList: - searchStr=b'Content-Type: image/png' - if extension=='jpeg': - searchStr=b'Content-Type: image/jpeg' - elif extension=='gif': - searchStr=b'Content-Type: image/gif' - elif extension=='mp4': - searchStr=b'Content-Type: video/mp4' - elif extension=='ogv': - searchStr=b'Content-Type: video/ogv' - elif extension=='mp3': - searchStr=b'Content-Type: audio/mpeg' - elif extension=='ogg': - searchStr=b'Content-Type: audio/ogg' - imageLocation=postBytes.find(searchStr) - filenameBase= \ - self.server.baseDir+'/accounts/'+ \ - nickname+'@'+self.server.domain+'/upload' - if imageLocation>-1: - if extension=='jpeg': - extension='jpg' - if extension=='mpeg': - extension='mp3' - filename=filenameBase+'.'+extension - attachmentMediaType= \ - searchStr.decode().split('/')[0].replace('Content-Type: ','') - break - if filename and imageLocation>-1: - # locate the beginning of the image, after any - # carriage returns - startPos=imageLocation+len(searchStr) - for offset in range(1,8): - if postBytes[startPos+offset]!=10: - if postBytes[startPos+offset]!=13: - startPos+=offset - break + # now extract any attached image or other media + if imageLocation>-1: + imageLocation2=-1 + filename=None + searchStr='' + # directly search the binary array for the beginning + # of an image + extensionList=['png','jpeg','gif','mp4','webm','ogv','mp3','ogg'] + for extension in extensionList: + searchStr=b'Content-Type: image/png' + if extension=='jpeg': + searchStr=b'Content-Type: image/jpeg' + elif extension=='gif': + searchStr=b'Content-Type: image/gif' + elif extension=='mp4': + searchStr=b'Content-Type: video/mp4' + elif extension=='ogv': + searchStr=b'Content-Type: video/ogv' + elif extension=='mp3': + searchStr=b'Content-Type: audio/mpeg' + elif extension=='ogg': + searchStr=b'Content-Type: audio/ogg' + imageLocation2=postBytes.find(searchStr) + filenameBase= \ + self.server.baseDir+'/accounts/'+ \ + nickname+'@'+self.server.domain+'/upload' + if imageLocation2>-1: + if extension=='jpeg': + extension='jpg' + elif extension=='mpeg': + extension='mp3' + filename=filenameBase+'.'+extension + attachmentMediaType= \ + searchStr.decode().split('/')[0].replace('Content-Type: ','') + break + if filename and imageLocation2>-1: + # locate the beginning of the image, after any + # carriage returns + startPos=imageLocation2+len(searchStr) + for offset in range(1,8): + if postBytes[startPos+offset]!=10: + if postBytes[startPos+offset]!=13: + startPos+=offset + break - fd = open(filename, 'wb') - fd.write(postBytes[startPos:]) - fd.close() - else: - filename=None + fd = open(filename, 'wb') + fd.write(postBytes[startPos:]) + fd.close() + else: + filename=None # send the post if not fields.get('message') and not fields.get('imageDescription'): @@ -3039,7 +3051,7 @@ class PubServer(BaseHTTPRequestHandler): else: if isSuspended(self.server.baseDir,loginNickname): msg=htmlSuspended(self.server.baseDir).encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3118,6 +3130,7 @@ class PubServer(BaseHTTPRequestHandler): postBytes=self.rfile.read(length) msg = email.parser.BytesParser().parsebytes(postBytes) + #messageFields=msg.get_payload(decode=True).decode('utf-8').split(boundary) messageFields=msg.get_payload(decode=False).split(boundary) fields={} filename=None @@ -3415,7 +3428,7 @@ class PubServer(BaseHTTPRequestHandler): elif moderationStr.startswith('submitInfo'): msg=htmlModerationInfo(self.server.translate, \ self.server.baseDir).encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3616,7 +3629,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.projectVersion) if hashtagStr: msg=hashtagStr.encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3630,7 +3643,7 @@ class PubServer(BaseHTTPRequestHandler): 64) if skillStr: msg=skillStr.encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3657,7 +3670,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.projectVersion) if profileStr: msg=profileStr.encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3677,7 +3690,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir,searchStr) if emojiStr: msg=emojiStr.encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -3693,7 +3706,7 @@ class PubServer(BaseHTTPRequestHandler): actorStr) if sharedItemsStr: msg=sharedItemsStr.encode('utf-8') - self._login_headers('text/html; charset=utf-8',len(msg)) + self._login_headers('text/html',len(msg)) self._write(msg) self.server.POSTbusy=False return @@ -4026,7 +4039,7 @@ class PubServer(BaseHTTPRequestHandler): originPathStr, \ optionsActor, \ optionsAvatarUrl).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.POSTbusy=False return @@ -4038,7 +4051,7 @@ class PubServer(BaseHTTPRequestHandler): originPathStr, \ optionsActor, \ optionsAvatarUrl).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.POSTbusy=False return @@ -4050,7 +4063,7 @@ class PubServer(BaseHTTPRequestHandler): originPathStr, \ optionsActor, \ optionsAvatarUrl).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.POSTbusy=False return @@ -4063,7 +4076,7 @@ class PubServer(BaseHTTPRequestHandler): reportPath,None, \ [optionsActor],None, \ pageNumber).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.POSTbusy=False return @@ -4095,7 +4108,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir, \ reportPath,None,[], \ postUrl,pageNumber).encode() - self._set_headers('text/html; charset=utf-8',len(msg),cookie) + self._set_headers('text/html',len(msg),cookie) self._write(msg) self.server.POSTbusy=False return @@ -4247,8 +4260,8 @@ class PubServer(BaseHTTPRequestHandler): return # refuse to receive non-json content - if 'application/json' not in self.headers['Content-type'] and \ - 'application/activity+json' not in self.headers['Content-type']: + if self.headers['Content-type'] != 'application/json' and \ + self.headers['Content-type'] != 'application/activity+json': print("POST is not json: "+self.headers['Content-type']) if self.server.debug: print(str(self.headers)) diff --git a/delete.py b/delete.py index f12f887c9..0f737998e 100644 --- a/delete.py +++ b/delete.py @@ -144,7 +144,7 @@ def sendDeleteViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newDeleteJson,[],inboxUrl,headers,"inbox:write") diff --git a/follow.py b/follow.py index 4dfc24dcf..428b71b21 100644 --- a/follow.py +++ b/follow.py @@ -733,7 +733,7 @@ def sendFollowRequestViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newFollowJson,[],inboxUrl,headers,"inbox:write") @@ -818,7 +818,7 @@ def sendUnfollowRequestViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,unfollowJson,[],inboxUrl,headers,"inbox:write") diff --git a/httpsig.py b/httpsig.py index 16e02eae1..b36b48c56 100644 --- a/httpsig.py +++ b/httpsig.py @@ -47,10 +47,10 @@ def signPostHeaders(dateStr: str,privateKeyPem: str, \ dateStr=strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) keyID=httpPrefix+'://'+domain+'/users/'+nickname+'#main-key' if not messageBodyJsonStr: - headers={'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'content-type': 'application/json; charset=utf-8'} + headers={'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'content-type': 'application/json'} else: bodyDigest=messageContentDigest(messageBodyJsonStr) - headers={'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': 'application/activity+json; charset=utf-8'} + headers={'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': 'application/activity+json'} privateKeyPem=RSA.import_key(privateKeyPem) #headers.update({ # '(request-target)': f'post {path}', @@ -87,7 +87,7 @@ def createSignedHeader(privateKeyPem: str,nickname: str, \ messageBodyJsonStr: str) -> {}: """Note that the domain is the destination, not the sender """ - contentType='application/activity+json; charset=utf-8' + contentType='application/activity+json' headerDomain=toDomain if toPort: diff --git a/like.py b/like.py index 0654fa05e..74e602c5a 100644 --- a/like.py +++ b/like.py @@ -402,7 +402,7 @@ def sendLikeViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newLikeJson,[],inboxUrl,headers,"inbox:write") @@ -481,7 +481,7 @@ def sendUndoLikeViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newUndoLikeJson,[],inboxUrl,headers,"inbox:write") diff --git a/posts.py b/posts.py index f14765ea6..88e813ad1 100644 --- a/posts.py +++ b/posts.py @@ -120,7 +120,7 @@ def getUserUrl(wfRequest: {}) -> str: if wfRequest.get('links'): for link in wfRequest['links']: if link.get('type') and link.get('href'): - if 'application/activity+json' in link['type']: + if link['type'] == 'application/activity+json': if not ('/users/' in link['href'] or \ '/profile/' in link['href'] or \ '/channel/' in link['href']): @@ -1250,7 +1250,7 @@ def sendPostViaServer(projectVersion: str, \ # return 9 headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJsonString(session,json.dumps(postJsonObject),[],inboxUrl,headers,"inbox:write",debug) @@ -1420,7 +1420,7 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \ # convert json to string so that there are no # subsequent conversions after creating message body digest - postJsonStr=json.dumps(postJsonObject, ensure_ascii=False) + postJsonStr=json.dumps(postJsonObject) # construct the http header, including the message body digest signatureHeaderJson = \ @@ -1894,34 +1894,29 @@ def isImageMedia(session,baseDir: str,httpPrefix: str,nickname: str,domain: str, def isReply(postJsonObject: {},actor: str) -> bool: """Returns true if the given post is a reply to the given actor """ - if isDM(postJsonObject): - if postJsonObject['object'].get('inReplyTo'): - if postJsonObject['object']['inReplyTo'].startswith(actor): - return True - else: - if postJsonObject['type']!='Create': - return False - if not postJsonObject.get('object'): - return False - if not isinstance(postJsonObject['object'], dict): - return False - if postJsonObject['object']['type']!='Note': - return False - if postJsonObject['object'].get('inReplyTo'): - if postJsonObject['object']['inReplyTo'].startswith(actor): - return True - if not postJsonObject['object'].get('tag'): - return False - if not isinstance(postJsonObject['object']['tag'], list): - return False - for tag in postJsonObject['object']['tag']: - if not tag.get('type'): + if postJsonObject['type']!='Create': + return False + if not postJsonObject.get('object'): + return False + if not isinstance(postJsonObject['object'], dict): + return False + if postJsonObject['object']['type']!='Note': + return False + if postJsonObject['object'].get('inReplyTo'): + if postJsonObject['object']['inReplyTo'].startswith(actor): + return True + if not postJsonObject['object'].get('tag'): + return False + if not isinstance(postJsonObject['object']['tag'], list): + return False + for tag in postJsonObject['object']['tag']: + if not tag.get('type'): + continue + if tag['type']=='Mention': + if not tag.get('href'): continue - if tag['type']=='Mention': - if not tag.get('href'): - continue - if actor in tag['href']: - return True + if actor in tag['href']: + return True return False def createBoxIndex(boxDir: str,postsInBoxDict: {}) -> int: diff --git a/roles.py b/roles.py index 8237eff73..3886b5477 100644 --- a/roles.py +++ b/roles.py @@ -281,7 +281,7 @@ def sendRoleViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(delegatorNickname,password) headers = {'host': delegatorDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newRoleJson,[],inboxUrl,headers,"inbox:write") @@ -294,4 +294,3 @@ def sendRoleViaServer(baseDir: str,session, \ print('DEBUG: c2s POST role success') return newRoleJson - diff --git a/session.py b/session.py index 5136497f8..c00b94205 100644 --- a/session.py +++ b/session.py @@ -96,7 +96,7 @@ def postJsonString(session,postJsonStr: str, \ postResult = session.post(url = inboxUrl, data = postJsonStr, headers=headers) if postResult.status_code<200 or postResult.status_code>202: #if postResult.status_code==400: - # headers['content-type']='application/ld+json; charset=utf-8' + # headers['content-type']='application/ld+json' # postResult = session.post(url = inboxUrl, data = postJsonStr, headers=headers) # if not (postResult.status_code<200 or postResult.status_code>202): # return True diff --git a/shares.py b/shares.py index ec9488d4c..8bf307217 100644 --- a/shares.py +++ b/shares.py @@ -392,7 +392,7 @@ def sendShareViaServer(baseDir,session, \ postImage(session,imageFilename,[],inboxUrl.replace('/'+postToBox,'/shares'),headers,"inbox:write") headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newShareJson,[],inboxUrl,headers,"inbox:write") @@ -473,7 +473,7 @@ def sendUndoShareViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) headers = {'host': fromDomain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,undoShareJson,[],inboxUrl,headers,"inbox:write") diff --git a/skills.py b/skills.py index fee9cb6c8..02689b9fb 100644 --- a/skills.py +++ b/skills.py @@ -151,7 +151,7 @@ def sendSkillViaServer(baseDir: str,session,nickname: str,password: str, authHeader=createBasicAuthHeader(Nickname,password) headers = {'host': domain, \ - 'Content-type': 'application/json; charset=utf-8', \ + 'Content-type': 'application/json', \ 'Authorization': authHeader} postResult = \ postJson(session,newSkillJson,[],inboxUrl,headers,"inbox:write") diff --git a/tests.py b/tests.py index 94e230163..72917a0f3 100644 --- a/tests.py +++ b/tests.py @@ -85,7 +85,7 @@ def testHttpsigBase(withDigest): os.mkdir(path) os.chdir(path) - contentType='application/activity+json; charset=utf-8' + contentType='application/activity+json' nickname='socrates' domain='argumentative.social' httpPrefix='https' @@ -106,7 +106,7 @@ def testHttpsigBase(withDigest): dateStr=strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) boxpath='/inbox' if not withDigest: - headers = {'host': headersDomain,'date': dateStr,'content-type': 'application/json; charset=utf-8'} + headers = {'host': headersDomain,'date': dateStr,'content-type': 'application/json'} signatureHeader = \ signPostHeaders(dateStr,privateKeyPem, nickname, \ domain, port, \ @@ -122,7 +122,6 @@ def testHttpsigBase(withDigest): boxpath, httpPrefix, messageBodyJsonStr) headers['signature'] = signatureHeader - assert 'utf-8' in headers['content-type'] assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \ boxpath,False,None, \ messageBodyJsonStr) @@ -134,7 +133,7 @@ def testHttpsigBase(withDigest): messageBodyJsonStr) == False if not withDigest: # fake domain - headers = {'host': 'bogon.domain','date': dateStr,'content-type': 'application/json; charset=utf-8'} + headers = {'host': 'bogon.domain','date': dateStr,'content-type': 'application/json'} else: # correct domain but fake message messageBodyJsonStr = '{"a key": "a value", "another key": "Fake GNUs", "yet another key": "More Fake GNUs"}' @@ -391,7 +390,7 @@ def testPostMessageBetweenServers(): sendPost(__version__, \ sessionAlice,aliceDir,'alice', aliceDomain, alicePort, \ 'bob', bobDomain, bobPort, ccUrl, httpPrefix, \ - 'Why is a mouse when it spins? Crème brûlée यह एक परीक्षण है #sillyquestion', followersOnly, \ + 'Why is a mouse when it spins? यह एक परीक्षण है #sillyquestion', followersOnly, \ saveToFile, clientToServer,attachedImageFilename,mediaType, \ attachedImageDescription,useBlurhash, federationList, \ aliceSendThreads, alicePostLog, aliceCachedWebfingers, \ @@ -432,7 +431,6 @@ def testPostMessageBetweenServers(): assert receivedJson assert 'Why is a mouse when it spins?' in receivedJson['object']['content'] assert 'यह एक परीक्षण है' in receivedJson['object']['content'] - assert 'Crème brûlée' in receivedJson['object']['content'] print('\n\n*******************************************************') print("Bob likes Alice's post") @@ -931,7 +929,7 @@ def testFollowBetweenServers(): assert 'bob@'+bobDomain in open(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt').read() # queue item removed - time.sleep(2) + time.sleep(4) assert len([name for name in os.listdir(queuePath) if os.path.isfile(os.path.join(queuePath, name))])==0 os.chdir(baseDir) @@ -1600,7 +1598,7 @@ def testGetStatusNumber(): assert int(statusNumber) > prevStatusNumber prevStatusNumber=int(statusNumber) -def testCommentJson(): +def testCommentJson() -> None: print('testCommentJson') filename='/tmp/test.json' messageStr="Crème brûlée यह एक परीक्षण ह" diff --git a/webinterface.py b/webinterface.py index 4b3d9fb3e..f7c2e749c 100644 --- a/webinterface.py +++ b/webinterface.py @@ -606,7 +606,7 @@ def htmlEditProfile(translate: {},baseDir: str,path: str,domain: str,port: int) editProfileForm=htmlHeader(cssFilename,editProfileCSS) editProfileForm+= \ - '
' \ + '' \ '
' \ '

'+translate['Profile for']+' '+nickname+'@'+domainFull+'

' \ '
' \ @@ -1001,7 +1001,7 @@ def htmlNewPost(translate: {},baseDir: str, \ mentionsStr='Re: '+reportUrl+'\n\n'+mentionsStr newPostForm+= \ - '' \ + '' \ '
' \ ' ' \ '
' \ @@ -3321,7 +3321,7 @@ def htmlSearch(translate: {}, \ followStr+='
' followStr+='

'+translate['Enter an address, shared item, #hashtag, *skill or :emoji: to search for']+'

' followStr+= \ - ' ' \ + ' ' \ ' ' \ '
' \ ' ' \