diff --git a/modules/pixtoilelibre/__init__.py b/modules/pixtoilelibre/__init__.py
new file mode 100644
index 00000000..60e84ad8
--- /dev/null
+++ b/modules/pixtoilelibre/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2014 Vincent A
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from .backend import PixtoilelibreBackend
+
+
+__all__ = ['PixtoilelibreBackend']
diff --git a/modules/pixtoilelibre/backend.py b/modules/pixtoilelibre/backend.py
new file mode 100644
index 00000000..97e85417
--- /dev/null
+++ b/modules/pixtoilelibre/backend.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2014 Vincent A
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.tools.backend import BaseBackend
+from weboob.capabilities.paste import ICapPaste, BasePaste
+from weboob.tools.capabilities.paste import image_mime
+import re
+
+from .browser import PixtoilelibreBrowser
+
+
+__all__ = ['PixtoilelibreBackend']
+
+
+class PixPaste(BasePaste):
+ @classmethod
+ def id2url(cls, id):
+ return 'http://pix.toile-libre.org/?img=%s' % id
+
+
+class PixtoilelibreBackend(BaseBackend, ICapPaste):
+ NAME = 'pixtoilelibre'
+ DESCRIPTION = u'toile-libre image hosting website'
+ MAINTAINER = u'Vincent A'
+ EMAIL = 'dev@indigo.re'
+ LICENSE = 'AGPLv3+'
+ VERSION = '0.i'
+
+ BROWSER = PixtoilelibreBrowser
+
+ def can_post(self, contents, title=None, public=None, max_age=None):
+ if re.search(r'[^a-zA-Z0-9=+/\s]', contents):
+ return 0
+ elif max_age:
+ return 0 # expiration is not possible
+ else:
+ mime = image_mime(contents, ('gif', 'jpeg', 'png'))
+ return 20 * int(mime is not None)
+
+ def get_paste(self, id):
+ paste = PixPaste(id)
+ contents = self.browser.get_contents(id)
+ if contents:
+ paste.contents = contents.encode('base64')
+ return paste
+
+ def new_paste(self, *a, **kw):
+ return PixPaste(*a, **kw)
+
+ def post_paste(self, paste, max_age=None):
+ d = self.browser.post_image(paste.title or '-', paste.contents.decode('base64'), private=(not paste.public), description=paste.title)
+ paste.id = d['id']
+ return paste
diff --git a/modules/pixtoilelibre/browser.py b/modules/pixtoilelibre/browser.py
new file mode 100644
index 00000000..687e377d
--- /dev/null
+++ b/modules/pixtoilelibre/browser.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2014 Vincent A
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.tools.browser import BaseBrowser
+from weboob.tools.capabilities.paste import image_mime
+from StringIO import StringIO
+
+from .pages import PageHome, PageImage, PageError
+
+
+__all__ = ['PixtoilelibreBrowser']
+
+
+class PixtoilelibreBrowser(BaseBrowser):
+ PROTOCOL = 'http'
+ DOMAIN = 'pix.toile-libre.org'
+ ENCODING = None
+
+ PAGES = {'%s://%s/' % (PROTOCOL, DOMAIN): PageHome,
+ r'%s://%s/\?action=upload': PageError,
+ r'%s://%s/\?img=(.+)' % (PROTOCOL, DOMAIN): PageImage}
+
+ def post_image(self, filename, contents, private=False, description=''):
+ self.location('/')
+ assert self.is_on_page(PageHome)
+
+ mime = image_mime(contents.encode('base64'))
+ self.select_form(nr=0)
+ self.form.find_control('private').items[0].selected = private
+ self.form['description'] = description or ''
+ self.form.find_control('img').add_file(StringIO(contents), filename=filename, content_type=mime)
+ self.submit()
+
+ assert self.is_on_page(PageImage)
+ return self.page.get_info()
+
+ def get_contents(self, id):
+ return self.readurl('%s://%s/upload/original/%s' % (self.PROTOCOL, self.DOMAIN, id))
diff --git a/modules/pixtoilelibre/pages.py b/modules/pixtoilelibre/pages.py
new file mode 100644
index 00000000..e76d24ca
--- /dev/null
+++ b/modules/pixtoilelibre/pages.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2014 Vincent A
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.tools.browser import BasePage
+import re
+
+
+__all__ = ['PageHome', 'PageImage', 'PageError']
+
+
+class PageHome(BasePage):
+ pass
+
+
+class PageImage(BasePage):
+ def get_info(self):
+ id = re.search(r'img=([^&]+)', self.url).group(1)
+ return {'url': self.url, 'id': id}
+
+
+class PageError(BasePage):
+ pass
diff --git a/modules/pixtoilelibre/test.py b/modules/pixtoilelibre/test.py
new file mode 100644
index 00000000..df56520b
--- /dev/null
+++ b/modules/pixtoilelibre/test.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2014 Vincent A
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.tools.test import BackendTest
+
+
+class PixtoilelibreTest(BackendTest):
+ BACKEND = 'pixtoilelibre'
+
+ # small gif file
+ DATA = 'R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==\n'
+
+ def test_pixtoilelibre(self):
+ assert self.backend.can_post(self.DATA, max_age=0)
+
+ post = self.backend.new_paste(None)
+ post.contents = self.DATA
+ post.public = True
+ self.backend.post_paste(post, max_age=0)
+ assert post.id
+
+ got = self.backend.get_paste(post.id)
+ assert got
+ assert got.contents.decode('base64') == self.DATA.decode('base64')