Skip to content
Commits on Source (141)
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Use multiple processes to speed up Pylint.
jobs=1
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
# be used to obtain the result of joining multiple strings with the addition
# operator. Joining a lot of strings can lead to a maximum recursion error in
# Pylint and this flag can prevent that. It has one side effect, the resulting
# AST will be different than the one from reality.
optimize-ast=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time. See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,line-too-long,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
ignored-classes=
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
[BASIC]
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,input
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for function names
function-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for variable names
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for attribute names
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for argument names
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming hint for class names
class-name-hint=[A-Z_][a-zA-Z0-9]+$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for method names
method-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
[ELIF]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception
Changelog
=========
Current
-------
- Add `python 3 support <https://git.ziirish.me/ziirish/burp-ui/issues/75>`_
- Add new fields in `backup reports <https://git.ziirish.me/ziirish/burp-ui/issues/48>`_
- Add `server-side initiated restoration <https://git.ziirish.me/ziirish/burp-ui/issues/12>`_
- Add percent done in `overview <https://git.ziirish.me/ziirish/burp-ui/issues/55>`_
- Add the ability to `chain multiple authentication backends <https://git.ziirish.me/ziirish/burp-ui/issues/79>`_
- Add display versions `within the interface <https://git.ziirish.me/ziirish/burp-ui/issues/89>`_
- Add support for `zip64 <https://git.ziirish.me/ziirish/burp-ui/issues/97>`_
- Add new `report <https://git.ziirish.me/ziirish/burp-ui/issues/15>`_
- Add new `calendar view <https://git.ziirish.me/ziirish/burp-ui/issues/61>`_
- Add "restart" option to debian init script thanks to @Larsen
- Add Basic HTTP Authentication (mostly for the API)
- Add self-documented API
- Fix issue `#81 <https://git.ziirish.me/ziirish/burp-ui/issues/81>`_
- Fix issue `#87 <https://git.ziirish.me/ziirish/burp-ui/issues/87>`_
- Fix issue `#88 <https://git.ziirish.me/ziirish/burp-ui/issues/88>`_
- Fix issue `#92 <https://git.ziirish.me/ziirish/burp-ui/issues/92>`_
- Fix issue `#95 <https://git.ziirish.me/ziirish/burp-ui/issues/95>`_
- Fix issue `#99 <https://git.ziirish.me/ziirish/burp-ui/issues/99>`_
- Fix issue `#100 <https://git.ziirish.me/ziirish/burp-ui/issues/100>`_
- Fix issue `#101 <https://git.ziirish.me/ziirish/burp-ui/issues/101>`_
0.2.0 (05/17/2016)
------------------
- Add: allow to `edit a server-initiated restoration <https://git.ziirish.me/ziirish/burp-ui/issues/125>`_
- Add: allow to `cancel a server-initiated restoration <https://git.ziirish.me/ziirish/burp-ui/issues/112>`_
- Add: support for `Burp labels <https://git.ziirish.me/ziirish/burp-ui/issues/116>`_
- Add: `server-initiated backups <https://git.ziirish.me/ziirish/burp-ui/issues/119>`_
- Add: support `sub-root path <https://git.ziirish.me/ziirish/burp-ui/issues/128>`_
- Add: new Burp 2 settings
- Improvement: `better logging system <https://git.ziirish.me/ziirish/burp-ui/issues/118>`_
- Improvement: `new security options <https://git.ziirish.me/ziirish/burp-ui/issues/86>`_
- Fix: issue `#109 <https://git.ziirish.me/ziirish/burp-ui/issues/109>`_
- Fix: issue `#113 <https://git.ziirish.me/ziirish/burp-ui/issues/113>`_
- Fix: issue `#114 <https://git.ziirish.me/ziirish/burp-ui/issues/114>`_
- Fix: issue `#117 <https://git.ziirish.me/ziirish/burp-ui/issues/117>`_
- Fix: issue `#123 <https://git.ziirish.me/ziirish/burp-ui/issues/123>`_
- Doc
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.1.0...v0.2.0>`__
0.1.3 (02/20/2016)
------------------
- Fix: issue `#107 <https://git.ziirish.me/ziirish/burp-ui/issues/107>`_
- Fix: issue `#108 <https://git.ziirish.me/ziirish/burp-ui/issues/108>`_
0.1.2 (02/18/2016)
------------------
- Fix: duration computation
- Fix: issue `#104 <https://git.ziirish.me/ziirish/burp-ui/issues/104>`_
- Fix: issue `#105 <https://git.ziirish.me/ziirish/burp-ui/issues/105>`_
- Fix: issue `#106 <https://git.ziirish.me/ziirish/burp-ui/issues/106>`_
0.1.1 (02/17/2016)
------------------
- Fix: burp2 backend issue
- Fix: Debian wheezy compatibility
- Fix: sample configuration files location
- Better calendar readability
0.1.0 (02/15/2016)
------------------
- Add: `python 3 support <https://git.ziirish.me/ziirish/burp-ui/issues/75>`_
- Add: new fields in `backup reports <https://git.ziirish.me/ziirish/burp-ui/issues/48>`_
- Add: `server-side initiated restoration <https://git.ziirish.me/ziirish/burp-ui/issues/12>`_
- Add: percent done in `overview <https://git.ziirish.me/ziirish/burp-ui/issues/55>`_
- Add: ability to `chain multiple authentication backends <https://git.ziirish.me/ziirish/burp-ui/issues/79>`_
- Add: display versions `within the interface <https://git.ziirish.me/ziirish/burp-ui/issues/89>`_
- Add: support for `zip64 <https://git.ziirish.me/ziirish/burp-ui/issues/97>`_
- Add: new `report <https://git.ziirish.me/ziirish/burp-ui/issues/15>`_
- Add: new `calendar view <https://git.ziirish.me/ziirish/burp-ui/issues/61>`_
- Add: "restart" option to debian init script thanks to @Larsen
- Add: Basic HTTP Authentication (mostly for the API)
- Add: self-documented API
- Fix: issue `#81 <https://git.ziirish.me/ziirish/burp-ui/issues/81>`_
- Fix: issue `#87 <https://git.ziirish.me/ziirish/burp-ui/issues/87>`_
- Fix: issue `#88 <https://git.ziirish.me/ziirish/burp-ui/issues/88>`_
- Fix: issue `#92 <https://git.ziirish.me/ziirish/burp-ui/issues/92>`_
- Fix: issue `#95 <https://git.ziirish.me/ziirish/burp-ui/issues/95>`_
- Fix: issue `#99 <https://git.ziirish.me/ziirish/burp-ui/issues/99>`_
- Fix: issue `#100 <https://git.ziirish.me/ziirish/burp-ui/issues/100>`_
- Fix: issue `#101 <https://git.ziirish.me/ziirish/burp-ui/issues/101>`_
- `demo <https://demo.ziirish.me/>`_
- API refactoring
- Security fixes
- Bugfixes
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/0.0.7...master>`__
0.0.7.3 (09/26/2015)
--------------------
- Fix issue `#77 <https://git.ziirish.me/ziirish/burp-ui/issues/77>`_
- Fix: issue `#77 <https://git.ziirish.me/ziirish/burp-ui/issues/77>`_
- Doc
0.0.7.2 (09/01/2015)
--------------------
- Fix issue `#73 <https://git.ziirish.me/ziirish/burp-ui/issues/72>`_
- Fix issue `#74 <https://git.ziirish.me/ziirish/burp-ui/issues/74>`_
- Fix: issue `#73 <https://git.ziirish.me/ziirish/burp-ui/issues/72>`_
- Fix: issue `#74 <https://git.ziirish.me/ziirish/burp-ui/issues/74>`_
- Doc
0.0.7.1 (08/22/2015)
--------------------
- Add `Burp-2 backend <https://git.ziirish.me/ziirish/burp-ui/issues/52>`_
- Add `sortable tables <https://git.ziirish.me/ziirish/burp-ui/issues/51>`_
- Add `ACL support <https://git.ziirish.me/ziirish/burp-ui/issues/47>`_
- Add `support client-side encrypted backups while performing an online restoration <https://git.ziirish.me/ziirish/burp-ui/issues/44>`_
- Add `multiple archive format <https://git.ziirish.me/ziirish/burp-ui/issues/31>`_
- Add `better Active Directory support <https://git.ziirish.me/ziirish/burp-ui/issues/64>`__
- Add: `Burp-2 backend <https://git.ziirish.me/ziirish/burp-ui/issues/52>`_
- Add: `sortable tables <https://git.ziirish.me/ziirish/burp-ui/issues/51>`_
- Add: `ACL support <https://git.ziirish.me/ziirish/burp-ui/issues/47>`_
- Add: `support client-side encrypted backups while performing an online restoration <https://git.ziirish.me/ziirish/burp-ui/issues/44>`_
- Add: `multiple archive format <https://git.ziirish.me/ziirish/burp-ui/issues/31>`_
- Add: `better Active Directory support <https://git.ziirish.me/ziirish/burp-ui/issues/64>`__
- Improvement: `better config file parser <https://git.ziirish.me/ziirish/burp-ui/issues/50>`_
- Improvement: `better logging with Gunicorn <https://git.ziirish.me/ziirish/burp-ui/issues/65>`_
- Improvement: `full support of server configuration file + clientconfdir <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix issue `#37 <https://git.ziirish.me/ziirish/burp-ui/issues/37>`_
- Fix issue `#41 <https://git.ziirish.me/ziirish/burp-ui/issues/41>`_
- Fix issue `#42 <https://git.ziirish.me/ziirish/burp-ui/issues/42>`_
- Fix issue `#46 <https://git.ziirish.me/ziirish/burp-ui/issues/46>`_
- Fix issue `#49 <https://git.ziirish.me/ziirish/burp-ui/issues/49>`_
- Fix issue `#53 <https://git.ziirish.me/ziirish/burp-ui/issues/53>`_
- Fix issue `#54 <https://git.ziirish.me/ziirish/burp-ui/issues/54>`_
- Fix issue `#59 <https://git.ziirish.me/ziirish/burp-ui/issues/59>`_
- Fix issue `#62 <https://git.ziirish.me/ziirish/burp-ui/issues/62>`_
- Fix issue `#68 <https://git.ziirish.me/ziirish/burp-ui/issues/68>`_
- Fix issue `#69 <https://git.ziirish.me/ziirish/burp-ui/issues/69>`_
- Fix issue `#70 <https://git.ziirish.me/ziirish/burp-ui/issues/70>`_
- Fix issue `#71 <https://git.ziirish.me/ziirish/burp-ui/issues/71>`_
- Fix issue `#72 <https://git.ziirish.me/ziirish/burp-ui/issues/72>`_
- doc on `readthedocs <http://burp-ui.readthedocs.org/en/latest/>`_
- Fix: issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix: issue `#37 <https://git.ziirish.me/ziirish/burp-ui/issues/37>`_
- Fix: issue `#41 <https://git.ziirish.me/ziirish/burp-ui/issues/41>`_
- Fix: issue `#42 <https://git.ziirish.me/ziirish/burp-ui/issues/42>`_
- Fix: issue `#46 <https://git.ziirish.me/ziirish/burp-ui/issues/46>`_
- Fix: issue `#49 <https://git.ziirish.me/ziirish/burp-ui/issues/49>`_
- Fix: issue `#53 <https://git.ziirish.me/ziirish/burp-ui/issues/53>`_
- Fix: issue `#54 <https://git.ziirish.me/ziirish/burp-ui/issues/54>`_
- Fix: issue `#59 <https://git.ziirish.me/ziirish/burp-ui/issues/59>`_
- Fix: issue `#62 <https://git.ziirish.me/ziirish/burp-ui/issues/62>`_
- Fix: issue `#68 <https://git.ziirish.me/ziirish/burp-ui/issues/68>`_
- Fix: issue `#69 <https://git.ziirish.me/ziirish/burp-ui/issues/69>`_
- Fix: issue `#70 <https://git.ziirish.me/ziirish/burp-ui/issues/70>`_
- Fix: issue `#71 <https://git.ziirish.me/ziirish/burp-ui/issues/71>`_
- Fix: issue `#72 <https://git.ziirish.me/ziirish/burp-ui/issues/72>`_
- doc on `readthedocs <http://burp-ui.readthedocs.io/en/latest/>`_
- Two merge requests from Wade Fitzpatrick (`!1 <https://git.ziirish.me/ziirish/burp-ui/merge_requests/1>`_ and `!2 <https://git.ziirish.me/ziirish/burp-ui/merge_requests/2>`_)
- API refactoring
- Security fixes
......@@ -80,19 +120,19 @@ Current
0.0.6 (12/15/2014)
------------------
- Add `gunicorn support <https://git.ziirish.me/ziirish/burp-ui/commit/836f522f51ba0706ca94b379d93b20c75e71ecb1>`_
- Add `init script for CentOS <https://git.ziirish.me/ziirish/burp-ui/issues/27>`_
- Add `init script for Debian <https://git.ziirish.me/ziirish/burp-ui/issues/29>`_
- Add `autofocus login field on login page <https://git.ziirish.me/ziirish/burp-ui/commit/a559c3c2191991f1065ff15df4cd94757133e67d>`_
- Add `burp-server configuration panel <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix issue `#25 <https://git.ziirish.me/ziirish/burp-ui/issues/25>`_
- Fix issue `#26 <https://git.ziirish.me/ziirish/burp-ui/issues/26>`_
- Fix issue `#30 <https://git.ziirish.me/ziirish/burp-ui/issues/30>`_
- Fix issue `#32 <https://git.ziirish.me/ziirish/burp-ui/issues/32>`_
- Fix issue `#33 <https://git.ziirish.me/ziirish/burp-ui/issues/33>`_
- Fix issue `#34 <https://git.ziirish.me/ziirish/burp-ui/issues/34>`_
- Fix issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix issue `#39 <https://git.ziirish.me/ziirish/burp-ui/issues/39>`_
- Add: `gunicorn support <https://git.ziirish.me/ziirish/burp-ui/commit/836f522f51ba0706ca94b379d93b20c75e71ecb1>`_
- Add: `init script for CentOS <https://git.ziirish.me/ziirish/burp-ui/issues/27>`_
- Add: `init script for Debian <https://git.ziirish.me/ziirish/burp-ui/issues/29>`_
- Add: `autofocus login field on login page <https://git.ziirish.me/ziirish/burp-ui/commit/a559c3c2191991f1065ff15df4cd94757133e67d>`_
- Add: `burp-server configuration panel <https://git.ziirish.me/ziirish/burp-ui/issues/13>`_
- Fix: issue `#25 <https://git.ziirish.me/ziirish/burp-ui/issues/25>`_
- Fix: issue `#26 <https://git.ziirish.me/ziirish/burp-ui/issues/26>`_
- Fix: issue `#30 <https://git.ziirish.me/ziirish/burp-ui/issues/30>`_
- Fix: issue `#32 <https://git.ziirish.me/ziirish/burp-ui/issues/32>`_
- Fix: issue `#33 <https://git.ziirish.me/ziirish/burp-ui/issues/33>`_
- Fix: issue `#34 <https://git.ziirish.me/ziirish/burp-ui/issues/34>`_
- Fix: issue `#35 <https://git.ziirish.me/ziirish/burp-ui/issues/35>`_
- Fix: issue `#39 <https://git.ziirish.me/ziirish/burp-ui/issues/39>`_
- Code cleanup
- Improve unit tests
- Bugfixes
......@@ -101,20 +141,20 @@ Current
0.0.5 (09/22/2014)
------------------
- Add multi-server support
- Add: multi-server support
- Fix bugs
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.4...v0.0.5>`__
0.0.4 (09/07/2014)
------------------
- Add the ability to download files directly from the web interface
- Add: ability to download files directly from the web interface
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.3...v0.0.4>`__
0.0.3 (09/02/2014)
------------------
- Add authentication
- Add: authentication
- `Full changelog <https://git.ziirish.me/ziirish/burp-ui/compare/v0.0.2...v0.0.3>`__
0.0.2 (08/25/2014)
......
......@@ -2,5 +2,5 @@ CONTRIBUTING
============
Please refer to the contributing
`page <https://burp-ui.readthedocs.org/en/latest/contributing.html>`_ available
`page <https://burp-ui.readthedocs.io/en/stable/contributing.html>`_ available
in the documentation.
This is a non-exhaustive list of people that have submitted patches or
contributed significantly to the project.
Sorted by surname (or nickname).
bedaes
Wade Fitzpatrick
Graham Keeling (main author of Burp)
larsen0815
Benjamin SANS (main author)
slarti5191
Badges
======
.. image:: https://ci.ziirish.me/projects/1/status.png?ref=stable
:target: https://ci.ziirish.me/projects/1?ref=stable
.. image:: https://git.ziirish.me/ci/projects/1/status.png?ref=master
:target: https://git.ziirish.me/ci/projects/1?ref=master
:alt: Build Status
.. image:: https://readthedocs.org/projects/burp-ui/badge/?version=stable
......@@ -58,14 +58,14 @@ Documentation
=============
The documentation is hosted on `readthedocs <https://readthedocs.org>`_ at the
following address: `burp-ui.readthedocs.org
<https://burp-ui.readthedocs.org/en/stable/>`_
following address: `burp-ui.readthedocs.io
<https://burp-ui.readthedocs.io/en/stable/>`_
FAQ
===
A `FAQ <https://burp-ui.readthedocs.org/en/stable/faq.html>`_ is available with
A `FAQ <https://burp-ui.readthedocs.io/en/stable/faq.html>`_ is available with
the documentation.
......@@ -73,7 +73,7 @@ Community
=========
Please refer to the `Contributing
<https://burp-ui.readthedocs.org/en/stable/contributing.html>`_ page.
<https://burp-ui.readthedocs.io/en/stable/contributing.html>`_ page.
Notes
......@@ -83,7 +83,7 @@ Feel free to report any issues on my `gitlab
<https://git.ziirish.me/ziirish/burp-ui/issues>`_.
I have closed the *github tracker* to have a unique tracker system.
Also please, read the `Contributing
<https://burp-ui.readthedocs.org/en/stable/contributing.html>`_
<https://burp-ui.readthedocs.io/en/stable/contributing.html>`_
page before reporting any issue to make sure we have all the informations to
help you.
......@@ -120,6 +120,8 @@ Thanks
Thank you all for your feedbacks and bug reports those are making the project
moving forward.
Thank you to the `Flask`_'s developers and community.
Special Thanks to Graham Keeling for its great piece of software! This project
would not exist without `Burp`_.
......
......@@ -13,6 +13,7 @@ jQuery/Bootstrap
import os
import sys
import logging
from logging import Formatter
if sys.version_info < (3, 0):
reload(sys)
......@@ -22,7 +23,7 @@ __title__ = 'burp-ui'
__author__ = 'Benjamin SANS (Ziirish)'
__author_email__ = 'hi+burpui@ziirish.me'
__url__ = 'https://git.ziirish.me/ziirish/burp-ui'
__doc__ = 'https://burp-ui.readthedocs.org/en/latest/'
__doc__ = 'https://burp-ui.readthedocs.io/en/stable/'
__description__ = ('Burp-UI is a web-ui for burp backup written in python with '
'Flask and jQuery/Bootstrap')
__license__ = 'BSD 3-clause'
......@@ -40,7 +41,7 @@ except: # pragma: no cover
def lookup_config(conf=None):
ret = None
if conf:
if os.path.isfile(conf):
if os.path.isfile(conf) or conf == '/dev/null':
ret = conf
else:
raise IOError('File not found: \'{0}\''.format(conf))
......@@ -58,12 +59,24 @@ def lookup_config(conf=None):
'burpui',
'etc'
)
root3 = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'..',
'..',
'..',
'..',
'share',
'burpui',
'etc',
)
conf_files = [
'/etc/burp/burpui.cfg',
os.path.join(root, 'burpui.cfg'),
os.path.join(root, 'burpui.sample.cfg'),
os.path.join(root2, 'burpui.cfg'),
os.path.join(root2, 'burpui.sample.cfg')
os.path.join(root2, 'burpui.sample.cfg'),
os.path.join(root3, 'burpui.cfg'),
os.path.join(root3, 'burpui.sample.cfg')
]
for p in conf_files:
if os.path.isfile(p):
......@@ -73,14 +86,14 @@ def lookup_config(conf=None):
return ret
def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
def init(conf=None, verbose=0, logfile=None, gunicorn=True, unittest=False, debug=False):
"""Initialize the whole application.
:param conf: Configuration file to use
:type conf: str
:param debug: Enable verbose output
:type debug: int
:param verbose: Set the verbosity level
:type verbose: int
:param logfile: Store the logs in the given file
:type logfile: str
......@@ -88,15 +101,84 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
:param gunicorn: Enable gunicorn engine instead of flask's default
:type gunicorn: bool
:param unittest: Are we running tests (used for test only)
:type unittest: bool
:param debug: Enable debug mode
:type debug: bool
:returns: A :class:`burpui.server.BUIServer` object
"""
from flask.ext.login import LoginManager
from flask.ext.bower import Bower
from .utils import basic_login_from_request
from flask_login import LoginManager
from flask_bower import Bower
from .utils import basic_login_from_request, ReverseProxied
from .server import BUIServer as BurpUI
from .routes import view
from .api import api, apibp
logger = logging.getLogger('burp-ui')
# The debug argument used to be a boolean so we keep supporting this format
if isinstance(verbose, bool):
if verbose:
verbose = logging.DEBUG
else:
verbose = logging.CRITICAL
else:
levels = [
logging.CRITICAL,
logging.ERROR,
logging.WARNING,
logging.INFO,
logging.DEBUG
]
if verbose >= len(levels):
verbose = len(levels) - 1
if not verbose:
verbose = 0
verbose = levels[verbose]
if logfile:
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
logfile,
maxBytes=1024 * 1024 * 100,
backupCount=5
)
else:
from logging import StreamHandler
handler = StreamHandler()
if verbose > logging.DEBUG:
LOG_FORMAT = (
'[%(asctime)s] %(levelname)s in '
'%(module)s.%(funcName)s: %(message)s'
)
else:
LOG_FORMAT = (
'-' * 80 + '\n' +
'%(levelname)s in %(module)s.%(funcName)s ' +
'[%(pathname)s:%(lineno)d]:\n' +
'%(message)s\n' +
'-' * 80
)
handler.setLevel(verbose)
handler.setFormatter(Formatter(LOG_FORMAT))
logger.setLevel(verbose)
logger.addHandler(handler)
logger.debug(
'conf: {}\n'.format(conf) +
'verbose: {}\n'.format(logging.getLevelName(verbose)) +
'logfile: {}\n'.format(logfile) +
'gunicorn: {}\n'.format(gunicorn) +
'debug: {}\n'.format(debug) +
'unittest: {}'.format(unittest)
)
if not unittest:
from ._compat import patch_json
patch_json()
......@@ -107,72 +189,47 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
# We initialize the core
app = BurpUI()
app.enable_logger()
app.gunicorn = gunicorn
app.config['CFG'] = None
# FIXME: strange behavior when bundling errors
# app.config['BUNDLE_ERRORS'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.secret_key = ('VpgOXNXAgcO81xFPyWj07ppN6kExNZeCDRShseNzFKV7ZCgmW2/eLn6x'
'Slt7pYAVBj12zx2Vv9Kw3Q3jd1266A==')
app.jinja_env.globals.update(
isinstance=isinstance,
list=list,
version_id='{}-{}'.format(__version__, __release__)
)
# The debug argument used to be a boolean so we keep supporting this format
if isinstance(debug, bool):
if debug:
debug = logging.DEBUG
else:
debug = logging.NOTSET
else:
levels = [
logging.NOTSET,
logging.ERROR,
logging.WARNING,
logging.INFO,
logging.DEBUG
]
if debug >= len(levels):
debug = len(levels) - 1
if not debug:
debug = 0
debug = levels[debug]
if debug != logging.NOTSET and not gunicorn: # pragma: no cover
if debug and not gunicorn: # pragma: no cover
app.config['DEBUG'] = True and not unittest
app.config['TESTING'] = True and not unittest
if logfile:
from logging import Formatter
from logging.handlers import RotatingFileHandler
file_handler = RotatingFileHandler(
logfile,
maxBytes=1024 * 1024 * 100,
backupCount=20
)
if debug < logging.INFO:
LOG_FORMAT = (
'-' * 80 + '\n' +
'%(levelname)s in %(module)s.%(funcName)s ' +
'[%(pathname)s:%(lineno)d]:\n' +
'%(message)s\n' +
'-' * 80
)
else:
LOG_FORMAT = ('[%(asctime)s] %(levelname)s in '
'%(module)s.%(funcName)s: %(message)s')
file_handler.setLevel(debug)
file_handler.setFormatter(Formatter(LOG_FORMAT))
app.logger.addHandler(file_handler)
# Still need to test conf file here because the init function can be called
# by gunicorn directly
app.config['CFG'] = lookup_config(conf)
logger.info('Using configuration: {}'.format(app.config['CFG']))
app.setup(app.config['CFG'])
# manage application secret key
if not app.secret_key or app.secret_key.lower() == 'random' and \
not gunicorn:
from base64 import b64encode
app.secret_key = b64encode(os.urandom(256))
elif app.secret_key.lower() == 'none' or \
(app.secret_key.lower() == 'random' and gunicorn):
app.secret_key = None
app.wsgi_app = ReverseProxied(app.wsgi_app, app)
# Manage gunicorn special tricks & improvements
if gunicorn: # pragma: no cover
logger.info('Using gunicorn')
from werkzeug.contrib.fixers import ProxyFix
if app.storage and app.storage.lower() == 'redis':
if app.redis:
......@@ -185,16 +242,19 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
else:
host = 'localhost'
port = 6379
logger.debug('Using redis {}:{}'.format(host, port))
try:
from redis import Redis
from flask.ext.session import Session
from flask_session import Session
red = Redis(host=host, port=port)
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = red
app.config['SESSION_COOKIE_SECURE'] = app.scookie
app.config['SESSION_USE_SIGNER'] = app.secret_key != None
app.config['SESSION_PERMANENT'] = False
ses = Session()
ses.init_app(app)
except:
except Exception as e:
logger.warning('Unable to initialize redis: {}'.format(str(e)))
pass
api.cache.init_app(
app,
......@@ -215,12 +275,6 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
else:
api.cache.init_app(app)
# Then we load our routes
view.init_bui(app)
view.__url__ = __url__
view.__doc__ = __doc__
app.register_blueprint(view)
# We initialize the API
api.init_bui(app)
api.version = __version__
......@@ -229,6 +283,12 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
api.__doc__ = __doc__
app.register_blueprint(apibp)
# Then we load our routes
view.init_bui(app)
view.__url__ = __url__
view.__doc__ = __doc__
app.register_blueprint(view)
# And the login_manager
app.login_manager = LoginManager()
app.login_manager.login_view = 'view.login'
......@@ -244,12 +304,23 @@ def init(conf=None, debug=0, logfile=None, gunicorn=True, unittest=False):
bower = Bower()
bower.init_app(app)
@app.before_request
def setup_request():
if app.scookie:
from flask import request
criteria = [
request.is_secure,
request.headers.get('X-Forwarded-Proto', 'http') == 'https'
]
app.config['SESSION_COOKIE_SECURE'] = \
app.config['REMEMBER_COOKIE_SECURE'] = any(criteria)
@app.login_manager.user_loader
def load_user(userid):
"""User loader callback"""
if app.auth != 'none':
return app.uhandler.user(userid)
return None # pragma: no cover
return None
@app.login_manager.request_loader
def load_user_from_request(request):
......
......@@ -13,7 +13,7 @@ def parse_args(mode=True, name=None):
name = 'burp-ui'
parser = ArgumentParser(prog=name)
parser.add_argument('-v', '--verbose', dest='log', help='increase output verbosity (e.g., -vv is more verbose than -v)', action='count')
parser.add_argument('-d', '--debug', dest='log', help='alias for -v', action='count') # alias for -v
parser.add_argument('-d', '--debug', dest='debug', help='enable debug mode', action='store_true') # alias for -v
parser.add_argument('-V', '--version', dest='version', help='print version and exit', action='store_true')
parser.add_argument('-c', '--config', dest='config', help='configuration file', metavar='<CONFIG>')
parser.add_argument('-l', '--logfile', dest='logfile', help='output logs in defined file', metavar='<FILE>')
......@@ -54,7 +54,7 @@ def server(options=None):
conf = lookup_config(options.config)
check_config(conf)
server = init(conf, options.log, options.logfile, False)
server = init(conf, options.log, options.logfile, False, debug=options.debug)
server.manual_run()
......@@ -85,12 +85,24 @@ def agent(options=None):
'burpui',
'etc'
)
root3 = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'..',
'..',
'..',
'..',
'share',
'burpui',
'etc',
)
conf_files = [
'/etc/burp/buiagent.cfg',
os.path.join(root, 'buiagent.cfg'),
os.path.join(root, 'buiagent.sample.cfg'),
os.path.join(root2, 'buiagent.cfg'),
os.path.join(root2, 'buiagent.sample.cfg')
os.path.join(root2, 'buiagent.sample.cfg'),
os.path.join(root3, 'buiagent.cfg'),
os.path.join(root3, 'buiagent.sample.cfg')
]
for p in conf_files:
if os.path.isfile(p):
......@@ -99,7 +111,7 @@ def agent(options=None):
check_config(conf)
agent = Agent(conf, options.log, options.logfile)
agent = Agent(conf, options.log, options.logfile, options.debug)
agent.run()
......
......@@ -11,28 +11,26 @@ import sys
import os
try:
import ConfigParser # NOQA
import ConfigParser # noqa
except ImportError:
import configparser as ConfigParser # NOQA
import configparser as ConfigParser # noqa
try:
import cPickle as pickle # NOQA
import cPickle as pickle # noqa
except ImportError:
import pickle # NOQA
import pickle # noqa
if sys.version_info[0] >= 3:
PY3 = True
from urllib.parse import unquote # NOQA
from urllib.parse import unquote # noqa
else:
PY3 = False
from urllib import unquote # NOQA
from urllib import unquote # noqa
IS_GUNICORN = 'gunicorn' in os.environ.get('SERVER_SOFTWARE', '')
if IS_GUNICORN:
from gevent.local import local # NOQA
if 'gunicorn' in os.environ.get('SERVER_SOFTWARE', ''):
IS_GUNICORN = True
else:
local = object
IS_GUNICORN = False
# maps module name -> attribute name -> original item
......@@ -66,7 +64,7 @@ def patch_module(name, items=None):
def patch_json():
try:
import ujson # NOQA
import ujson # noqa
except ImportError:
# ujson is not available, we won't patch anything
return
......
......@@ -12,4 +12,4 @@
from . import init
app = init(gunicorn=False)
app = init(conf='/dev/null', gunicorn=False)
......@@ -13,6 +13,7 @@ from logging.handlers import RotatingFileHandler
from .exceptions import BUIserverException
from .misc.backend.interface import BUIbackend
from ._compat import ConfigParser, pickle
from .utils import BUIlogging
g_port = u'10000'
g_bind = u'::'
......@@ -43,9 +44,8 @@ class BurpHandler(BUIbackend):
mod = __import__(module, fromlist=['Burp'])
Client = mod.Burp
self.backend = Client(conf=conf)
self.backend.set_logger(self.logger)
except Exception as e:
self._logger('error', '{}\n\nFailed loading backend for Burp version {}: {}'.format(traceback.format_exc(), self.vers, str(e)))
self.logger.error('{}\n\nFailed loading backend for Burp version {}: {}'.format(traceback.format_exc(), self.vers, str(e)))
sys.exit(2)
def __getattribute__(self, name):
......@@ -60,7 +60,7 @@ class BurpHandler(BUIbackend):
return object.__getattribute__(self, name)
class BUIAgent(BUIbackend):
class BUIAgent(BUIbackend, BUIlogging):
BUIbackend.__abstractmethods__ = frozenset()
defaults = {
'port': g_port, 'bind': g_bind,
......@@ -68,30 +68,37 @@ class BUIAgent(BUIbackend):
'version': g_version, 'password': g_password
}
def __init__(self, conf=None, debug=False, logfile=None):
def __init__(self, conf=None, level=0, logfile=None, debug=False):
self.conf = conf
self.dbg = debug
self.debug = debug
self.padding = 1
if debug > logging.NOTSET:
if level > logging.NOTSET:
logging.addLevelName(DISCLOSURE, 'DISCLOSURE')
levels = [0, logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG, DISCLOSURE]
if debug >= len(levels):
debug = len(levels) - 1
lvl = levels[debug]
self.app.logger = logging.getLogger(__name__)
self.set_logger(self.app.logger)
levels = [
logging.CRITICAL,
logging.ERROR,
logging.WARNING,
logging.INFO,
logging.DEBUG,
DISCLOSURE
]
if level >= len(levels):
level = len(levels) - 1
lvl = levels[level]
self.logger.setLevel(lvl)
if logfile:
handler = RotatingFileHandler(logfile, maxBytes=1024 * 1024 * 100, backupCount=20)
if lvl > logging.DEBUG:
LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s.%(funcName)s: %(message)s'
else:
handler = logging.StreamHandler()
LOG_FORMAT = (
'-' * 80 + '\n' +
'%(levelname)s in %(module)s.%(funcName)s [%(pathname)s:%(lineno)d]:\n' +
'%(message)s\n' +
'-' * 80
)
if logfile:
handler = RotatingFileHandler(logfile, maxBytes=1024 * 1024 * 100, backupCount=20)
else:
handler = logging.StreamHandler()
handler.setLevel(lvl)
handler.setFormatter(logging.Formatter(LOG_FORMAT))
self.logger.addHandler(handler)
......@@ -184,6 +191,12 @@ class BUIAgent(BUIbackend):
self.request.sendall(buf)
buf = f.read(1024)
os.unlink(res)
lengthbuf = self.request.recv(8)
length, = struct.unpack('!Q', lengthbuf)
data = self.recvall(length)
txt = data.decode('UTF-8')
if txt == 'RE':
return
else:
self.request.sendall(struct.pack('!Q', len(res)))
self.request.sendall(res.encode('UTF-8'))
......
......@@ -10,18 +10,17 @@
"""
import os
import sys
import json
from flask import Blueprint, Response, request
from flask.ext.restplus import Api
from flask.ext.login import current_user
from flask.ext.cache import Cache
from flask_restplus import Api
from flask_login import current_user
from flask_cache import Cache
from importlib import import_module
from functools import wraps
from .._compat import IS_GUNICORN
from .._compat import IS_GUNICORN, PY3
if sys.version_info >= (3, 0): # pragma: no cover
if PY3: # pragma: no cover
basestring = str
EXEMPT_METHODS = set(['OPTIONS'])
......@@ -33,7 +32,7 @@ if IS_GUNICORN:
import gevent
from gevent.queue import Queue
ret = []
api.bui.cli._logger('debug', 'Using gevent')
api.bui.cli.logger.debug('Using gevent')
if not callable(func):
api.abort(500, 'The provided \'func\' is not callable!')
......@@ -127,7 +126,7 @@ def api_login_required(func):
class ApiWrapper(Api):
"""Wrapper class around :class:`flask.ext.restplus.Api`"""
"""Wrapper class around :class:`flask_restplus.Api`"""
cache = Cache(config={'CACHE_TYPE': 'null', 'CACHE_NO_NULL_WARNING': True})
loaded = False
release = None
......@@ -143,17 +142,6 @@ class ApiWrapper(Api):
self.bui = bui
self.load_all()
def abort(self, code=500, message=None, **kwargs):
"""Override :func:`flask.ext.restplus.Api.abort` in order to raise
custom exceptions
"""
if message and not isinstance(message, basestring):
try:
message = json.dumps(message) # pragma: no cover
except:
message = None
super(ApiWrapper, self).abort(code, message, **kwargs) # pragma: no cover
def load_all(self):
"""hack to automatically import api modules"""
if not self.loaded:
......@@ -165,7 +153,7 @@ class ApiWrapper(Api):
ext == '.py' and
name not in ['__init__', '.', '..']):
mod = '.' + name
import_module(mod, 'burpui.api')
import_module(mod, __name__)
apibp = Blueprint('api', __name__, url_prefix='/api')
......
# -*- coding: utf8 -*-
"""
.. module:: burpui.api.backup
:platform: Unix
:synopsis: Burp-UI backup api module.
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
from . import api
from .custom import Resource
from ..exceptions import BUIserverException
ns = api.namespace('backup', 'Backup methods')
@ns.route('/server-backup/<name>',
'/<server>/server-backup/<name>',
methods=['GET', 'DELETE'],
endpoint='is_server_backup')
@ns.route('/do-server-backup/<name>',
'/<server>/do-server-backup/<name>',
methods=['PUT'],
endpoint='server_backup')
class ServerBackup(Resource):
"""The :class:`burpui.api.backup.ServerBackup` resource allows you to
prepare a server-initiated backup.
This resource is part of the :mod:`burpui.api.backup` module.
"""
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
'name': 'Client name',
},
responses={
200: 'Success',
400: 'Missing parameter',
403: 'Insufficient permissions',
500: 'Internal failure',
},
)
def get(self, server=None, name=None):
"""Tells if a 'backup' file is present
**GET** method provided by the webservice.
:param server: Which server to collect data from when in multi-agent
mode
:type server: str
:param name: The client we are working on
:type name: str
:returns: True if the file is found
"""
if not name:
self.abort(400, 'Missing options')
# Manage ACL
if (api.bui.acl and
(not api.bui.acl.is_client_allowed(self.username,
name,
server) and not
self.is_admin)):
self.abort(403, 'You are not allowed to access this client')
try:
return {'is_server_backup': api.bui.cli.is_server_backup(name, server)}
except BUIserverException as e:
self.abort(500, str(e))
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
'name': 'Client name',
},
responses={
200: 'Success',
400: 'Missing parameter',
403: 'Insufficient permissions',
500: 'Internal failure',
},
)
def delete(self, server=None, name=None):
"""Remove the 'backup' file if present
**DELETE** method provided by the webservice.
:param server: Which server to collect data from when in multi-agent
mode
:type server: str
:param name: The client we are working on
:type name: str
:returns: Status message (success or failure)
"""
if not name:
self.abort(400, 'Missing options')
# Manage ACL
if (api.bui.acl and
(not api.bui.acl.is_client_allowed(self.username,
name,
server) and not
self.is_admin)):
self.abort(403, 'You are not allowed to cancel a backup for this client')
try:
return api.bui.cli.cancel_server_backup(name, server)
except BUIserverException as e:
self.abort(500, str(e))
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
'name': 'Client name',
},
responses={
201: 'Success',
400: 'Missing parameter',
403: 'Insufficient permissions',
500: 'Internal failure',
},
)
def put(self, server=None, name=None):
"""Schedule a server-initiated backup
**PUT** method provided by the webservice.
:param server: Which server to collect data from when in multi-agent
mode
:type server: str
:param name: The client we are working on
:type name: str
:returns: Status message (success or failure)
"""
json = []
# Check params
if not name:
self.abort(400, 'Missing options')
# Manage ACL
if (api.bui.acl and
(not api.bui.acl.is_client_allowed(self.username,
name,
server) and not
self.is_admin and
(to and not
api.bui.acl.is_client_allowed(self.username,
to,
server)))):
self.abort(
403,
'You are not allowed to schedule a backup for this client'
)
try:
json = api.bui.cli.server_backup(name, server)
return json, 201
except BUIserverException as e:
self.abort(500, str(e))
This diff is collapsed.
......@@ -7,13 +7,11 @@
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
# This is a submodule we can also use "from ..api import api"
from . import api, cache_key
from .custom import fields, Resource
from ..exceptions import BUIserverException
from six import iteritems
from flask.ext.login import current_user
ns = api.namespace('clients', 'Clients methods')
......@@ -33,14 +31,14 @@ class RunningClients(Resource):
in multi-agent mode.
"""
parser = api.parser()
parser.add_argument('serverName', type=str, help='Which server to collect data from when in multi-agent mode')
parser.add_argument('serverName', help='Which server to collect data from when in multi-agent mode')
@api.doc(
@ns.expect(parser)
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
'client': 'Client name',
},
parser=parser
)
def get(self, client=None, server=None):
"""Returns a list of clients currently running a backup
......@@ -67,8 +65,8 @@ class RunningClients(Resource):
server = server or self.parser.parse_args()['serverName']
if client:
if api.bui.acl:
if (not api.bui.acl.is_admin(current_user.get_id()) and not
api.bui.acl.is_client_allowed(current_user.get_id(),
if (not self.is_admin and not
api.bui.acl.is_client_allowed(self.username,
client,
server)):
r = []
......@@ -82,16 +80,15 @@ class RunningClients(Resource):
r = api.bui.cli.is_one_backup_running(server)
# Manage ACL
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.get_id())):
if api.bui.acl and not self.is_admin:
if isinstance(r, dict):
new = {}
for serv in api.bui.acl.servers(current_user.get_id()):
allowed = api.bui.acl.clients(current_user.get_id(), serv)
for serv in api.bui.acl.servers(self.username):
allowed = api.bui.acl.clients(self.username, serv)
new[serv] = [x for x in r[serv] if x in allowed]
r = new
else:
allowed = api.bui.acl.clients(current_user.get_id(), server)
allowed = api.bui.acl.clients(self.username, server)
r = [x for x in r if x in allowed]
return r
......@@ -110,8 +107,8 @@ class RunningBackup(Resource):
'running': fields.Boolean(required=True, description='Is there a backup running right now'),
})
@api.marshal_with(running_fields, code=200, description='Success')
@api.doc(
@ns.marshal_with(running_fields, code=200, description='Success')
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
}
......@@ -139,16 +136,15 @@ class RunningBackup(Resource):
"""
j = api.bui.cli.is_one_backup_running(server)
# Manage ACL
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.get_id())):
if api.bui.acl and not self.is_admin:
if isinstance(j, dict):
new = {}
for serv in api.bui.acl.servers(current_user.get_id()):
allowed = api.bui.acl.clients(current_user.get_id(), serv)
for serv in api.bui.acl.servers(self.username):
allowed = api.bui.acl.clients(self.username, serv)
new[serv] = [x for x in j[serv] if x in allowed]
j = new
else:
allowed = api.bui.acl.clients(current_user.get_id(), server)
allowed = api.bui.acl.clients(self.username, server)
j = [x for x in j if x in allowed]
r = False
if isinstance(j, dict):
......@@ -174,7 +170,7 @@ class ClientsReport(Resource):
in multi-agent mode.
"""
parser = api.parser()
parser.add_argument('serverName', type=str, help='Which server to collect data from when in multi-agent mode')
parser.add_argument('serverName', help='Which server to collect data from when in multi-agent mode')
stats_fields = api.model('ClientsStats', {
'total': fields.Integer(required=True, description='Number of files', default=0),
'totsize': fields.Integer(required=True, description='Total size occupied by all the backups of this client', default=0),
......@@ -194,8 +190,9 @@ class ClientsReport(Resource):
})
@api.cache.cached(timeout=1800, key_prefix=cache_key)
@api.marshal_with(report_fields, code=200, description='Success')
@api.doc(
@ns.marshal_with(report_fields, code=200, description='Success')
@ns.expect(parser)
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
},
......@@ -203,7 +200,6 @@ class ClientsReport(Resource):
403: 'Insufficient permissions',
500: 'Internal failure',
},
parser=parser
)
def get(self, server=None):
"""Returns a global report about all the clients of a given server
......@@ -258,19 +254,18 @@ class ClientsReport(Resource):
j = {}
# Manage ACL
if (not api.bui.standalone and api.bui.acl and
(not api.bui.acl.is_admin(current_user.get_id()) and
(not self.is_admin and
server not in
api.bui.acl.servers(current_user.get_id()))):
api.abort(403, 'Sorry, you don\'t have any rights on this server')
api.bui.acl.servers(self.username))):
self.abort(403, 'Sorry, you don\'t have any rights on this server')
clients = []
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.get_id())):
clients = [{'name': x} for x in api.bui.acl.clients(current_user.get_id(), server)]
if api.bui.acl and not self.is_admin:
clients = [{'name': x} for x in api.bui.acl.clients(self.username, server)]
else:
try:
clients = api.bui.cli.get_all_clients(agent=server)
except BUIserverException as e:
api.abort(500, str(e))
self.abort(500, str(e))
j = api.bui.cli.get_clients_report(clients, server)
return j
......@@ -288,7 +283,7 @@ class ClientsStats(Resource):
in multi-agent mode.
"""
parser = api.parser()
parser.add_argument('serverName', type=str, help='Which server to collect data from when in multi-agent mode')
parser.add_argument('serverName', help='Which server to collect data from when in multi-agent mode')
client_fields = api.model('ClientsStatsSingle', {
'last': fields.DateTime(required=True, dt_format='iso8601', description='Date of last backup'),
'name': fields.String(required=True, description='Client name'),
......@@ -298,8 +293,9 @@ class ClientsStats(Resource):
})
@api.cache.cached(timeout=1800, key_prefix=cache_key)
@api.marshal_list_with(client_fields, code=200, description='Success')
@api.doc(
@ns.marshal_list_with(client_fields, code=200, description='Success')
@ns.expect(parser)
@ns.doc(
params={
'server': 'Which server to collect data from when in multi-agent mode',
},
......@@ -307,7 +303,6 @@ class ClientsStats(Resource):
403: 'Insufficient permissions',
500: 'Internal failure',
},
parser=parser
)
def get(self, server=None):
"""Returns a list of clients with their states
......@@ -350,14 +345,13 @@ class ClientsStats(Resource):
try:
if (not api.bui.standalone and
api.bui.acl and
(not api.bui.acl.is_admin(current_user.get_id()) and
(not self.is_admin and
server not in
api.bui.acl.servers(current_user.get_id()))):
api.abort(403, 'Sorry, you don\'t have any rights on this server')
api.bui.acl.servers(self.username))):
self.abort(403, 'Sorry, you don\'t have any rights on this server')
j = api.bui.cli.get_all_clients(agent=server)
if (api.bui.acl and not
api.bui.acl.is_admin(current_user.get_id())):
j = [x for x in j if x['name'] in api.bui.acl.clients(current_user.get_id(), server)]
if api.bui.acl and not self.is_admin:
j = [x for x in j if x['name'] in api.bui.acl.clients(self.username, server)]
except BUIserverException as e:
api.abort(500, str(e))
self.abort(500, str(e))
return j
......@@ -7,4 +7,4 @@
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
from .resource import Resource
from .resource import Resource # noqa
......@@ -8,5 +8,5 @@
"""
from flask.ext.restplus.fields import *
from .my_fields import DateTime, BackupNumber
from flask_restplus.fields import * # noqa
from .my_fields import DateTime, BackupNumber # noqa
# -*- coding: utf8 -*-
"""
.. module:: burpui.api.custom.inputs
:platform: Unix
:synopsis: Burp-UI api custom inputs module.
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
from flask_restplus.inputs import * # noqa
from .my_inputs import boolean # noqa
......@@ -10,7 +10,7 @@
"""
import arrow
from flask.ext.restplus import fields
from flask_restplus import fields
from tzlocal import get_localzone
......
# -*- coding: utf8 -*-
"""
.. module:: burpui.api.custom.my_inputs
:platform: Unix
:synopsis: Burp-UI api custom inputs module.
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
from flask_restplus.inputs import boolean as boolean_ori
def boolean(value):
"""
Parse the string ``"true"`` or ``"false"`` as a boolean (case insensitive).
Also accepts ``"1"`` and ``"0"`` as ``True``/``False`` (respectively).
A form checkbox returns ``"on"`` when checked. This will be treated as
``True``.
If the input is from the request JSON body, the type is already a native
python boolean, and will be passed through without further parsing.
:raises ValueError: if the boolean value is invalid
"""
try:
return boolean_ori(value)
except ValueError as e:
if not value:
return False
value = value.lower()
if value == 'on':
return True
raise e