Browse Source

Fixing non-ascii text

Bob Mottram 11 months ago
parent
commit
0192532293
15 changed files with 195 additions and 190 deletions
  1. 1 1
      announce.py
  2. 1 1
      availability.py
  3. 2 2
      blocking.py
  4. 144 131
      daemon.py
  5. 1 1
      delete.py
  6. 2 2
      follow.py
  7. 3 3
      httpsig.py
  8. 2 2
      like.py
  9. 25 30
      posts.py
  10. 1 2
      roles.py
  11. 1 1
      session.py
  12. 2 2
      shares.py
  13. 1 1
      skills.py
  14. 6 8
      tests.py
  15. 3 3
      webinterface.py

+ 1 - 1
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")

+ 1 - 1
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")

+ 2 - 2
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")

+ 144 - 131
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
-
-                                fd = open(filename, 'wb')
-                                fd.write(postBytes[startPos:])
-                                fd.close()
-                            else:
-                                filename=None
+            # 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
 
             # 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))

+ 1 - 1
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")

+ 2 - 2
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")

+ 3 - 3
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:

+ 2 - 2
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")

+ 25 - 30
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:

+ 1 - 2
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
-

+ 1 - 1
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

+ 2 - 2
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")

+ 1 - 1
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")

+ 6 - 8
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 यह एक परीक्षण ह"

+ 3 - 3
webinterface.py

@@ -606,7 +606,7 @@ def htmlEditProfile(translate: {},baseDir: str,path: str,domain: str,port: int)
         
     editProfileForm=htmlHeader(cssFilename,editProfileCSS)
     editProfileForm+= \
-        '<form enctype="multipart/form-data" method="POST" action="'+path+'/profiledata">' \
+        '<form enctype="multipart/form-data" method="POST" accept-charset="UTF-8" action="'+path+'/profiledata">' \
         '  <div class="vertical-center">' \
         '    <p class="new-post-text">'+translate['Profile for']+' '+nickname+'@'+domainFull+'</p>' \
         '    <div class="container">' \
@@ -1001,7 +1001,7 @@ def htmlNewPost(translate: {},baseDir: str, \
         mentionsStr='Re: '+reportUrl+'\n\n'+mentionsStr
     
     newPostForm+= \
-        '<form enctype="multipart/form-data" method="POST" action="'+path+'?'+endpoint+'?page='+str(pageNumber)+'">' \
+        '<form enctype="multipart/form-data" method="POST" accept-charset="UTF-8" action="'+path+'?'+endpoint+'?page='+str(pageNumber)+'">' \
         '  <div class="vertical-center">' \
         '    <label for="nickname"><b>'+newPostText+'</b></label>' \
         '    <div class="container">' \
@@ -3321,7 +3321,7 @@ def htmlSearch(translate: {}, \
     followStr+='  <center>'    
     followStr+='  <p class="followText">'+translate['Enter an address, shared item, #hashtag, *skill or :emoji: to search for']+'</p>'
     followStr+= \
-        '  <form method="POST" action="'+actor+'/searchhandle">' \
+        '  <form method="POST" accept-charset="UTF-8" action="'+actor+'/searchhandle">' \
         '    <input type="hidden" name="actor" value="'+actor+'">' \
         '    <input type="text" name="searchtext" autofocus><br>' \
         '    <button type="submit" class="button" name="submitSearch">'+translate['Submit']+'</button>' \