{ "info": { "author": "Clearcode - The A Room", "author_email": "thearoom@clearcode.cc", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": ".. image:: https://travis-ci.org/ClearcodeHQ/querystringsafe_base64.svg?branch=v1.2.0\n :target: https://travis-ci.org/ClearcodeHQ/querystringsafe_base64\n :alt: Tests\n\n.. image:: https://coveralls.io/repos/ClearcodeHQ/querystringsafe_base64/badge.png?branch=v1.2.0\n :target: https://coveralls.io/r/ClearcodeHQ/querystringsafe_base64?branch=v1.2.0\n :alt: Coverage Status\n\nQuery string safe Base64\n========================\n\nEncoding and decoding arbitrary strings into strings that are safe to put into a URL query param.\n\nThe problem\n-----------\n\n`urlsafe_b64encode` and `urlsafe_b64decode` from base64 are not enough because they leave `=` used for padding chars unquoted:\n\n.. code-block:: python\n\n import base64\n\n base64.urlsafe_b64encode('a')\n 'YQ=='\n\nAnd there are 2 problems with that\n\nI. `=` sign gets quoted:\n\n.. code-block:: python\n\n import urllib\n\n urllib.quote('=')\n '%3D'\n\nII. Some libraries tolerate the `=` in query string values:\n\n.. code-block:: python\n\n from urlparse import urlsplit, parse_qs\n\n parse_qs(urlsplit('http://aaa.com/asa?q=AAAA=BBBB=CCCC').query)\n {'q': ['AAAA=BBBB=CCCC']}\n\nbut the RFC 3986 underspecifies the query string so we cannot rely on `=` chars being handled by all web applications as it is done by urlparse.\n\nTherefore we consider chars: `['+', '/', '=']` unsafe and we replace them with `['-', '_', '.']`.\nCharacters `+` and `/` are already handled by `urlsafe_*` functions from base64 so only `=` is left.\nSince the `=` is used exclusively for padding, we simply remove it, and re-attach the padding during decoding.\nBecause of that, `querystringsafe_base64` is able to decode padded and unpadded string.\n\nThe solution\n------------\n\n.. code-block:: python\n\n import querystringsafe_base64\n\n querystringsafe_base64.encode(b'foo-bar')\n b'Zm9vLWJhcg'\n\n querystringsafe_base64.decode(b'Zm9vLWJhcg..')\n b'foo-bar'\n\n querystringsafe_base64.decode(b'Zm9vLWJhcg')\n b'foo-bar'\n\n\nCHANGELOG\n=========\n\n1.2.0\n-------\n\n* Remove padding characters from encoded string.\n\n1.1.1\n-------\n\n* Fixed packaging\n\n1.1.0\n-------\n\n* Always expect bytes\n* Add type annotations\n\n1.0.0\n-------\n\n* support for restore missing padding during decode process\n\n0.2.0\n-------\n\n* Support for python3\n\n0.1.5\n-------\n\n* Move querystringsafe_base64 module to the root\n* Use install instead of develop during tests\n\n0.1.4\n-------\n\n* Remove bdist_wheel from distributons\n\n0.1.3\n-------\n\n* Install pandoc (travis)\n\n0.1.2\n-------\n\n* Add setup.cfg and pypandoc to tests\n\n0.1.1\n-------\n\n* add MANIFEST.in file\n\n0.1.0\n-------\n\n* package structure\n* tests\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ClearcodeHQ/querystringsafe_base64", "keywords": "", "license": "LGPL", "maintainer": "", "maintainer_email": "", "name": "querystringsafe-base64", "package_url": "https://pypi.org/project/querystringsafe-base64/", "platform": "", "project_url": "https://pypi.org/project/querystringsafe-base64/", "project_urls": { "Homepage": "https://github.com/ClearcodeHQ/querystringsafe_base64" }, "release_url": "https://pypi.org/project/querystringsafe-base64/1.2.0/", "requires_dist": [ "pytest ; extra == 'tests'", "pytest-cov ; extra == 'tests'", "pylama ; extra == 'tests'" ], "requires_python": "", "summary": "Encoding and decoding arbitrary strings into strings that are safe to put into a URL query param.", "version": "1.2.0" }, "last_serial": 5613902, "releases": { "0.1.0": [], "0.1.1": [], "0.1.3": [], "0.1.4": [ { "comment_text": "", "digests": { "md5": "42226a9dc1357e10b3d00e5ca2a21f9d", "sha256": "d9619962000f9c8046879b40e44116e6210c3646156c8f93f0c29c0a4a8b742b" }, "downloads": -1, "filename": "querystringsafe_base64-0.1.4.tar.gz", "has_sig": false, "md5_digest": "42226a9dc1357e10b3d00e5ca2a21f9d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4012, "upload_time": "2016-02-09T17:01:51", "url": "https://files.pythonhosted.org/packages/a4/e1/c63e61a11b0a0dcd76ebc715eb9be2279790690c7584655e9131e7672de4/querystringsafe_base64-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "bac7aee626b1186644510a0d06ba329e", "sha256": "6d9dced617bb2f40b4cb56379c6dd3e7b92ef30338ecdded521671b67971c235" }, "downloads": -1, "filename": "querystringsafe_base64-0.1.5-py2.6.egg", "has_sig": false, "md5_digest": "bac7aee626b1186644510a0d06ba329e", "packagetype": "bdist_egg", "python_version": "2.6", "requires_python": null, "size": 4194, "upload_time": "2016-02-10T10:30:21", "url": "https://files.pythonhosted.org/packages/8f/5f/94c8ede06449458d22717bac69b0681cf93cf8e21397dbda7f9c2d0e4867/querystringsafe_base64-0.1.5-py2.6.egg" }, { "comment_text": "", "digests": { "md5": "01108485ce3d58988f2273097edf4e57", "sha256": "70a3af691783e3187dbc5755e339a670b6ed2496f0f82b1ec4f4f0a68e75493e" }, "downloads": -1, "filename": "querystringsafe_base64-0.1.5-py2.7.egg", "has_sig": false, "md5_digest": "01108485ce3d58988f2273097edf4e57", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 4193, "upload_time": "2016-02-10T10:30:34", "url": "https://files.pythonhosted.org/packages/bf/ab/11bc71cfa9708cd248f5175c4e972ab40a00e89a3c1a7ee839acfd9dea1e/querystringsafe_base64-0.1.5-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "036ddb989e297e0b2d580434e088cc2f", "sha256": "d86cfb1577d20a7a9e61a01828805034b2e001061addabdf43ff97ae4bdaaa62" }, "downloads": -1, "filename": "querystringsafe_base64-0.1.5.tar.gz", "has_sig": false, "md5_digest": "036ddb989e297e0b2d580434e088cc2f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4005, "upload_time": "2016-02-10T10:30:25", "url": "https://files.pythonhosted.org/packages/37/b3/56bf3c2f41f635f9a02240ffd4735a86303ee7bb02a38cf0a32d8de8662f/querystringsafe_base64-0.1.5.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "8e20b8e014c701df0f57152efbd20737", "sha256": "1064ad8d8bf5a88501e9f895b6560d1c45949645557fd6020abec8bbbe9462ec" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0-py2.6.egg", "has_sig": false, "md5_digest": "8e20b8e014c701df0f57152efbd20737", "packagetype": "bdist_egg", "python_version": "2.6", "requires_python": null, "size": 4293, "upload_time": "2016-02-10T19:11:17", "url": "https://files.pythonhosted.org/packages/b0/61/a1554f89d12dc074dc4e182cbc6c003dbd350988f605871eece7eb62fd68/querystringsafe_base64-0.2.0-py2.6.egg" }, { "comment_text": "", "digests": { "md5": "d2ca020d489726d387fb5ff581d04728", "sha256": "682df1043abd816be9805cc06cb2da67add4311735af5de925f81dd2cfea82da" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0-py2.7.egg", "has_sig": false, "md5_digest": "d2ca020d489726d387fb5ff581d04728", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 4294, "upload_time": "2016-02-10T19:11:04", "url": "https://files.pythonhosted.org/packages/d5/d4/bc270447b1e6df59a8c1c9000cbc80be08707f08562a3121dcaf17e9a9c3/querystringsafe_base64-0.2.0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "798c4c6cbfa147902805f9cc20e00b49", "sha256": "977ae9b93f64413e83f84763cac8046e0d17d0e0a599842cb0be80c573b85cb2" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0-py3.3.egg", "has_sig": false, "md5_digest": "798c4c6cbfa147902805f9cc20e00b49", "packagetype": "bdist_egg", "python_version": "3.3", "requires_python": null, "size": 4357, "upload_time": "2016-02-10T19:11:21", "url": "https://files.pythonhosted.org/packages/6b/9b/2a0fc0910daeb0da91643fcb54c1a98427f39922ed78bb2bdac02773fc74/querystringsafe_base64-0.2.0-py3.3.egg" }, { "comment_text": "", "digests": { "md5": "574294575273e1709c012c185c9859ae", "sha256": "fc15ea4ce494a4585497513ac947095262bdcad3cb304c6c870418d45824a659" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0-py3.4.egg", "has_sig": false, "md5_digest": "574294575273e1709c012c185c9859ae", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 4354, "upload_time": "2016-02-10T19:11:58", "url": "https://files.pythonhosted.org/packages/18/ef/e7d1f1b8eeaab4d62960cdb397127e87bd3411b875e617deef3a3b05a26e/querystringsafe_base64-0.2.0-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "9647ef7236ebb7edc0169c2d88ef79c0", "sha256": "d54e3c7aa7a2e7fbd49ee4bd39595eadad636f56e16b33c14ba2e3a1f928f312" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0-py3.5.egg", "has_sig": false, "md5_digest": "9647ef7236ebb7edc0169c2d88ef79c0", "packagetype": "bdist_egg", "python_version": "3.5", "requires_python": null, "size": 4354, "upload_time": "2016-02-10T19:12:14", "url": "https://files.pythonhosted.org/packages/68/1a/93c29f3c244fc425737302cc00efc7831765ef0a8e252307aed09c66cb8f/querystringsafe_base64-0.2.0-py3.5.egg" }, { "comment_text": "", "digests": { "md5": "3b1dcf9282845b48314a97d405dd2e74", "sha256": "1bf7cae5509a1e4bc17ebf3518aa1e2a21bd6e03a7f82f156eb2d84bdaa7dc58" }, "downloads": -1, "filename": "querystringsafe_base64-0.2.0.tar.gz", "has_sig": false, "md5_digest": "3b1dcf9282845b48314a97d405dd2e74", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4010, "upload_time": "2016-02-10T19:11:14", "url": "https://files.pythonhosted.org/packages/16/d1/1cf3bdc8eb29dd42d57c3ebaf837c06efbf4e7f7e2226e46b52fbc5e815d/querystringsafe_base64-0.2.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "92c82116d6d4f8f72e1c2b76d4475ce3", "sha256": "46b4152bb4233c9850fe9cf5309356c7a3dfb43306f46fd124c96b4955c04643" }, "downloads": -1, "filename": "querystringsafe_base64-1.0.0.tar.gz", "has_sig": false, "md5_digest": "92c82116d6d4f8f72e1c2b76d4475ce3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4288, "upload_time": "2018-01-15T15:19:54", "url": "https://files.pythonhosted.org/packages/cd/e7/25318a71322ec2c8bf3beeb58ad9fb8e0b72297818299e948bb166b07ab3/querystringsafe_base64-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "bd037cc290efae47f9135b110bd0c89f", "sha256": "7e52557f02dafff351b14a2818f046e4ee81f9ed1876950e082e6f86389f177a" }, "downloads": -1, "filename": "querystringsafe_base64-1.1.0.tar.gz", "has_sig": false, "md5_digest": "bd037cc290efae47f9135b110bd0c89f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3801, "upload_time": "2018-01-24T13:35:06", "url": "https://files.pythonhosted.org/packages/62/93/11d3bbffad27f849f6bf9f5a2ea39118ca88c847ba39bee7efdb7f5cdfc8/querystringsafe_base64-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "51ca2ed2b1cf84eb4427942a44bbf9bc", "sha256": "bad9187c0406456020ee354be7f51d2e0dfc262dadde0449cbdd1fd78d437eed" }, "downloads": -1, "filename": "querystringsafe_base64-1.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "51ca2ed2b1cf84eb4427942a44bbf9bc", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 6014, "upload_time": "2018-01-24T13:54:51", "url": "https://files.pythonhosted.org/packages/50/b8/893818f11d2c9035347685a30db643e2cad18aa6ead0568da7074fc9eb69/querystringsafe_base64-1.1.1-py2.py3-none-any.whl" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "a654dee762e024ca087f50939dba953d", "sha256": "850913d05558d31a6bdb90711c3ef5ca855d8e1730bf8bc0ca2bcc1ef273c130" }, "downloads": -1, "filename": "querystringsafe_base64-1.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a654dee762e024ca087f50939dba953d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 7234, "upload_time": "2019-07-31T14:57:23", "url": "https://files.pythonhosted.org/packages/be/13/b11c71984a9bcc59dc09ca9b487673731b79fef37422fbeeca7cc54d5d7e/querystringsafe_base64-1.2.0-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a654dee762e024ca087f50939dba953d", "sha256": "850913d05558d31a6bdb90711c3ef5ca855d8e1730bf8bc0ca2bcc1ef273c130" }, "downloads": -1, "filename": "querystringsafe_base64-1.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a654dee762e024ca087f50939dba953d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 7234, "upload_time": "2019-07-31T14:57:23", "url": "https://files.pythonhosted.org/packages/be/13/b11c71984a9bcc59dc09ca9b487673731b79fef37422fbeeca7cc54d5d7e/querystringsafe_base64-1.2.0-py2.py3-none-any.whl" } ] }