# GopherObject.py # $Id: GopherObject.py,v 1.17 2001/07/09 22:31:32 s2mdalle Exp $ # Written by David Allen # Released under the terms of the GNU General Public License # # Base class for GopherResource, GopherResponse # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ############################################################################# import re import os import utils from string import * from gopher import * GopherObjectException = "Whoops...something went wrong!" class GopherObject: def __init__(self, typecode = None, host = None, port = None, locator = None, name = None, len = -2): self.__class = "GopherObject" self._shouldCache = "YES" self.setTypeCode(typecode) self.setHost(host) self.setPort(port) self.setLocator(locator) self.setName(name) self.setLen(len) self.setDataBlock("") return None def dup(self, res): """Returns a copy of this object.""" self.setLen(res.getLen()) self.setTypeCode(res.getTypeCode()) self.setHost(res.getHost()) self.setLocator(res.getLocator()) self.setName(res.getName()) self.setPort(res.getPort()) return self # Accessors, mutators def shouldCache(self): return self._shouldCache def setShouldCache(self, boolval): self._shouldCache = boolval return self.getShouldCache() def getShouldCache(self): return self._shouldCache def getLen(self): return self.len def setLen(self, newlen): self.len = newlen return self.len def getTypeCode(self): return self.type[0] def setDataBlock(self, block): self.datablock = block return self.datablock def getDataBlock(self): return self.datablock def setType(self, newtype): return self.setTypeCode(newtype) def setTypeCode(self, newtype): self.type = newtype return self.type def getType(self): """Return a string representing the type code of the response. See the gopher module for more information.""" try: return responses[self.type] except KeyError: return "-Unknown-" def getHost(self): return self.host def setHost(self, newhost): self.host = newhost return self.host def getPort(self): return self.port def setPort(self, newport): self.port = newport return self.port def getLocator(self): return self.locator def setLocator(self, newlocator): self.locator = newlocator return self.locator def getName(self): if strip(self.name) == '/': self.setName("%s root" % self.getHost()) elif self.name == '' or self.name is None: loc = strip(self.getLocator()) if loc == '' or loc == '/': self.setName("%s root" % self.getHost()) else: self.setName(" ") # self.setName("%s %s" % (self.getHost(), self.getLocator())) return self.name def setName(self, newname): self.name = newname return self.name # Methods def toURL(self): """Return the URL form of this GopherResource""" return "gopher://%s:%s/%s%s" % (self.getHost(), self.getPort(), self.getTypeCode(), re.sub("\t", "%9;", self.getLocator())) def toProtocolString(self): """Returns the protocol string, i.e. how it would have been served by the server, in a string.""" return "%s%s\t%s\t%s\t%s\r\n" % (self.getTypeCode(), self.getName(), self.getLocator(), self.getHost(), self.getPort()) def toXML(self): """Returns a small XML tree corresponding to this object. The root element is the name of the object. Override me in subclasses.""" tags = [["type", self.type], ["locator", self.locator], ["host", self.host], ["port", self.port], ["name", self.name]] str = "" for tag in tags: str = str + "<%s>%s" % (tag[0], tag[1], tag[0]) str = str + "" return str def __str__(self): return self.__class # return self.toString() def toString(self): """Returns a string form of this object. Mostly only good for debugging.""" return ("Type: %s\nLocator: %s\nHost: %s\nPort: %s\nName: %s\n" % (self.getTypeCode(), self.getLocator(), self.getHost(), self.getPort(), self.getName())) def filenameToURL(self, filename): """Unencodes filenames returned by toFilename() into URLs""" try: return utils.character_replace(filename, os.sep, "/") except: # os.sep is '/' - character_replace doesn't allow replacing a # character with itself. we're running Eunuchs. return filename def toCacheFilename(self): filename = self.toFilename() lastchr = filename[len(filename)-1] if lastchr == os.sep or lastchr == '/': # Pray for no name clashes... :) # We have to call it something inside the leaf directory, because # if you don't, you get into the problem of caching responses from # directories as files, and not having a directory to put the items # in the directory in. And you can't call the file "" on any # filesystem. :) filename = "%sgopherdir.idx" % filename elif self.getTypeCode() == RESPONSE_DIR: filename = "%s%sgopherdir.idx" % (filename, os.sep) port = self.getPort() str_to_find = ":%d" % int(port) # Cut out the port portion of the filename. This is because some # OS's throw up with ':' in filenames. Bummer, but this will make it # hard to translate a filename/path -> URL ind = find(filename, str_to_find) if ind != -1: filename = "%s%s" % (filename[0:ind], filename[ind+len(str_to_find):]) if os.sep == '\\': # No-name mac wannabe OS's... :) for char in ['/', ':', ';', '%', '*', '|']: # This isn't necessarily a good idea, but it's somewhat # necessary for windows boxen. filename = utils.character_replace(filename, char, ' ') return filename def toFilename(self): """Returns the name of a unique file containing the elements of this object. This file is not guaranteed to not exist, but it probably doesn't. :) Get rid of all of the slashes, since they are Frowned Upon (TM) by most filesystems.""" replaceables = ['\t', '\n', '\\', '/'] data = self.toURL() if find(lstrip(lower(data)), "gopher://") == 0: # Chomp the "gopher://" part data = data[len("gopher://"):] for r in replaceables: try: data = utils.character_replace(data, r, os.sep) except: pass return data