Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot-preview[bot]
051f259fa7
Upgrade to GitHub-native Dependabot 2021-04-29 21:00:42 +00:00
14 changed files with 210 additions and 612 deletions

1
.gitattributes vendored
View File

@ -1,4 +1,3 @@
.github/** export-ignore
.gitattributes export-ignore
.gitignore export-ignore
README.md export-ignore

View File

@ -1,24 +0,0 @@
name: Package Application with Pyinstaller
on: [push, pull_request]
jobs:
build:
name: Binary for windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Build executable with pyinstaller
run: |
python -m pip install --upgrade pip
pip install .
pip install pyinstaller pywin32-ctypes
pyinstaller pbincli.spec
- uses: actions/upload-artifact@v2
with:
name: pbincli-windows
path: dist/*

1
.gitignore vendored
View File

@ -54,7 +54,6 @@ MANIFEST
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
-pbincli.spec
# Installer logs
pip-log.txt

136
README.md
View File

@ -1,139 +1,73 @@
[![GitHub license](https://img.shields.io/github/license/r4sas/PBinCLI.svg)](https://github.com/r4sas/PBinCLI/blob/master/LICENSE)
[![GitHub tag](https://img.shields.io/github/tag/r4sas/PBinCLI.svg)](https://github.com/r4sas/PBinCLI/tags/)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4f24f43356a84621bbd9078c4b3f1b70)](https://www.codacy.com/gh/r4sas/PBinCLI/dashboard?utm_source=github.com&utm_medium=referral&utm_content=r4sas/PBinCLI&utm_campaign=Badge_Grade)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/4f24f43356a84621bbd9078c4b3f1b70)](https://www.codacy.com/app/r4sas/PBinCLI?utm_source=github.com&utm_medium=referral&utm_content=r4sas/PBinCLI&utm_campaign=Badge_Grade)
# PBinCLI
PBinCLI
=====
PBinCLI is a command line client for [PrivateBin](https://github.com/PrivateBin/PrivateBin/) written in Python 3.
PBinCLI is command line client for [PrivateBin](https://github.com/PrivateBin/PrivateBin/) written on Python 3.
# Installation
Installing globally using pip3:
Installing
-----
```bash
pip3 install pbincli
```
Installing with `virtualenv`:
```bash
python3 -m virtualenv --python=python3 venv
virtualenv --python=python3 venv
. venv/bin/activate
pip install pbincli
```
*Note*: if you used `virtualenv` installation method, don't forget to activate your virtual environment before running the tool: call `. /path/to/venv/bin/activate` in terminal
Usage
-----
By default pbincli configured to use `https://paste.i2pd.xyz/` for sending and receiving pastes. No proxy used by default.
# Configuration
You can create config file with variables `server` and `proxy` in `~/.config/pbincli/pbincli.conf` to use different settings.
By default PBinCLI is configured to use `https://paste.i2pd.xyz/` for sending and receiving pastes. No proxy is used by default.
You can always create a config file to use different settings.
Configuration file is expected to be found in `~/.config/pbincli/pbincli.conf`, `%APPDATA%/pbincli/pbincli.conf` (Windows) and `~/Library/Application Support/pbincli/pbincli.conf` (MacOS)
## Example of config file content
Example contents:
```ini
server=https://paste.i2pd.xyz/
proxy=http://127.0.0.1:3128
```
## List of OPTIONS available
Run inside `venv` command:
| Option | Default | Possible value |
|----------------------|-------------------------|----------------|
| server | https://paste.i2pd.xyz/ | Domain ending with slash |
| mirrors | None | Domains separated with comma, like `http://privatebin.ygg/,http://privatebin.i2p/` |
| proxy | None | Proxy address starting with scheme `http://` or `socks5://` |
| expire | 1day | 5min / 10min / 1hour / 1day / 1week / 1month / 1year / never |
| burn | False | True / False |
| discus | False | True / False |
| format | plaintext | plaintext / syntaxhighlighting / markdown |
| short | False | True / False |
| short_api | None | `tinyurl`, `clckru`, `isgd`, `vgd`, `cuttly`, `yourls`, `custom` |
| short_url | None | Domain name of shortener service for `yourls`, or URL (with required parameters) for `custom` |
| short_user | None | Used only in `yourls` |
| short_pass | None | Used only in `yourls` |
| short_token | None | Used only in `yourls` |
| no_check_certificate | False | True / False |
| no_insecure_warning | False | True / False |
| compression | zlib | zlib / none |
# Usage
PBinCLI tool is started with `pbincli` command. Detailed help on command usage is provided with `-h` option:
```bash
pbincli {send|get|delete} -h
pbincli send --text "Hello!"
```
## Sending
Or use stdin input to read text for paste:
* Sending text:
```bash
pbincli send -t "Hello! This is a test paste!"
```
* Using stdin input to read text into a paste:
```bash
pbincli send - <<EOF
Hello! This is a test paste!
Hello! This is test paste!
EOF
```
* Sending a file with text attached into a paste:
It will send string `Hello! This is test paste!` to PrivateBin.
To send file use `--file` or `-f` with filename. Example:
```bash
pbincli send -f info.pdf -t "I'm sending my document."
pbincli send -c "My document" -f info.pdf
```
* Sending a file only with no text attached:
To retrieve paste from server, use `get` command with paste info.
It must be formated like `pasteID#passphrase`. Example:
```bash
pbincli send -q -f info.pdf
pbincli get 49eeb1326cfa9491#vfeortoVWaYeJlviDdhxQBtj5e0I2kArpynrtu/tnGs=
```
More info you can find by typing
### Other options
It is also possible to set-up paste parameters such as "burn after reading", expiritaion time, formatting, enabling discussions and changing compression algorithm. Please refer to `pbincli send -h` output for more information.
## Receiving
To retrieve a paste from a server, you need to use `get` command with the paste info.
Paste info must be formated as `pasteID#Passphrase` or just use full URL to a paste. Example:
```bash
pbincli get "xxx#yyy" ### receive paste xxx from https://paste.i2pd.xyz/ by default
pbincli get "https://example.com/?xxx#yyy" ### receive paste xxx from https://example.com/
pbincli [-h] {send, get, delete}
```
## Deletion
TODO
----
Write a more complete usage documentation.
To delete a paste from a server, use `delete` command with paste info:
```bash
pbincli delete "pasteid=xxx&deletetoken=yyy" ### delete paste xxx from https://paste.i2pd.xyz/ by default
pbincli delete "https://example.com/?pasteid=xxx&deletetoken=yyy" ### delete paste xxx from https://example.com/
```
If you need to delete a paste on different server than the configured one, use `-s` option together with the instance URL.
# Additional examples
Here you can find additional examples.
## Usage with I2P enabled services
Change settings to set server to `http://privatebin.i2p/` and proxy to `http://127.0.0.1:4444`. Configuration file for this example is:
```ini
server=http://privatebin.i2p/
proxy=http://127.0.0.1:4444
```
## Using aliases
Example of alias to send a paste from `stdin` direclty to I2P service:
```bash
alias pastei2p="echo 'paste the text to stdin' && pbincli send -s http://privatebin.i2p/ -x http://127.0.0.1:4444 -"
```
Call it by running `pastei2p` in terminal.
# License
This project is licensed under the MIT license, which can be found in the file [LICENSE](https://github.com/r4sas/PBinCLI/blob/master/LICENSE) in the root of the project source code.
License
-------
This project is licensed under the MIT license, which can be found in the file
[LICENSE](https://github.com/r4sas/PBinCLI/blob/master/LICENSE) in the root of the project source code.

View File

@ -1,219 +1,91 @@
.. image:: https://img.shields.io/github/license/r4sas/PBinCLI.svg
:target: https://github.com/r4sas/PBinCLI/blob/master/LICENSE
:alt: GitHub license
.. image:: https://img.shields.io/github/tag/r4sas/PBinCLI.svg
:target: https://github.com/r4sas/PBinCLI/tags/
:alt: GitHub tag
.. image:: https://app.codacy.com/project/badge/Grade/4f24f43356a84621bbd9078c4b3f1b70
:target: https://www.codacy.com/gh/r4sas/PBinCLI/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=r4sas/PBinCLI&amp;utm_campaign=Badge_Grade
:alt: Codacy Badge
PBinCLI
=======
PBinCLI is a command line client for `PrivateBin <https://github.com/PrivateBin/PrivateBin/>`_ written in Python 3.
Installation
============
Installing globally using pip3:
.. code-block:: bash
pip3 install pbincli
Installing with ``virtualenv``\ :
.. code-block:: bash
python3 -m virtualenv --python=python3 venv
. venv/bin/activate
pip install pbincli
*Note*\ : if you used ``virtualenv`` installation method, don't forget to activate your virtual environment before running the tool: call ``. /path/to/venv/bin/activate`` in terminal
Configuration
=============
By default PBinCLI is configured to use ``https://paste.i2pd.xyz/`` for sending and receiving pastes. No proxy is used by default.
You can always create a config file to use different settings.
Configuration file is expected to be found in ``~/.config/pbincli/pbincli.conf``\ , ``%APPDATA%/pbincli/pbincli.conf`` (Windows) and ``~/Library/Application Support/pbincli/pbincli.conf`` (MacOS)
Example of config file content
------------------------------
.. code-block:: ini
server=https://paste.i2pd.xyz/
proxy=http://127.0.0.1:3128
List of OPTIONS available
-------------------------
.. list-table::
:header-rows: 1
* - Option
- Default
- Possible value
* - server
- https://paste.i2pd.xyz/
- Domain ending with slash
* - mirrors
- None
- Domains separated with comma, like ``http://privatebin.ygg/,http://privatebin.i2p/``
* - proxy
- None
- Proxy address starting with scheme ``http://`` or ``socks5://``
* - expire
- 1day
- 5min / 10min / 1hour / 1day / 1week / 1month / 1year / never
* - burn
- False
- True / False
* - discus
- False
- True / False
* - format
- plaintext
- plaintext / syntaxhighlighting / markdown
* - short
- False
- True / False
* - short_api
- None
- ``tinyurl``\ , ``clckru``\ , ``isgd``\ , ``vgd``\ , ``cuttly``\ , ``yourls``\ , ``custom``
* - short_url
- None
- Domain name of shortener service for ``yourls``\ , or URL (with required parameters) for ``custom``
* - short_user
- None
- Used only in ``yourls``
* - short_pass
- None
- Used only in ``yourls``
* - short_token
- None
- Used only in ``yourls``
* - no_check_certificate
- False
- True / False
* - no_insecure_warning
- False
- True / False
* - compression
- zlib
- zlib / none
Usage
=====
PBinCLI tool is started with ``pbincli`` command. Detailed help on command usage is provided with ``-h`` option:
.. code-block:: bash
pbincli {send|get|delete} -h
Sending
-------
*
Sending text:
.. code-block:: bash
pbincli send -t "Hello! This is a test paste!"
*
Using stdin input to read text into a paste:
.. code-block:: bash
pbincli send - <<EOF
Hello! This is a test paste!
EOF
*
Sending a file with text attached into a paste:
.. code-block:: bash
pbincli send -f info.pdf -t "I'm sending my document."
*
Sending a file only with no text attached:
.. code-block:: bash
pbincli send -q -f info.pdf
Other options
^^^^^^^^^^^^^
It is also possible to set-up paste parameters such as "burn after reading", expiritaion time, formatting, enabling discussions and changing compression algorithm. Please refer to ``pbincli send -h`` output for more information.
Receiving
---------
To retrieve a paste from a server, you need to use ``get`` command with the paste info.
Paste info must be formated as ``pasteID#Passphrase`` or just use full URL to a paste. Example:
.. code-block:: bash
pbincli get "xxx#yyy" ### receive paste xxx from https://paste.i2pd.xyz/ by default
pbincli get "https://example.com/?xxx#yyy" ### receive paste xxx from https://example.com/
Deletion
--------
To delete a paste from a server, use ``delete`` command with paste info:
.. code-block:: bash
pbincli delete "pasteid=xxx&deletetoken=yyy" ### delete paste xxx from https://paste.i2pd.xyz/ by default
pbincli delete "https://example.com/?pasteid=xxx&deletetoken=yyy" ### delete paste xxx from https://example.com/
If you need to delete a paste on different server than the configured one, use ``-s`` option together with the instance URL.
Additional examples
===================
Here you can find additional examples.
Usage with I2P enabled services
-------------------------------
Change settings to set server to ``http://privatebin.i2p/`` and proxy to ``http://127.0.0.1:4444``. Configuration file for this example is:
.. code-block:: ini
server=http://privatebin.i2p/
proxy=http://127.0.0.1:4444
Using aliases
-------------
Example of alias to send a paste from ``stdin`` direclty to I2P service:
.. code-block:: bash
alias pastei2p="echo 'paste the text to stdin' && pbincli send -s http://privatebin.i2p/ -x http://127.0.0.1:4444 -"
Call it by running ``pastei2p`` in terminal.
License
=======
This project is licensed under the MIT license, which can be found in the file `LICENSE <https://github.com/r4sas/PBinCLI/blob/master/LICENSE>`_ in the root of the project source code.
.. image:: https://img.shields.io/github/license/r4sas/PBinCLI.svg
:target: https://github.com/r4sas/PBinCLI/blob/master/LICENSE
:alt: GitHub license
.. image:: https://img.shields.io/github/tag/r4sas/PBinCLI.svg
:target: https://github.com/r4sas/PBinCLI/tags/
:alt: GitHub tag
.. image:: https://api.codacy.com/project/badge/Grade/4f24f43356a84621bbd9078c4b3f1b70
:target: https://www.codacy.com/app/r4sas/PBinCLI?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=r4sas/PBinCLI&amp;utm_campaign=Badge_Grade
:alt: Codacy Badge
PBinCLI
=======
PBinCLI is command line client for `PrivateBin <https://github.com/PrivateBin/PrivateBin/>`_ written on Python 3.
Installing
----------
.. code-block:: bash
virtualenv --python=python3 venv
. venv/bin/activate
pip install pbincli
Usage
-----
By default pbincli configured to use ``https://paste.i2pd.xyz/`` for sending and receiving pastes. No proxy used by default.
You can create config file with variables ``server`` and ``proxy`` in ``~/.config/pbincli/pbincli.conf`` to use different settings.
Example contents:
.. code-block:: ini
server=https://paste.i2pd.xyz/
proxy=http://127.0.0.1:3128
Run inside ``venv`` command:
.. code-block:: bash
pbincli send --text "Hello!"
Or use stdin input to read text for paste:
.. code-block:: bash
pbincli send - <<EOF
Hello! This is test paste!
EOF
It will send string ``Hello! This is test paste!`` to PrivateBin.
To send file use ``--file`` or ``-f`` with filename. Example:
.. code-block:: bash
pbincli send -c "My document" -f info.pdf
To retrieve paste from server, use ``get`` command with paste info.
It must be formated like ``pasteID#passphrase``. Example:
.. code-block:: bash
pbincli get 49eeb1326cfa9491#vfeortoVWaYeJlviDdhxQBtj5e0I2kArpynrtu/tnGs=
More info you can find by typing
.. code-block:: bash
pbincli [-h] {send, get, delete}
TODO
----
Write a more complete usage documentation.
License
-------
This project is licensed under the MIT license, which can be found in the file
`LICENSE <https://github.com/r4sas/PBinCLI/blob/master/LICENSE>`_ in the root of the project source code.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,67 +0,0 @@
# -*- mode: python -*-
from pkg_resources import parse_version
from PyInstaller.utils.win32.versioninfo import VSVersionInfo, FixedFileInfo, StringFileInfo, StringTable, StringStruct, VarFileInfo, VarStruct
from pbincli.__init__ import __version__ as pbincli_version, __copyright__ as pbincli_copyright
pbincli_ver = parse_version(pbincli_version)
block_cipher = None
a = Analysis(['pbincli\\cli.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='pbincli-' + pbincli_version,
version=VSVersionInfo(
ffi=FixedFileInfo(
filevers=(pbincli_ver.major, pbincli_ver.minor, pbincli_ver.micro, 0),
prodvers=(pbincli_ver.major, pbincli_ver.minor, pbincli_ver.micro, 0),
mask=0x3f,
flags=0x0,
OS=0x40004,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo([
StringTable(
u'040904B0',
[
StringStruct(u'FileDescription', u'PrivateBin CLI'),
StringStruct(u'FileVersion', pbincli_version),
StringStruct(u'InternalName', u'pbincli'),
StringStruct(u'LegalCopyright', pbincli_copyright),
StringStruct(u'OriginalFilename', u'pbincli-' + pbincli_version + u'.exe'),
StringStruct(u'ProductName', u'PBinCLI'),
StringStruct(u'ProductVersion', pbincli_version)
]
)
]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
]
),
icon=['contrib\\privatebin.ico'],
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True)

View File

@ -2,6 +2,6 @@
# -*- coding: utf-8 -*-
__author__ = "R4SAS <r4sas@i2pmail.org>"
__version__ = "0.3.4"
__version__ = "0.3.1"
__copyright__ = "Copyright (c) R4SAS"
__license__ = "MIT"

View File

@ -1,47 +1,38 @@
import signal, sys
from urllib.parse import parse_qsl
from pbincli.api import Shortener
from pbincli.format import Paste
from pbincli.utils import PBinCLIError, check_writable, json_encode, uri_validator, validate_url_ending
from pbincli.utils import PBinCLIError
import signal
def signal_handler(sig, frame):
print('Keyboard interrupt received, terminating')
sys.exit(0)
print('Keyboard interrupt received, terminating...')
exit(0)
signal.signal(signal.SIGINT, signal_handler)
def send(args, api_client, settings=None):
if settings['short']:
from pbincli.api import Shortener
if args.short:
shortener = Shortener(settings)
if not args.notext:
if args.text:
text = args.text
elif args.stdin:
print("Reading text from stdin…")
text = args.stdin.read()
elif not args.file:
PBinCLIError("Nothing to send!")
else:
text = ""
print("Preparing paste…")
paste = Paste(args.debug)
if args.verbose: print("Used server: {}".format(api_client.getServer()))
# get from server supported paste format version and update object
if args.verbose: print("Getting supported paste format version from server…")
version = api_client.getVersion()
paste.setVersion(version)
if args.verbose: print("Filling paste with data…")
# set compression type, works only on v2 pastes
if version == 2:
paste.setCompression(settings['compression'])
paste.setCompression(args.compression)
# add text in paste (if it provided)
paste.setText(text)
@ -54,22 +45,21 @@ def send(args, api_client, settings=None):
if args.file:
paste.setAttachment(args.file)
if args.verbose: print("Encrypting paste…")
paste.encrypt(
formatter = settings['format'],
burnafterreading = settings['burn'],
discussion = settings['discus'],
expiration = settings['expire'])
formatter = args.format,
burnafterreading = args.burn,
discussion = args.discus,
expiration = args.expire)
if args.verbose: print("Sending request to server…")
request = paste.getJSON()
if args.debug: print("Passphrase:\t{}\nRequest:\t{}".format(paste.getHash(), request))
if args.debug:
print("Passphrase:\t{}".format(paste.getHash()))
print("Request:\t{}".format(request))
# If we use dry option, exit now
if args.dry: sys.exit(0)
if args.dry: exit(0)
print("Uploading paste…")
result = api_client.post(request)
if args.debug: print("Response:\t{}\n".format(result))
@ -78,41 +68,20 @@ def send(args, api_client, settings=None):
if not result['status']: # return code is zero
passphrase = paste.getHash()
# Paste information
print("Paste uploaded!\nPasteID:\t{}\nPassword:\t{}\nDelete token:\t{}".format(
print("Paste uploaded!\nPasteID:\t{}\nPassword:\t{}\nDelete token:\t{}\n\nLink:\t\t{}?{}#{}".format(
result['id'],
passphrase,
result['deletetoken']))
# Paste link
print("\nLink:\t\t{}?{}#{}".format(
result['deletetoken'],
settings['server'],
result['id'],
passphrase))
# Paste deletion link
print("Delete Link:\t{}?pasteid={}&deletetoken={}".format(
settings['server'],
result['id'],
result['deletetoken']))
# Print links to mirrors if present
if settings['mirrors']:
print("\nMirrors:")
urls = settings['mirrors'].split(',')
for x in urls:
print("\t\t{}?{}#{}".format(
validate_url_ending(x),
result['id'],
passphrase))
elif result['status']: # return code is other then zero
PBinCLIError("Something went wrong\nError:\t\t{}".format(result['message']))
PBinCLIError("Something went wrong...\nError:\t\t{}".format(result['message']))
else: # or here no status field in response or it is empty
PBinCLIError("Something went wrong\nError: Empty response.")
PBinCLIError("Something went wrong...\nError: Empty response.")
if settings['short']:
print("\nQuerying URL shortening service")
if args.short:
print("\nQuerying URL shortening service...")
shortener.getlink("{}?{}#{}".format(
settings['server'],
result['id'],
@ -120,19 +89,16 @@ def send(args, api_client, settings=None):
def get(args, api_client, settings=None):
parseduri, isuri = uri_validator(args.pasteinfo)
from pbincli.utils import check_writable, json_encode
if isuri and parseduri.query and parseduri.fragment:
api_client.server = args.pasteinfo.split("?")[0]
pasteid = parseduri.query
passphrase = parseduri.fragment
elif parseduri.path and parseduri.path != "/" and parseduri.fragment:
pasteid = parseduri.path
passphrase = parseduri.fragment
else:
PBinCLIError("Provided info hasn't contain valid URL or PasteID#Passphrase string")
try:
pasteid, passphrase = args.pasteinfo.split("#")
except ValueError:
PBinCLIError("Provided info hasn't contain valid PasteID#Passphrase string")
if not (pasteid and passphrase):
PBinCLIError("Incorrect request")
if args.verbose: print("Used server: {}".format(api_client.getServer()))
if args.debug: print("PasteID:\t{}\nPassphrase:\t{}".format(pasteid, passphrase))
paste = Paste(args.debug)
@ -141,14 +107,13 @@ def get(args, api_client, settings=None):
paste.setPassword(args.password)
if args.debug: print("Password:\t{}".format(args.password))
if args.verbose: print("Requesting paste from server…")
result = api_client.get(pasteid)
if args.debug: print("Response:\t{}\n".format(result))
# Paste was received. Checking received status code
if not result['status']: # return code is zero
print("Paste received! Decoding…")
print("Paste received!")
version = result['v'] if 'v' in result else 1
paste.setVersion(version)
@ -185,32 +150,21 @@ def get(args, api_client, settings=None):
f.close()
if version == 1 and 'meta' in result and 'burnafterreading' in result['meta'] and result['meta']['burnafterreading']:
print("Burn afrer reading flag found. Deleting paste")
print("Burn afrer reading flag found. Deleting paste...")
api_client.delete(json_encode({'pasteid':pasteid,'deletetoken':'burnafterreading'}))
elif result['status']: # return code is other then zero
PBinCLIError("Something went wrong\nError:\t\t{}".format(result['message']))
PBinCLIError("Something went wrong...\nError:\t\t{}".format(result['message']))
else: # or here no status field in response or it is empty
PBinCLIError("Something went wrong\nError: Empty response.")
PBinCLIError("Something went wrong...\nError: Empty response.")
def delete(args, api_client, settings=None):
parseduri, isuri = uri_validator(args.pasteinfo)
from pbincli.utils import json_encode
if isuri:
api_client.server = args.pasteinfo.split("?")[0]
query = dict(parse_qsl(parseduri.query))
else:
query = dict(parse_qsl(args.pasteinfo))
pasteid = args.paste
token = args.token
if 'pasteid' in query and 'deletetoken' in query:
pasteid = query['pasteid']
token = query['deletetoken']
else:
PBinCLIError("Provided info hasn't contain required information")
if args.verbose: print("Used server: {}".format(api_client.getServer()))
if args.debug: print("PasteID:\t{}\nToken:\t\t{}".format(pasteid, token))
print("Requesting paste deletion…")
api_client.delete(json_encode({'pasteid':pasteid,'deletetoken':token}))

View File

@ -78,10 +78,6 @@ class PrivateBin:
'@value' in jsonldSchema['@context']['v']) \
else 1
def getServer(self):
return self.server
class Shortener:
"""Some parts of this class was taken from
python-yourls (https://github.com/tflink/python-yourls/) library
@ -89,17 +85,12 @@ class Shortener:
def __init__(self, settings=None):
self.api = settings['short_api']
if self.api is None:
PBinCLIError("Unable to activate link shortener without short_api.")
# we checking which service is used, because some services doesn't require
# any authentication, or have only one domain on which it working
if self.api == 'yourls':
self._yourls_init(settings)
elif self.api == 'isgd' or self.api == 'vgd':
self._gd_init()
elif self.api == 'custom':
self.apiurl = settings['short_url']
self.session, self.proxy = _config_requests(settings)
@ -146,8 +137,7 @@ class Shortener:
'tinyurl': self._tinyurl,
'isgd': self._gd,
'vgd': self._gd,
'cuttly': self._cuttly,
'custom': self._custom
'cuttly': self._cuttly
}
# run function selected by choosen API
servicesList[self.api](url)
@ -256,20 +246,3 @@ class Shortener:
print("Short Link:\t{}".format(result.text))
except Exception as ex:
PBinCLIError("cutt.ly: unexcepted behavior: {}".format(ex))
def _custom(self, url):
if self.apiurl is None:
PBinCLIError("No short_url specified - link will not be shortened.")
from urllib.parse import quote
qUrl = quote(url, safe="") # urlencoded paste url
rUrl = self.apiurl.replace("{{url}}", qUrl)
try:
result = self.session.get(
url = rUrl,
proxies = self.proxy)
print("Short Link:\t{}".format(result.text))
except Exception as ex:
PBinCLIError("Shorter: unexcepted behavior: {}".format(ex))

View File

@ -1,21 +1,12 @@
#!/usr/bin/env python
import os, sys, argparse
from distutils.util import strtobool
import pbincli.actions
from pbincli.api import PrivateBin
from pbincli.utils import PBinCLIException, PBinCLIError, validate_url_ending
CONFIG_PATHS = [
os.path.join(".", "pbincli.conf", ),
os.path.join(os.getenv("HOME") or "~", ".config", "pbincli", "pbincli.conf")
]
if sys.platform == "win32":
CONFIG_PATHS.append(os.path.join(os.getenv("APPDATA"), "pbincli", "pbincli.conf"))
elif sys.platform == "darwin":
CONFIG_PATHS.append(os.path.join(os.getenv("HOME") or "~", "Library", "Application Support", "pbincli", "pbincli.conf"))
from pbincli.utils import PBinCLIException, PBinCLIError, validate_url
CONFIG_PATHS = [os.path.join(".", "pbincli.conf", ),
os.path.join(os.getenv("HOME") or "~", ".config", "pbincli", "pbincli.conf") ]
def read_config(filename):
"""Read config variables from a file"""
@ -25,119 +16,103 @@ def read_config(filename):
if len(l.strip()) == 0:
continue
try:
key, value = l.strip().split("=", 1)
if value.strip().lower() in ['true', 'false']:
settings[key.strip()] = bool(strtobool(value.strip()))
else:
settings[key.strip()] = value.strip()
key, value = l.strip().split("=")
settings[key.strip()] = value.strip()
except ValueError:
PBinCLIError("Unable to parse config file, please check it for errors.")
return settings
def main():
parser = argparse.ArgumentParser(description='Full-featured PrivateBin command-line client')
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(title="actions", help="List of commands")
# a send command
send_parser = subparsers.add_parser("send", description="Send data to PrivateBin instance")
send_parser.add_argument("-t", "--text", help="Text in quotes. Ignored if used stdin. If not used, forcefully used stdin")
send_parser.add_argument("-f", "--file", help="Example: image.jpg or full path to file")
send_parser.add_argument("-p", "--password", help="Password for encrypting paste")
send_parser.add_argument("-t", "--text", help="text in quotes. Ignored if used stdin. If not used, forcefully used stdin")
send_parser.add_argument("-f", "--file", help="example: image.jpg or full path to file")
send_parser.add_argument("-p", "--password", help="password for encrypting paste")
send_parser.add_argument("-E", "--expire", default="1day", action="store",
choices=["5min", "10min", "1hour", "1day", "1week", "1month", "1year", "never"], help="Paste lifetime (default: 1day)")
send_parser.add_argument("-B", "--burn", default=argparse.SUPPRESS, action="store_true", help="Set \"Burn after reading\" flag")
send_parser.add_argument("-D", "--discus", default=argparse.SUPPRESS, action="store_true", help="Open discussion for sent paste")
choices=["5min", "10min", "1hour", "1day", "1week", "1month", "1year", "never"], help="paste lifetime (default: 1day)")
send_parser.add_argument("-B", "--burn", default=False, action="store_true", help="burn sent paste after reading")
send_parser.add_argument("-D", "--discus", default=False, action="store_true", help="open discussion for sent paste")
send_parser.add_argument("-F", "--format", default="plaintext", action="store",
choices=["plaintext", "syntaxhighlighting", "markdown"], help="Format of text (default: plaintext)")
send_parser.add_argument("-q", "--notext", default=False, action="store_true", help="Don't send text in paste")
choices=["plaintext", "syntaxhighlighting", "markdown"], help="format of text (default: plaintext)")
send_parser.add_argument("-q", "--notext", default=False, action="store_true", help="don't send text in paste")
send_parser.add_argument("-c", "--compression", default="zlib", action="store",
choices=["zlib", "none"], help="Set compression for paste (default: zlib). Note: works only on v2 paste format")
choices=["zlib", "none"], help="set compression for paste (default: zlib). Note: works only on v2 paste format")
## URL shortener
send_parser.add_argument("-S", "--short", default=argparse.SUPPRESS, action="store_true", help="Use URL shortener")
send_parser.add_argument("-S", "--short", default=False, action="store_true", help="use URL shortener")
send_parser.add_argument("--short-api", default=argparse.SUPPRESS, action="store",
choices=["tinyurl", "clckru", "isgd", "vgd", "cuttly", "yourls", "custom"], help="API used by shortener service")
choices=["tinyurl", "clckru", "isgd", "vgd", "cuttly", "yourls"], help="API used by shortener service")
send_parser.add_argument("--short-url", default=argparse.SUPPRESS, help="URL of shortener service API")
send_parser.add_argument("--short-user", default=argparse.SUPPRESS, help="Shortener username")
send_parser.add_argument("--short-pass", default=argparse.SUPPRESS, help="Shortener password")
send_parser.add_argument("--short-token", default=argparse.SUPPRESS, help="Shortener token")
## Connection options
send_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="Instance URL (default: https://paste.i2pd.xyz/)")
send_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="PrivateBin service URL (default: https://paste.i2pd.xyz/)")
send_parser.add_argument("-x", "--proxy", default=argparse.SUPPRESS, help="Proxy server address (default: None)")
send_parser.add_argument("--no-check-certificate", default=argparse.SUPPRESS, action="store_true", help="Disable certificate validation")
send_parser.add_argument("--no-insecure-warning", default=argparse.SUPPRESS, action="store_true",
help="Suppress InsecureRequestWarning (only with --no-check-certificate)")
send_parser.add_argument("--no-check-certificate", default=False, action="store_true", help="disable certificate validation")
send_parser.add_argument("--no-insecure-warning", default=False, action="store_true",
help="suppress InsecureRequestWarning (only with --no-check-certificate)")
##
send_parser.add_argument("-L", "--mirrors", default=argparse.SUPPRESS, help="Comma-separated list of mirrors of service with scheme (default: None)")
send_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
send_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output")
send_parser.add_argument("--dry", default=False, action="store_true", help="Invoke dry run")
send_parser.add_argument("stdin", help="Input paste text from stdin", nargs="?", type=argparse.FileType("r"), default=sys.stdin)
send_parser.add_argument("-d", "--debug", default=False, action="store_true", help="enable debug")
send_parser.add_argument("--dry", default=False, action="store_true", help="invoke dry run")
send_parser.add_argument("stdin", help="input paste text from stdin", nargs="?", type=argparse.FileType("r"), default=sys.stdin)
send_parser.set_defaults(func=pbincli.actions.send)
# a get command
get_parser = subparsers.add_parser("get", description="Get data from PrivateBin instance")
get_parser.add_argument("pasteinfo", help="\"PasteID#Passphrase\" or full URL")
get_parser.add_argument("-p", "--password", help="Password for decrypting paste")
get_parser.add_argument("pasteinfo", help="example: aabb#cccddd")
get_parser.add_argument("-p", "--password", help="password for decrypting paste")
## Connection options
get_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="Instance URL (default: https://paste.i2pd.xyz/, ignored if URL used in pasteinfo)")
get_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="PrivateBin service URL (default: https://paste.i2pd.xyz/)")
get_parser.add_argument("-x", "--proxy", default=argparse.SUPPRESS, help="Proxy server address (default: None)")
get_parser.add_argument("--no-check-certificate", default=argparse.SUPPRESS, action="store_true", help="Disable certificate validation")
get_parser.add_argument("--no-insecure-warning", default=argparse.SUPPRESS, action="store_true",
help="Suppress InsecureRequestWarning (only with --no-check-certificate)")
get_parser.add_argument("--no-check-certificate", default=False, action="store_true", help="disable certificate validation")
get_parser.add_argument("--no-insecure-warning", default=False, action="store_true",
help="suppress InsecureRequestWarning (only with --no-check-certificate)")
##
get_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
get_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output")
get_parser.add_argument("-d", "--debug", default=False, action="store_true", help="enable debug")
get_parser.set_defaults(func=pbincli.actions.get)
# a delete command
delete_parser = subparsers.add_parser("delete", description="Delete paste from PrivateBin instance")
delete_parser.add_argument("pasteinfo", help="Paste deletion URL or string in \"pasteid=PasteID&deletetoken=Token\" format")
delete_parser = subparsers.add_parser("delete", description="Delete paste from PrivateBin instance using token")
delete_parser.add_argument("-p", "--paste", required=True, help="paste id")
delete_parser.add_argument("-t", "--token", required=True, help="paste deletion token")
## Connection options
delete_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="Instance URL (default: https://paste.i2pd.xyz/)")
delete_parser.add_argument("-s", "--server", default=argparse.SUPPRESS, help="PrivateBin service URL (default: https://paste.i2pd.xyz/)")
delete_parser.add_argument("-x", "--proxy", default=argparse.SUPPRESS, help="Proxy server address (default: None)")
delete_parser.add_argument("--no-check-certificate", default=argparse.SUPPRESS, action="store_true", help="Disable certificate validation")
delete_parser.add_argument("--no-insecure-warning", default=argparse.SUPPRESS, action="store_true",
help="Suppress InsecureRequestWarning (only with --no-check-certificate)")
delete_parser.add_argument("--no-check-certificate", default=False, action="store_true", help="disable certificate validation")
delete_parser.add_argument("--no-insecure-warning", default=False, action="store_true",
help="suppress InsecureRequestWarning (only with --no-check-certificate)")
##
delete_parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Enable verbose output")
delete_parser.add_argument("-d", "--debug", default=False, action="store_true", help="Enable debug output")
delete_parser.add_argument("-d", "--debug", default=False, action="store_true", help="enable debug")
delete_parser.set_defaults(func=pbincli.actions.delete)
# parse arguments
args = parser.parse_args()
# default configuration
CONFIG = {
'server': 'https://paste.i2pd.xyz/',
'mirrors': None,
'proxy': None,
'expire': '1day',
'burn': False,
'discus': False,
'format': None,
'short': False,
'short_api': None,
'short_url': None,
'short_user': None,
'short_pass': None,
'short_token': None,
'no_check_certificate': False,
'no_insecure_warning': False,
'compression': None
'no_insecure_warning': False
}
# Configuration preference order:
# 1. Command line switches
# 2. Environment variables
# 3. Configuration file
# 4. Defaults above
# 4. Default values below
for p in CONFIG_PATHS:
if os.path.exists(p):
fileconfig = read_config(p)
if args.debug: print("Configuration readed from file:\t{}".format(fileconfig))
CONFIG.update(fileconfig)
CONFIG.update(read_config(p))
break
for key in CONFIG.keys():
@ -149,9 +124,8 @@ def main():
CONFIG[key] = args_var[key]
# Re-validate PrivateBin instance URL
CONFIG['server'] = validate_url_ending(CONFIG['server'])
CONFIG['server'] = validate_url(CONFIG['server'])
if args.debug: print("Whole configuration:\t\t{}".format(CONFIG))
api_client = PrivateBin(CONFIG)
if hasattr(args, "func"):

View File

@ -254,7 +254,6 @@ class Paste:
self._discussion = discussion
self._expiration = expiration
if self._debug: print("[Enc] Starting encyptor…")
if self._version == 2: self._encryptV2()
else: self._encryptV1()
@ -262,13 +261,10 @@ class Paste:
def _encryptV2(self):
from pbincli.utils import json_encode
if self._debug: print("[Enc] Preparing IV, Salt…")
iv = get_random_bytes(int(self._tag_bits / 8))
salt = get_random_bytes(self._salt_bytes)
if self._debug: print("[Enc] Deriving Key…")
key = self.__deriveKey(salt)
if self._debug: print("[Enc] Preparing aData and message…")
# prepare encryption authenticated data and message
adata = [
[
@ -290,7 +286,6 @@ class Paste:
cipher_message['attachment'] = self._attachment
cipher_message['attachment_name'] = self._attachment_name
if self._debug: print("[Enc] Encrypting message…")
cipher = self.__initializeCipher(key, iv, adata, int(self._tag_bits /8 ))
ciphertext, tag = cipher.encrypt_and_digest(self.__compress(json_encode(cipher_message)))

View File

@ -6,7 +6,7 @@ class PBinCLIException(Exception):
def PBinCLIError(message):
print("PBinCLI Error: {}".format(message), file=sys.stderr)
sys.exit(1)
exit(1)
def path_leaf(path):
@ -30,16 +30,7 @@ def json_encode(s):
return json.dumps(s, separators=(',',':')).encode()
def validate_url_ending(s):
def validate_url(s):
if not s.endswith('/'):
s = s + "/"
return s
def uri_validator(x):
from urllib.parse import urlsplit
try:
result = urlsplit(x)
isuri = all([result.scheme, result.netloc])
return result, isuri
except ValueError:
return False

View File

@ -1,2 +0,0 @@
[build-system]
requires = ["setuptools", "wheel"]