2
# -*- coding: utf-8 -*-
3
# nautilus-pastebin - Nautilus extension to paste a file to a pastebin service
5
# Alessio Treglia <quadrispro@ubuntu.com>
6
# Copyright (C) 2009, Alessio Treglia
8
# Part of this code has been taken from pastebinit script
9
# pastebinit was written by:
10
# Stéphane Graber <stgraber@stgraber.org>
11
# Daniel Bartlett <dan@f-box.org>
12
# David Paleino <d.paleino@gmail.com>
13
# URL: http://www.stgraber.org/download/projects/pastebin/
14
# Copyright (C) 2006-2009, Stéphane Graber, Daniel Bartlett, David Paleino
15
# Distributed under the terms of the GNU GPL-2 license
17
# This package is free software; you can redistribute it and/or modify
18
# it under the terms of the GNU General Public License as published by
19
# the Free Software Foundation; either version 2 of the License, or
20
# (at your option) any later version.
22
# This package is distributed in the hope that it will be useful,
23
# but WITHOUT ANY WARRANTY; without even the implied warranty of
24
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
# GNU General Public License for more details.
27
# You should have received a copy of the GNU General Public License
28
# along with this package; if not, write to the Free Software
29
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36
from ConfigParser import ConfigParser
39
GLOBALCONFIG_FILENAME = '/etc/nautilus-pastebin.conf'
40
USERCONFIG_FILENAME = os.path.expanduser('~/.config/nautilus-pastebin/nautilus-pastebin.conf')
42
class ConfigFileException(Exception):
45
# Custom urlopener to handle 401's
46
class pasteURLopener(urllib.FancyURLopener):
47
"""Do the HTTP requests."""
48
def http_error_401(self, url, fp, errcode, errmsg, headers, data=None):
51
class GlobalConfigurationValidator(object):
52
"""Configuration wrapper """
53
NEEDED_OPTS = ['pastebin']
54
MAIN_SECTION = 'generals'
57
glbl = dict(self.__config.items(GlobalConfigurationValidator.MAIN_SECTION))
59
# Each needed field must be fill'd.
60
if k in GlobalConfigurationValidator.NEEDED_OPTS and not glbl[k]:
61
#raise ConfigFileException, "Missing required value for %s field!" % k
63
if re.search('enable_.*', k): # In case of boolean value...
64
# ...we should parse it well
65
glbl[k] = self.__config.getboolean(GlobalConfigurationValidator.MAIN_SECTION, k)
66
# Everything seems well-configured
70
def getPastebinConfiguration(self):
71
"""Retrieve and returns the configuration related to the pastebin service."""
72
pastebinConfiguration = None
73
pastebin = self.globals['pastebin']
74
return PastebinConfiguration(self.globals, dict(self.__config.items(pastebin)))
76
def getAvailablePastebins(self):
77
pastebins = self.__config.sections()
78
pastebins.remove(GlobalConfigurationValidator.MAIN_SECTION)
81
def getConfigParser(self): return self.__config
83
def __init__(self, files=[GLOBALCONFIG_FILENAME, USERCONFIG_FILENAME]):
84
self.__config = ConfigParser()
85
self.__config.read(files)
88
class PastebinConfiguration(object):
89
PARAMETERS = ["website",
103
def __setDefaultParameters(self):
104
for k in PastebinConfiguration.PARAMETERS:
105
self.__dict__.setdefault(k,'')
106
if k in self._optionsDict.keys():
107
setattr(self, k, self._optionsDict[k])
109
def __setGlobalParameters(self):
110
for k in self._globalsDict.keys():
111
setattr(self, k, self._globalsDict[k])
113
def __getMappingByName(self, optname):
115
if optname in self._optionsDict:
116
exec(self._optionsDict[optname])
119
def __init__(self, globalsDict, optionsDict):
120
self._optionsDict = optionsDict
121
self._globalsDict = globalsDict
122
self.__setGlobalParameters()
123
self.__setDefaultParameters()
124
self.aliases = self.__getMappingByName('aliases')
125
self.extras = self.__getMappingByName('extras')
126
self.mimetypes = self.__getMappingByName('mimetypes')
127
self.mimetypes.setdefault('text/plain', self._optionsDict['default_mime'])
129
def setFormatByMimeType(self, mimetype):
130
if mimetype in self.mimetypes.keys():
131
self.format = self.mimetypes[mimetype]
132
elif mimetype.split('/')[0] == 'text':
133
self.format = self.mimetypes['text/plain']
139
s = 'Configuration:\n'
140
s += "mimetypes = %s\n" % self.mimetypes.__str__()
141
s += "aliases = %s" % self.aliases.__str__()
142
s += "extras = %s" % self.extras.__str__()
145
def setContent(self, pastefile):
152
self.content = content
153
self.title = os.path.split(pastefile)[-1]
156
class PastebinValidatorFactory(object):
157
"""Singleton factory which returns a validator object dinamically."""
159
class __impl(object):
160
"""Implementation of the class' methods"""
161
def getValidator(self, pasteconf):
162
validator = pasteconf.validator
165
exec("obj = %sValidator(pasteconf)" % validator)
170
def __getattr__(self, attr):
171
return getattr(self.__instance, attr)
172
def __setattr__(self, attr, value):
173
return setattr(self.__instance, attr, value)
176
if PastebinValidatorFactory.__instance is None:
177
PastebinValidatorFactory.__instance = PastebinValidatorFactory.__impl()
178
self.__dict__['_PastebinValidatorFactory__instance'] = PastebinValidatorFactory.__instance
180
class GenericPastebinValidator(object):
181
NOT_EMPTY_FIELDS = ['website', 'content', 'format', 'title']
183
def checkAliases(self):
186
lambda x: x in self.conf.__dict__, self.conf.aliases.keys())
189
def checkExtras(self): return True
191
def __init__(self, pastebinConfiguration):
192
"""Class constructor"""
194
toAdd = getattr(cls, 'notEmptyFields')
195
GenericPastebinValidator.NOT_EMPTY_FIELDS.extend(toAdd)
198
self.conf = pastebinConfiguration
201
"""Do the validation of the configuration file."""
202
if self.conf.user == '':
203
self.conf.user = os.environ.get('USER')
204
return self.checkNotEmpty() and self.checkAliases() and self.checkExtras()
206
def checkNotEmpty(self):
207
"""Verify whether all the opts' keys are non-empty."""
208
return all(map(lambda x: getattr(self.conf, x) != '', GenericPastebinValidator.NOT_EMPTY_FIELDS))
210
def getParameters(self):
213
for k in self.conf.aliases.keys():
214
for v in self.conf.aliases[k]:
215
params[v] = getattr(self.conf, k)
216
for k in self.conf.extras.keys():
217
params[k] = self.conf.extras[k]
220
def updateParametersAfterSending(self): pass
222
class PasteyNetValidator(GenericPastebinValidator):
224
def parentFixup(self, website, parentid):
227
url_opener = pasteURLopener()
228
page = url_opener.open(website + '/' + parentid, None)
229
matches = re.split('<input.*?name="parent".*?value="(.*?)"', page.read())
230
if len(matches) <= 1 or re.match(parentid, matches[1]) == None:
231
# The obfuscated version didn't begin with the partial version,
232
# or unable to find the obfuscated version for some reason!
233
# Create a paste with no parent (should we throw, instead?)
237
def getParameters(self):
238
params = GenericPastebinValidator.getParameters(self)
239
params['parent'] = self.parentFixup(self.conf.website, self.conf.parentid)
242
class Paster(object):
243
def __init__(self, pasteconf):
244
self.pasteconf = pasteconf
247
validator = PastebinValidatorFactory().getValidator(self.pasteconf)
250
if (not validator) or (not validator.validate()):
253
website = self.pasteconf.website
254
params = validator.getParameters()
256
if not re.search(".*/", website):
261
if params.__contains__("page"):
262
website+=params['page']
263
tmp_page=params['page']
264
params.__delitem__("page")
265
if params.__contains__("regexp"):
266
reLink=params['regexp']
267
params.__delitem__("regexp")
268
params = urllib.urlencode(params) #Convert to a format usable with the HTML POST
271
url_opener = pasteURLopener()
272
page = url_opener.open(website, params) #Send the informations and be redirected to the final page
273
summary = 'File pasted to: '
274
URLmarkup = '<a href="%(pasteurl)s">%(pasteurl)s</a>'
275
if reLink: #Check if we have to apply a regexp
276
if website.count(tmp_page) > 1:
277
website = website.rstrip(tmp_page)
279
website = website.replace(tmp_page, "")
280
pasteurl = website + "/" + re.split(reLink, page.read())[1]
283
message = URLmarkup % { 'pasteurl': pasteurl }
285
except Exception, value: