Gopher protocol

From Encyclopedia Dramatica
Jump to navigation Jump to search
Gopher Protocol faggot gopher

Gopher protocol is another protocol as it can be http or ftp. Its from the 90s, so only oldfags could know about it. Its more web 1.0 than Usenet or IRC. At the present is nearly dead, but there are some people still using it.

What is it?

The Gopher protocol is a TCP/IP application layer protocol designed for distributing, searching, and retrieving documents over the Internet. The Gopher protocol was strongly oriented towards a menu-document design and presented an alternative to the World Wide Web in its early stages, but ultimately HTTP became the dominant protocol. The Gopher ecosystem is often regarded as the effective predecessor of the World Wide Web.

The protocol was invented by a team led by Mark P. McCahill at the University of Minnesota. It offers some features not natively supported by the Web and imposes a much stronger hierarchy on information stored on it. Its text menu interface is well-suited to computing environments that rely heavily on remote text-oriented computer terminals, which were still common at the time of its creation in 1991, and the simplicity of its protocol facilitated a wide variety of client implementations. More recent Gopher revisions and graphical clients added support for multimedia. Gopher was preferred by many network administrators for using fewer network resources than Web services.

Gopher's hierarchical structure provided a platform for the first large-scale electronic library connections. Gopher has been described by some enthusiasts as "faster and more efficient and so much more organised" than today's Web services. The Gopher protocol is still in use by enthusiasts, and a small population of actively maintained servers remain although it has been almost entirely supplanted by the Web.

What can you find on Gopher?

  • ASCII pr0n
  • ASCII pr0n
  • Ancient web sites
  • Archives of all kind
  • Faggots
  • ASCII pr0n
  • Gopherchan

How to access Gopher sites?

You need a browser compatible with gopher protocol, of the main browsers the only one that supports it is Mozilla Firefox and its forks by installing an addon called OverbiteFF. Once you install it you can access a bigger ammount of the net, since search engines dont index gopher sites, so its the best place to hide something online apart from local servers or in Onionland.

How to browse them?

Do I need to explain this???? If you cant navigate properly on gopher sites GTFO of the internet.

Gopher sites

NOTE: there are more


Gopherchan index

Gopherchan is probably the most web 1.0 chan out there, its also one of the smallests, it only has 2 boards: /b/ and /paste/ and to be able to post on it you need to use the following python file as explained:

#!/usr/bin/env python

# client configuration

nickname = 'anon'
delpass = 'lofasz'
handler = ''
editor = 'vim "+set tw=70" -c startinsert'

# below, the urllib2_file library is embedded
# got it from:
# Version: 0.2.0
#  - UTF-8 filenames are now allowed (Eli Golovinsky)<br/>
#  - File object is no more mandatory, Object only needs to have seek() read() attributes (Eli Golovinsky)<br/>
# Version: 0.1.0
#  - upload is now done with chunks (Adam Ambrose)
# Version: older
# bug fix: kosh @T
# HTTPS support : Ryan Grow <ryangrow @T>

# Copyright (C) 2004,2005,2006 Fabien SEISEN
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
# you can contact me at: <[email protected]>
# Also modified by Adam Ambrose (aambrose @T to write data in
# chunks (hardcoded to CHUNK_SIZE for now), so the entire contents of the file
# don't need to be kept in memory.
enable to upload files using multipart/form-data

idea from:
upload files in python: overriding Python socket API:

import urllib2_files
import urllib2
u = urllib2.urlopen('' [, data])

data can be a mapping object or a sequence of two-elements tuples
(like in original urllib2.urlopen())
varname still need to be a string and
value can be string of a file object
  ((varname, value),
   (varname2, value),
  { name:  value,
    name2: value2


import os
import socket
import sys
import stat
import mimetypes
import mimetools
import httplib
import urllib
import urllib2

CHUNK_SIZE = 65536

def get_content_type(filename):
	return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

# if sock is None, juste return the estimate size
def send_data(v_vars, v_files, boundary, sock=None):
	l = 0
	for (k, v) in v_vars:
		buffer += '--%s\r\n' % boundary
		buffer += 'Content-Disposition: form-data; name="%s"\r\n' % k
		buffer += '\r\n'
		buffer += v + '\r\n'
		if sock:
		l += len(buffer)
	for (k, v) in v_files:
		fd = v
		file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
		name ='/')[-1]
		if isinstance(name, unicode):
			name = name.encode('UTF-8')
		buffer += '--%s\r\n' % boundary
		buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' \
				  % (k, name)
		buffer += 'Content-Type: %s\r\n' % get_content_type(name)
		buffer += 'Content-Length: %s\r\n' % file_size
		buffer += '\r\n'

		l += len(buffer)
		if sock:
			if hasattr(fd, 'seek'):
			while True:
				chunk =
				if not chunk: break

		l += file_size
	buffer += '--%s--\r\n' % boundary
	buffer += '\r\n'
	if sock:
	l += len(buffer)
	return l

# mainly a copy of HTTPHandler from urllib2
class newHTTPHandler(urllib2.BaseHandler):
	def http_open(self, req):
		return self.do_open(httplib.HTTP, req)

	def do_open(self, http_class, req):
		data = req.get_data()
		# mapping object (dict)
		if req.has_data() and type(data) != str:
			if hasattr(data, 'items'):
				data = data.items()
					if len(data) and not isinstance(data[0], tuple):
						raise TypeError
				except TypeError:
					ty, va, tb = sys.exc_info()
					raise TypeError, "not a valid non-string sequence or mapping object", tb
			for (k, v) in data:
				if hasattr(v, 'read'):
					v_files.append((k, v))
					v_vars.append( (k, v) )
		# no file ? convert to string
		if len(v_vars) > 0 and len(v_files) == 0:
			data = urllib.urlencode(v_vars)
		host = req.get_host()
		if not host:
			raise urllib2.URLError('no host given')

		h = http_class(host) # will parse host:port
		if req.has_data():
			h.putrequest('POST', req.get_selector())
			if not 'Content-type' in req.headers:
				if len(v_files) > 0:
					boundary = mimetools.choose_boundary()
					l = send_data(v_vars, v_files, boundary)
								'multipart/form-data; boundary=%s' % boundary)
					h.putheader('Content-length', str(l))
					if not 'Content-length' in req.headers:
						h.putheader('Content-length', '%d' % len(data))
			h.putrequest('GET', req.get_selector())

		scheme, sel = urllib.splittype(req.get_selector())
		sel_host, sel_path = urllib.splithost(sel)
		h.putheader('Host', sel_host or host)
		for name, value in self.parent.addheaders:
			name = name.capitalize()
			if name not in req.headers:
				h.putheader(name, value)
		for k, v in req.headers.items():
			h.putheader(k, v)
		# httplib will attempt to connect() here.  be prepared
		# to convert a socket error to a URLError.
		except socket.error, err:
			raise urllib2.URLError(err)

		if req.has_data():
			if len(v_files) >0:
				l = send_data(v_vars, v_files, boundary, h)
			elif len(v_vars) > 0:
				# if data is passed as dict ...
				data = urllib.urlencode(v_vars)
				# "normal" urllib2.urlopen()

		code, msg, hdrs = h.getreply()
		fp = h.getfile()
		if code == 200:
			resp = urllib.addinfourl(fp, hdrs, req.get_full_url())
			resp.code = code
			resp.msg = msg
			return resp
			return self.parent.error('http', req, fp, code, msg, hdrs)

