#!/usr/bin/env python # The Gopher CGI Library v0.2 # Provides functions for creating moles for the gopher protocol in python # # Copyright (c) 2011 by Christopher Yealy (octotep at sdf.lonestar.org) # Permission is granted for the user to use, modify, copy, and publish # any modifications however they like. # Note that the software is provided "as is" with no warranty whatsoever; # implied or otherwise. # # Documentation can be found at: # gopher://sdf.org/1/users/octotep/downloads/gophercgi import textwrap import re def print_text(text, line_length=67): """ Prints a line of text by formatting it as a gopher selector and word-wrapping the text to the 'line_length' variable. """ string = textwrap.fill(text, line_length) for line in string.split('\n'): print "i%s\t\terror.host\t0" % (line) def print_para(text, line_length=67): """ Prints a paragraph(s) of text by word-wrapping each paragraph, while preserving any newline characters. Word-wraps to the 'line_length' variable. """ for para in text.split("\n"): print_text(para, line_length) def print_error(text, line_length=67): """ Prints a string as an itemtype-3 gopher selector (error), while wrapping the text to the 'line_length' variable. """ string = textwrap.fill(text, line_length) for line in string.split('\n'): print "3%s\t\terror.host\t0" % (line) def print_link(link_type, link_text, dir_path, host, port=70): """ Prints a gopher selector link using the arguments provided. """ print "%s%s\t%s\t%s\t%s" % (link_type, link_text, dir_path, host, port) def print_telnet(link_text, host, port=23): """ Prints a telnet link, using the arguments provided. """ print "8%s\t\t%s\t%s" % (link_text, host, port) def print_special(link_text, special_url): """ Prints an external link to any url, not just gopher. """ print "h%s\tURL:%s\tspecial.link\t70" % (link_text, special_url) def print_line(): """ Prints a blank line. """ print "i error.host 0" def get_arg_list(args_str, separator, prefix): """ Converts a string containing arguments given to the mole into a list for easy use. 'args_str' is a string contaning the arguments. 'seperator' is the character that separates each argument 'prefix' is a part at the beginning of the string which contains no arguments and will be removed from the results. Returns a list of the arguments from the string. """ if args_str.startswith(prefix): pre_len = len(prefix) args = args_str[pre_len:] args_list = args.split(separator) else: args = args_str args_list = args.split(separator) return args_list def get_arg_dict(args_str, separator, prefix, dict_separator="="): """ Converts a string containing key-value pairs given to the mole into a dictionary for easy use. 'args_str' is a string containing the arguments. 'seperator' is the character which separates the pairs from each other. 'prefix' is a part at the beginning of the string which contains no arguments and will be removed from the results. 'dict_separator' is the character which separates each key from its respective value Returns a dictionary of the arguments from the string. """ if args_str.startswith(prefix): pre_len = len(prefix) args = args_str[pre_len:] args_list = args.split(separator) else: args = args_str args_list = args.split(separator) args_dict = {} for part in args_list: key, value = part.split(dict_separator) args_dict[key] = value return args_dict def tabs_to_spaces(text, tab_size=8): """ Converts all the tab characters in 'text' to spaces. 'tab_size' indicates the size of the tab stops. Returns the converted string. """ text_arr = [] for line in text.split("\n"): string = "" counter = 0 for letter in line: if (letter != "\t"): string = "%s%s" % (string, letter) counter += 1 else: indent = tab_size - (counter % tab_size) space = " " * indent string = "%s%s" % (string, space) counter += indent text_arr.append(string) return "\n".join(text_arr) def gs_to_text(gm_text, show_prefixes=True, show_links=True): """ Converts text formatted as a gopher selectors into plain text. Bears similarities to `lynx -dump` 'show_prefixes' controls whether each selector that isn't text gets a label to identify what type of link it is. 'show_links' controls whether a list of URL's is printed at the bottom of the output. Returns the converted text. """ final_list = [] link_list = [] counter = 0 gm_lines = gm_text.splitlines() for line in gm_lines: if len(line) == "": line = "i\t\terror.host\t0" itemtype = line[:1] prefix = "" suffix = "" tabs = line.split("\t") text = tabs.pop(0) if show_links: if (itemtype != 'i') and (itemtype != '3'): counter += 1 suffix = " [%s]" % (str(counter)) path = tabs.pop(0) host = tabs.pop(0) port = tabs.pop(0) url = _return_url(itemtype, host, path, port) link_list.append("%s. %s" % (suffix, url)) if show_prefixes: prefix = _return_prefix(itemtype) final_list.append("%s\t%s%s" % (prefix, text[1:], suffix)) final_str = "\n".join(final_list) if show_links: link_str = "\n".join(link_list) final_str = "%s\n\n%s" % (final_str, link_str) return final_str def gm_to_gs(menu_text): """ Converts text formatted as a gophermap into gopher selectors. Returns the converted text. """ regex = re.compile('[\w\+].*?\t.*?\t.*?\t\d.*') final_list = [] text_lines = menu_text.splitlines() for line in text_lines: match = regex.match(line) if match: final_list.append(line) else: new_line = "i%s\t\terror.host\t0" % (line) final_list.append(new_line) return "\n".join(final_list) def _return_url(itemtype, host, path, port): """ Takes parameters and creates a URL based on the itemtype. Used internally by the library. Returns the URL string. """ if len(path) != 0: if path[0] == '/': tmp_path = path[1:] path = tmp_path if str(itemtype) == '8': return "telnet://%s:%s/%s" % (host, port, path) elif str(itemtype) == 'h': # Check for URL: if path[:4] == 'URL:': return path[4:] else: return "gopher://%s:%s/%s/%s" % (host, port, itemtype, path) else: return "gopher://%s:%s/%s/%s" % (host, port, itemtype, path) def _return_prefix(itemtype): """ Returns a text label based on itemtype. Used internally by the library. """ if itemtype == 'i': return "" elif itemtype == '0': return "Text:" elif itemtype == '1': return "Dir:" elif itemtype == '2': return "CSO:" elif itemtype == '3': return "!!!:" elif itemtype == '4': return "File:" elif itemtype == '5': return "File:" elif itemtype == '6': return "File:" elif itemtype == '7': return "?:" elif itemtype == '8': return "Tel:" elif itemtype == '9': return "File:" elif itemtype == 'g': return "GIF:" elif itemtype == 'I': return "Image:" elif itemtype == 'T': return "Tel:" elif itemtype == 's': return "Snd:" elif itemtype == 'p': return "PNG:" elif itemtype == 'd': return "PDF:" elif itemtype == 'x': return "XML:" elif itemtype == 'c': return "CSS:" elif itemtype == 'h': return "HTML:" else: return "UnKN:"