def _GetHashObject(self): message = '' if self._contact_from is not None: message += yaml.safe_dump(self._contact_from.GetPublicKey()) contact_to_public_keys = [ contact_to.GetPublicKey() for contact_to in self._contacts_to ] contact_to_public_keys.sort() if type(self._subject) == unicode: subject_text = self._subject.encode('utf-8') else: subject_text = self._subject if type(self._body) == unicode: body_text = self._body.encode('utf-8') else: body_text = self._body message += ''.join([ yaml.safe_dump(public_key) for public_key in contact_to_public_keys ]) + subject_text + body_text + ''.join(self._files) + HC.u( self._conversation_key) + HC.u(self._timestamp) hash_object = Crypto.Hash.SHA256.new(message) return hash_object
def InitDB(self): try: def make_temp_files_deletable(function_called, path, traceback_gumpf): os.chmod(path, stat.S_IWRITE) try: function_called(path) # try again except: pass if os.path.exists(HC.TEMP_DIR): shutil.rmtree(HC.TEMP_DIR, onerror=make_temp_files_deletable) except: pass try: if not os.path.exists(HC.TEMP_DIR): os.mkdir(HC.TEMP_DIR) except: pass db_initialised = False while not db_initialised: try: self._db = ClientDB.DB() db_initialised = True except HydrusExceptions.DBAccessException as e: try: print(HC.u(e)) except: print(repr(HC.u(e))) message = 'This instance of the client had a problem connecting to the database, which probably means an old instance is still closing.' message += os.linesep * 2 message += 'If the old instance does not close for a _very_ long time, you can usually safely force-close it from task manager.' with ClientGUIDialogs.DialogYesNo( None, message, 'There was a problem connecting to the database.', yes_label='wait a bit, then try again', no_label='forget it') as dlg: if dlg.ShowModal() == wx.ID_YES: time.sleep(3) else: raise HydrusExceptions.PermissionException() threading.Thread(target=self._db.MainLoop, name='Database Main Loop').start()
def StartService(*args, **kwargs): try: if 'port' not in options: return port = options['port'] connection = httplib.HTTPConnection('127.0.0.1', port, timeout=10) try: connection.connect() connection.close() raise Exception( 'Something was already bound to port ' + HC.u(port)) except: message = options['message'] if service_type == HC.SERVER_ADMIN: service_object = HydrusServer.HydrusServiceAdmin( service_key, service_type, message) elif service_type == HC.FILE_REPOSITORY: service_object = HydrusServer.HydrusServiceRepositoryFile( service_key, service_type, message) elif service_type == HC.TAG_REPOSITORY: service_object = HydrusServer.HydrusServiceRepositoryTag( service_key, service_type, message) elif service_type == HC.MESSAGE_DEPOT: return self._services[service_key] = reactor.listenTCP( port, service_object) connection = httplib.HTTPConnection('127.0.0.1', port, timeout=10) try: connection.connect() connection.close() except: raise Exception('Tried to bind port ' + HC.u(port) + ' but it failed.') except Exception as e: print(traceback.format_exc())
def ConvertHydrusGETArgsToQuery(request_args): if 'subject_identifier' in request_args: subject_identifier = request_args['subject_identifier'] del request_args['subject_identifier'] data = subject_identifier.GetData() if subject_identifier.HasAccountKey(): request_args['subject_account_key'] = data.encode('hex') elif subject_identifier.HasHash(): request_args['subject_hash'] = data.encode('hex') if subject_identifier.HasMapping(): (subject_hash, subject_tag) = data request_args['subject_hash'] = subject_hash.encode('hex') request_args['subject_tag'] = subject_tag.encode('hex') if 'title' in request_args: request_args['title'] = request_args['title'].encode('hex') query = '&'.join( [key + '=' + HC.u(value) for (key, value) in request_args.items()]) return query
def _checkUserAgent(self, request): request.is_hydrus_user_agent = False if request.requestHeaders.hasHeader('User-Agent'): user_agent_texts = request.requestHeaders.getRawHeaders( 'User-Agent') user_agent_text = user_agent_texts[0] try: user_agents = user_agent_text.split(' ') except: return # crazy user agent string, so just assume not a hydrus client for user_agent in user_agents: if '/' in user_agent: (client, network_version) = user_agent.split('/', 1) if client == 'hydrus': request.is_hydrus_user_agent = True network_version = int(network_version) if network_version == HC.NETWORK_VERSION: return else: if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'This server is out of date; please ask its admin to update to the latest release.' raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! This server\'s network version is ' + HC.u(HC.NETWORK_VERSION) + ', whereas your client\'s is ' + HC.u(network_version) + '! ' + message)
def InitGUI(self): self._managers = {} self._managers['services'] = CC.ServicesManager() self._managers[ 'hydrus_sessions'] = HydrusSessions.HydrusSessionManagerClient() self._managers['local_booru'] = CC.LocalBooruCache() self._managers['tag_censorship'] = HydrusTags.TagCensorshipManager() self._managers['tag_siblings'] = HydrusTags.TagSiblingsManager() self._managers['tag_parents'] = HydrusTags.TagParentsManager() self._managers['undo'] = CC.UndoManager() self._managers[ 'web_sessions'] = HydrusSessions.WebSessionManagerClient() self._fullscreen_image_cache = CC.RenderedImageCache('fullscreen') self._preview_image_cache = CC.RenderedImageCache('preview') self._thumbnail_cache = CC.ThumbnailCache() CC.GlobalBMPs.STATICInitialise() self._gui = ClientGUI.FrameGUI() HC.pubsub.sub(self, 'Clipboard', 'clipboard') HC.pubsub.sub(self, 'RestartServer', 'restart_server') HC.pubsub.sub(self, 'RestartBooru', 'restart_booru') self.Bind(wx.EVT_TIMER, self.TIMEREventMaintenance, id=ID_MAINTENANCE_EVENT_TIMER) self._maintenance_event_timer = wx.Timer(self, ID_MAINTENANCE_EVENT_TIMER) self._maintenance_event_timer.Start(MAINTENANCE_PERIOD * 1000, wx.TIMER_CONTINUOUS) # this is because of some bug in wx C++ that doesn't add these by default wx.richtext.RichTextBuffer.AddHandler( wx.richtext.RichTextHTMLHandler()) wx.richtext.RichTextBuffer.AddHandler(wx.richtext.RichTextXMLHandler()) if HC.is_first_start: wx.CallAfter(self._gui.DoFirstStart) if HC.is_db_updated: wx.CallLater( 1, HC.ShowText, 'The client has updated to version ' + HC.u(HC.SOFTWARE_VERSION) + '!') self.RestartServer() self.RestartBooru() self._db.StartDaemons()
def _RefreshConnection(self): if self._scheme == 'http': self._connection = httplib.HTTPConnection(self._host, self._port, timeout=self._timeout) elif self._scheme == 'https': self._connection = httplib.HTTPSConnection(self._host, self._port, timeout=self._timeout) try: self._connection.connect() except: raise Exception('Could not connect to ' + HC.u(self._host) + '!')
def StartServer(*args, **kwargs): try: connection = httplib.HTTPConnection('127.0.0.1', port, timeout=10) try: connection.connect() connection.close() text = 'The client\'s local server could not start because something was already bound to port ' + HC.u( port) + '.' text += os.linesep * 2 text += 'This usually means another hydrus client is already running and occupying that port. It could be a previous instantiation of this client that has yet to shut itself down.' text += os.linesep * 2 text += 'You can change the port this client tries to host its local server on in file->options.' wx.CallLater(1, HC.ShowText, text) except: self._local_service = reactor.listenTCP( port, HydrusServer.HydrusServiceLocal( HC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE, 'This is the local file service.')) connection = httplib.HTTPConnection('127.0.0.1', port, timeout=10) try: connection.connect() connection.close() except: text = 'Tried to bind port ' + HC.u( port) + ' for the local server, but it failed.' wx.CallLater(1, HC.ShowText, text) except Exception as e: wx.CallAfter(HC.ShowException, e)
def ParseFileArguments(path): HydrusImageHandling.ConvertToPngIfBmp(path) hash = HydrusFileHandling.GetHashFromPath(path) try: (size, mime, width, height, duration, num_frames, num_words) = HydrusFileHandling.GetFileInfo(path) except HydrusExceptions.SizeException: raise HydrusExceptions.ForbiddenException('File is of zero length!') except HydrusExceptions.MimeException: raise HydrusExceptions.ForbiddenException('Filetype is not permitted!') except Exception as e: raise HydrusExceptions.ForbiddenException(HC.u(e)) args = {} args['path'] = path args['hash'] = hash args['size'] = size args['mime'] = mime if width is not None: args['width'] = width if height is not None: args['height'] = height if duration is not None: args['duration'] = duration if num_frames is not None: args['num_frames'] = num_frames if num_words is not None: args['num_words'] = num_words if mime in HC.IMAGES: try: thumbnail = HydrusFileHandling.GenerateThumbnail(path) except: raise HydrusExceptions.ForbiddenException( 'Could not generate thumbnail from that file.') args['thumbnail'] = thumbnail return args
def _errbackHandleProcessingError(self, failure, request): do_yaml = True try: # the error may have occured before user agent was set up! if not request.is_hydrus_user_agent: do_yaml = False except: pass if do_yaml: default_mime = HC.APPLICATION_YAML default_encoding = lambda x: yaml.safe_dump(HC.u(x)) else: default_mime = HC.TEXT_HTML default_encoding = lambda x: HC.u(x) if failure.type == KeyError: response_context = HC.ResponseContext( 403, mime=default_mime, body=default_encoding( 'It appears one or more parameters required for that request were missing:' + os.linesep + failure.getTraceback())) elif failure.type == HydrusExceptions.PermissionException: response_context = HC.ResponseContext(401, mime=default_mime, body=default_encoding( failure.value)) elif failure.type == HydrusExceptions.ForbiddenException: response_context = HC.ResponseContext(403, mime=default_mime, body=default_encoding( failure.value)) elif failure.type == HydrusExceptions.NotFoundException: response_context = HC.ResponseContext(404, mime=default_mime, body=default_encoding( failure.value)) elif failure.type == HydrusExceptions.NetworkVersionException: response_context = HC.ResponseContext(426, mime=default_mime, body=default_encoding( failure.value)) elif failure.type == HydrusExceptions.SessionException: response_context = HC.ResponseContext(403, mime=default_mime, body=default_encoding( failure.value)) else: print(failure.getTraceback()) response_context = HC.ResponseContext( 500, mime=default_mime, body=default_encoding( 'The repository encountered an error it could not handle! Here is a dump of what happened, which will also be written to your client.log file. If it persists, please forward it to [email protected]:' + os.linesep * 2 + failure.getTraceback())) request.hydrus_response_context = response_context return request
import urllib import wx import yaml from twisted.internet import reactor, defer from twisted.internet.threads import deferToThread from twisted.web.server import Request, Site, NOT_DONE_YET from twisted.web.resource import Resource from twisted.web.static import File as FileResource, NoRangeStaticProducer from twisted.python import log CLIENT_ROOT_MESSAGE = '''<html> <head> <title>hydrus client</title> </head> <body> <p>This hydrus client uses software version ''' + HC.u( HC.SOFTWARE_VERSION) + ''' and network version ''' + HC.u( HC.NETWORK_VERSION) + '''.</p> <p>It only serves requests from 127.0.0.1.</p> </body> </html>''' ROOT_MESSAGE_BEGIN = '''<html> <head> <title>hydrus service</title> </head> <body> <p>This hydrus service uses software version ''' + HC.u( HC.SOFTWARE_VERSION) + ''' and network version ''' + HC.u( HC.NETWORK_VERSION) + '''.</p> <p>'''
def OnInit(self): HC.app = self try: self.Bind(HC.EVT_PUBSUB, self.EventPubSub) self._db = ServerDB.DB() threading.Thread(target=self._db.MainLoop, name='Database Main Loop').start() self.Bind(wx.EVT_MENU, self.EventExit, id=wx.ID_EXIT) self._managers = {} self._managers[ 'restricted_services_sessions'] = HydrusSessions.HydrusSessionManagerServer( ) self._managers[ 'messaging_sessions'] = HydrusSessions.HydrusMessagingSessionManagerServer( ) HC.pubsub.sub(self, 'ActionService', 'action_service') self._services = {} # self.Bind(wx.EVT_TIMER, self.TIMEREventMaintenance, id=ID_MAINTENANCE_EVENT_TIMER) self._maintenance_event_timer = wx.Timer( self, ID_MAINTENANCE_EVENT_TIMER) self._maintenance_event_timer.Start(MAINTENANCE_PERIOD * 1000, wx.TIMER_CONTINUOUS) # (service_type, options) = self.Read('service_info', HC.SERVER_ADMIN_KEY) port = options['port'] connection = httplib.HTTPConnection('127.0.0.1', port, timeout=10) try: connection.connect() connection.close() message = 'Something was already bound to port ' + HC.u(port) wx.MessageBox(message) return False except: pass # service_keys = self.Read('service_keys') for service_key in service_keys: self.ActionService(service_key, 'start') self.StartDaemons() if HC.PLATFORM_WINDOWS: self._tbicon = TaskBarIcon() else: stay_open_frame = wx.Frame(None, title='Hydrus Server') stay_open_frame.SetBackgroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) stay_open_frame.SetIcon( wx.Icon(HC.STATIC_DIR + os.path.sep + 'hydrus.ico', wx.BITMAP_TYPE_ICO)) wx.StaticText(stay_open_frame, label='The hydrus server is now running.' + os.linesep * 2 + 'Close this window to stop it.') (x, y) = stay_open_frame.GetEffectiveMinSize() stay_open_frame.SetInitialSize((x, y)) stay_open_frame.Show() return True except Exception as e: print(traceback.format_exc()) return False
<font color="gray">MM</font>:::::::::::::::::<font color="gray">M</font>::::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::::::::::<font color="gray">M</font>::::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::::::::::<font color="gray">M</font>::::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::::::::<font color="gray">M</font>:::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::::::::<font color="gray">M</font>:::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::::::<font color="gray">M</font>::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::::::<font color="gray">M</font>::::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::::<font color="gray">M</font>:::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::::<font color="gray">M</font>:::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::<font color="gray">M</font>::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::<font color="gray">M</font>::::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::::::<font color="gray">M</font>:::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::<font color="gray">M</font>:::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::::<font color="gray">M</font>::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::<font color="gray">M</font>::::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::<font color="gray">M</font>:::::::::::::::::::<font color="gray">MMM</font> THIS IS THE HYDRUS SERVER ADMIN SERVICE, VERSION ''' + HC.u( HC.SOFTWARE_VERSION) + ''' <font color="gray">MM</font>:<font color="gray">M</font>:::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MMM</font>::::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::::::::::::::::::<font color="gray">MMM</font> <font color="gray">M</font>:::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>:::::::::::::::<font color="gray">MMM</font> <font color="gray">MM</font>::::<font color="gray">M</font>:::::::::<font color="gray">MMM</font>: <font color="gray">mMM</font>::::<font color="gray">MM</font>:::::::<font color="gray">MMMM</font> <font color="gray">MMM</font>:::::::::::<font color="gray">MMM</font>:<font color="gray">M</font> <font color="gray">mMM</font>:::<font color="gray">M</font>:::::::<font color="gray">M</font>:<font color="gray">M</font>:<font color="gray">M</font> <font color="gray">MM</font>::<font color="gray">MMMM</font>:::::::<font color="gray">M</font>:<font color="gray">M</font> <font color="gray">MM</font>::<font color="gray">MMM</font>::::::::<font color="gray">M</font>:<font color="gray">M</font> <font color="gray">mMM</font>::<font color="gray">MM</font>::::::::<font color="gray">M</font>:<font color="gray">M</font> <font color="gray">MM</font>::<font color="gray">MM</font>:::::::::<font color="gray">M</font>:<font color="gray">M</font> <font color="gray">MM</font>::<font color="gray">MM</font>::::::::::<font color="gray">M</font>:<font color="gray">m</font>
def _GetCurrentFrame( self ): if self._cv_mode: ( retval, numpy_image ) = self._cv_video.read() if not retval: self._next_render_index = ( self._next_render_index + 1 ) % self._num_frames raise HydrusExceptions.CantRenderWithCVException( 'CV could not render frame ' + HC.u( self._next_render_index - 1 ) + '.' ) else: if self._pil_image.mode == 'P' and 'transparency' in self._pil_image.info: # I think gif problems are around here somewhere; the transparency info is not converted to RGBA properly, so it starts drawing colours when it should draw nothing current_frame = self._pil_image.convert( 'RGBA' ) if self._pil_canvas is None: self._pil_canvas = current_frame else: self._pil_canvas.paste( current_frame, None, current_frame ) # use the rgba image as its own mask else: self._pil_canvas = self._pil_image numpy_image = HydrusImageHandling.GenerateNumPyImageFromPILImage( self._pil_canvas ) self._next_render_index = ( self._next_render_index + 1 ) % self._num_frames if self._next_render_index == 0: self._RewindGIF() else: if not self._cv_mode: self._pil_image.seek( self._next_render_index ) if self._pil_image.palette == self._pil_global_palette: # for some reason, when pil falls back from local palette to global palette, a bunch of important variables reset! pil_image.palette.dirty = self._pil_dirty pil_image.palette.mode = self._pil_mode pil_image.palette.rawmode = self._pil_rawmode return numpy_image
def Request(self, method, path_and_query, request_headers, body, report_hooks=[], response_to_path=False): if method == HC.GET: method_string = 'GET' elif method == HC.POST: method_string = 'POST' if 'User-Agent' not in request_headers: request_headers['User-Agent'] = 'hydrus/' + HC.u( HC.NETWORK_VERSION) # it is important to only send str, not unicode, to httplib # it uses += to extend the message body, which propagates the unicode (and thus fails) when # you try to push non-ascii bytes as the body (e.g. during a file upload!) method_string = str(method_string) path_and_query = str(path_and_query) request_headers = { str(k): str(v) for (k, v) in request_headers.items() } try: self._connection.request(method_string, path_and_query, headers=request_headers, body=body) response = self._connection.getresponse() except (httplib.CannotSendRequest, httplib.BadStatusLine): # for some reason, we can't send a request on the current connection, so let's make a new one and try again! self._RefreshConnection() self._connection.request(method_string, path_and_query, headers=request_headers, body=body) response = self._connection.getresponse() if response.status == 200 and response_to_path: (temp_path, size_of_response) = self._WriteResponseToPath( response, report_hooks) parsed_response = temp_path else: (parsed_response, size_of_response) = self._ParseResponse(response, report_hooks) response_headers = { k: v for (k, v) in response.getheaders() if k != 'set-cookie' } cookies = self._ParseCookies(response.getheader('set-cookie')) self._last_request_time = HC.GetNow() if response.status == 200: return (parsed_response, None, size_of_response, response_headers, cookies) elif response.status in (301, 302, 303, 307): location = response.getheader('Location') if location is None: raise Exception(parsed_response) else: url = location if ' ' in url: # some booru is giving daft redirect responses print(url) url = urllib.quote(url, safe='/?=&') print(url) if not url.startswith(self._scheme): # assume it is like 'index.php' or '/index.php', rather than 'http://blah.com/index.php' if url.startswith('/'): slash_sep = '' else: slash_sep = '/' url = self._scheme + '://' + self._host + slash_sep + url if response.status in (301, 307): # 301: moved permanently, repeat request # 307: moved temporarily, repeat request redirect_info = (method, url) elif response.status in (302, 303): # 302: moved temporarily, repeat request (except everyone treats it like 303 for no good f*****g reason) # 303: thanks, now go here with GET redirect_info = (HC.GET, url) return (parsed_response, redirect_info, size_of_response, response_headers, cookies) elif response.status == 304: raise HydrusExceptions.NotModifiedException() else: if response.status == 401: raise HydrusExceptions.PermissionException(parsed_response) elif response.status == 403: raise HydrusExceptions.ForbiddenException(parsed_response) elif response.status == 404: raise HydrusExceptions.NotFoundException(parsed_response) elif response.status == 426: raise HydrusExceptions.NetworkVersionException(parsed_response) elif response.status in (500, 501, 502, 503): raise Exception(parsed_response) else: raise Exception(parsed_response)
def _check_network_version( self, network_version ): if network_version != HC.NETWORK_VERSION: if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'This server is out of date; please ask its admin to update to the latest release.' message = 'Network version mismatch! This server\'s network version is ' + HC.u( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + HC.u( network_version ) + '! ' + message raise HydrusExceptions.NetworkVersionException( message )