urllib2._old_HTTPHandler = urllib2.HTTPHandler
urllib2.HTTPHandler = newHTTPHandler

class newHTTPSHandler(newHTTPHandler):
	def https_open(self, req):
		return self.do_open(httplib.HTTPS, req)
urllib2.HTTPSHandler = newHTTPSHandler

# Here comes the gopherchan client code.

if __name__ == '__main__':
	import getopt
	import urllib2
	import string
	import sys
	import os
	import tempfile

	# print short usage instructions
	def usage(progname):
		print """
Usage: %s [-n nickname] [-d delpass] [-m message] [-f file] [-k killpostno] (-b board | -t threadname)
""" % progname

	board = False 
	message = False
	file = False
	thread = False
	kill = False

	# read command line args

		opts, args = getopt.getopt(sys.argv[1:], 'hn:d:m:f:b:k:t:M:')
	except getopt.GetoptError, errmsg:
		print "ERROR:", errmsg

	for name, value in opts:
		if name == '-h':
		elif name == '-n':
			nickname = value
		elif name == '-d':
			delpass = value
		elif name == '-m':
			message = value
		elif name == '-f':
			file = value
		elif name == '-b':
			board = value
		elif name == '-k':
			kill = value
		elif name == '-t':
			thread = value
		elif name == '-M':
				fn = open(value, 'r')
				message =
			except IOError:
				print "Failed to read message from file"
			print "invalid argument:", name

	if(args != []):
		print "Superfluous arguments"

	if(kill != False):
		if(board == False):
			print "To kill a post, you must specify the board as well"

	if(thread == False and board == False):
		print "Either the thread or the board has to be specified."
	if(thread != False and board != False):
		print "The thread and the board can't be both specified at the same time"

	# open image file
	fileobj = False
	if(file != False):
			fileobj = open(file, 'rb')
		except IOError:
			print "Failed to open image file."

	# launch external editor to edit message
	if(message == False and kill == False):
		tf = tempfile.mkstemp('.txt', 'chan-');
		if(os.system(editor + " '" + tf[1] + "'") != 0):
			print "Calling the editor failed:", editor + " '" + tf[1] + "'"
		mf = open(tf[1], 'r')
		message =
		if(message == ''):
			print "Empty message, aborted"

		opts = {
			'author': nickname,
			'pass': delpass,
			'text': message,
			'board': '',
			'thread': ''
		if(fileobj != False):
			opts['image'] = fileobj
		if(board != False):
			opts['board'] = board
		if(thread != False):
			opts['thread'] = thread
		if(kill != False):
			opts['kill'] = kill

		u = urllib2.urlopen(handler, opts)
	except urllib2.HTTPError, errobj:
		print "HTTP error:", errobj.code

To post a comment:

Customize this part of the .py file:

   nickname = 'anon'
   delpass = 'lofasz'
   handler = ''
   editor = 'vim "+set tw=70" -c startinsert'

And then use it like this:

   ./ [-n nickname] [-d delpass] [-m message] [-f file] [-k killpostno] (-b board | -t threadname)

If you want to use a .txt file as message, use -M instead of -m.

External links

Gopher protocol
is part of a series on Web 1.0


Old Memes  • Celebs, h4x0rz, and Phreaks  • Technologies  • Fun and Games  • Events  • Death of Web1.0
Click topics to expand

Softwarez series.jpg

Gopher protocol is part of a series on


Visit the Softwarez Portal for complete coverage.


Gopher protocol is part of a series on


Visit the Chans Portal for complete coverage.