]> git.nothing2do.fr Git - get-hack-src.git/commitdiff
Added support for automatic Canari package root detection.
authorallfro <ndouba@gmail.com>
Mon, 14 Jan 2013 21:52:29 +0000 (16:52 -0500)
committerallfro <ndouba@gmail.com>
Mon, 14 Jan 2013 21:52:29 +0000 (16:52 -0500)
17 files changed:
docs/Makefile [new file with mode: 0644]
docs/canari.rst [new file with mode: 0644]
docs/conf.py [new file with mode: 0644]
docs/development.rst [new file with mode: 0644]
docs/index.rst [new file with mode: 0644]
docs/intro.rst [new file with mode: 0644]
docs/make.bat [new file with mode: 0644]
src/canari/commands/common.py
src/canari/commands/create_package.py
src/canari/commands/create_transform.py
src/canari/commands/debug_transform.py
src/canari/commands/delete_transform.py
src/canari/commands/generate_entities.py
src/canari/commands/help.py
src/canari/commands/rename_transform.py
src/canari/commands/run_server.py
src/canari/commands/run_transform.py

diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644 (file)
index 0000000..7893ce4
--- /dev/null
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  html       to make standalone HTML files"
+       @echo "  dirhtml    to make HTML files named index.html in directories"
+       @echo "  singlehtml to make a single large HTML file"
+       @echo "  pickle     to make pickle files"
+       @echo "  json       to make JSON files"
+       @echo "  htmlhelp   to make HTML files and a HTML help project"
+       @echo "  qthelp     to make HTML files and a qthelp project"
+       @echo "  devhelp    to make HTML files and a Devhelp project"
+       @echo "  epub       to make an epub"
+       @echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+       @echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+       @echo "  text       to make text files"
+       @echo "  man        to make manual pages"
+       @echo "  texinfo    to make Texinfo files"
+       @echo "  info       to make Texinfo files and run them through makeinfo"
+       @echo "  gettext    to make PO message catalogs"
+       @echo "  changes    to make an overview of all changed/added/deprecated items"
+       @echo "  linkcheck  to check all external links for integrity"
+       @echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+       -rm -rf $(BUILDDIR)/*
+
+html:
+       $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+       $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+       $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+       @echo
+       @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+       $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+       @echo
+       @echo "Build finished; now you can process the pickle files."
+
+json:
+       $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+       @echo
+       @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+       $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+       @echo
+       @echo "Build finished; now you can run HTML Help Workshop with the" \
+             ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+       $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+       @echo
+       @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+             ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+       @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sploitego.qhcp"
+       @echo "To view the help file:"
+       @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sploitego.qhc"
+
+devhelp:
+       $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+       @echo
+       @echo "Build finished."
+       @echo "To view the help file:"
+       @echo "# mkdir -p $$HOME/.local/share/devhelp/sploitego"
+       @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sploitego"
+       @echo "# devhelp"
+
+epub:
+       $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+       @echo
+       @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo
+       @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+       @echo "Run \`make' in that directory to run these through (pdf)latex" \
+             "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo "Running LaTeX files through pdflatex..."
+       $(MAKE) -C $(BUILDDIR)/latex all-pdf
+       @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+       $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+       @echo
+       @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+       $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+       @echo
+       @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo
+       @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+       @echo "Run \`make' in that directory to run these through makeinfo" \
+             "(use \`make info' here to do that automatically)."
+
+info:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo "Running Texinfo files through makeinfo..."
+       make -C $(BUILDDIR)/texinfo info
+       @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+       $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+       @echo
+       @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+       $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+       @echo
+       @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+       $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+       @echo
+       @echo "Link check complete; look for any errors in the above output " \
+             "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+       $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+       @echo "Testing of doctests in the sources finished, look at the " \
+             "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/canari.rst b/docs/canari.rst
new file mode 100644 (file)
index 0000000..87d83d8
--- /dev/null
@@ -0,0 +1,452 @@
+.. _ref_canari_commander:
+
+Canari Commander
+================
+
+The Canari commander (``canari``) script provides all of the functionality to create, debug, execute, distribute, and
+install transforms. The ``canari`` commander provides the following set of commands:
+
++--------------------------+-------------------------------------------------------------------------------------------+
+| Canari Command           | Description                                                                               |
++==========================+===========================================================================================+
+| :ref:`create-package`    | Creates a Canari transform package skeleton.                                              |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`create-transform`  | Creates a new transform in the specified directory and auto-updates ``__init__.py``.      |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`csv2sheets`        | Convert mixed entity type CSVs to separated CSV sheets.                                   |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`debug-transform`   | Runs Canari local transforms in a terminal-friendly fashion.                              |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`delete-transform`  | Deletes a transform in the specified directory and auto-updates ``__init__.py``.          |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`generate-entities` | Converts Maltego entity definition files to Canari python classes. Excludes Maltego       |
+|                          | built-in entities.                                                                        |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`help`              | Provides detailed help on a specific command (alias for ``-h`` option in all commands).   |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`install-package`   | Installs and configures Canari transform packages in Maltego's UI                         |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`list-commands`     | Lists all the available Canari commands                                                   |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`mtgx2csv`          | Convert Maltego graph files (``*.mtgx``) to comma-separated values (CSV) file.            |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`rename-transform`  | Renames a transform in the specified directory and auto-updates ``__init__.py``.          |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`run-server`        | Runs a transform server for the given packages.                                           |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`run-transform`     | Runs Canari local transforms in a terminal-friendly fashion.                              |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`shell`             | Creates a Canari debug shell for the specified transform package.                         |
++--------------------------+-------------------------------------------------------------------------------------------+
+| :ref:`uninstall-package` | Uninstalls and unconfigures canari transform packages in Maltego's UI                     |
++--------------------------+-------------------------------------------------------------------------------------------+
+
+
+Canari Commands
+---------------
+
+The following subsections provide detailed information on each of the ``canari`` commands. Each of these commands accept
+an additional ``-h`` argument that is an alias to the ``help`` command.
+
+
+.. _list-commands:
+
+``list-commands``
+^^^^^^^^^^^^^^^^^
+
+The ``list-commands`` command accepts lists all of the available ``canari`` commands along with a brief description. It
+accepts no parameters::
+
+    $ canari list-commands
+    create-package - Creates a Canari transform package skeleton.
+    create-transform - Creates a new transform in the specified directory and auto-updates __init__.py.
+    csv2sheets - Convert mixed entity type CSVs to separated CSV sheets.
+    debug-transform - Runs Canari local transforms in a terminal-friendly fashion.
+    delete-transform - Deletes a transform in the specified directory and auto-updates __init__.py.
+    generate-entities - Converts Maltego entity definition files to Canari python classes. Excludes Maltego built-in entities.
+    install-package - Installs and configures canari transform packages in Maltego's UI
+    list-commands - Lists all the available canari commands
+    mtgx2csv - Convert Maltego graph files (*.mtgx) to comma-separated values (CSV) file.
+    rename-transform - Renames a transform in the specified directory and auto-updates __init__.py.
+    run-server - Runs a transform server for the given packages.
+    run-transform - Runs Canari local transforms in a terminal-friendly fashion.
+    shell - Creates a Canari debug shell for the specified transform package.
+    uninstall-package - Uninstalls and unconfigures canari transform packages in Maltego's UI
+    ...
+
+.. _help:
+
+``help``
+^^^^^^^^
+
+The ``help`` command displays detailed help on a specific ``canari`` command. It accepts the following parameters:
+
+* ``<command name>`` (**required**): the name of the ``canari`` command you're seeking help for.
+
+The following example illustrates the use of the ``canari help`` command to display detailed help for the
+``run-transform`` command::
+
+    $ canari help run-transform
+    usage: canari run-transform <transform> [param1 ... paramN] <value> [field1=value1...#fieldN=valueN]
+
+    Runs Canari local transforms in a terminal-friendly fashion.
+
+    positional arguments:
+      <transform>           The name of the transform you wish to run (e.g.
+                            sploitego.transforms.nmapfastscan).
+      <value>               The value of the input entity being passed into the
+                            local transform.
+      [param1 ... paramN]   Any extra parameters that can be sent to the local
+                            transform.
+      [field1=value1...#fieldN=valueN]
+                            The fields of the input entity being passed into the
+                            local transform.
+
+    optional arguments:
+      -h, --help            show this help message and exit
+
+.. _run-transform:
+
+``run-transform``
+^^^^^^^^^^^^^^^^^
+
+The ``run-transform`` command loads and executes the specified local transform module, returning transform results to
+the Maltego UI. It accepts the following parameters:
+
+* ``<transform module>`` (**required**): the name of the python module that contains the local transform data mining
+  logic (e.g. :py:mod:`sploitego.transforms.whatismyip`)
+* ``[param1 ... paramN]`` (**optional**): any extra local transform parameters that can be parsed using
+  :py:mod:`argparse` (e.g. ``-p 80``)
+* ``<value>`` (**required**): the value of the entity being passed into the local transform (e.g. ``google.com``)
+* ``[field1=value1...#fieldN=valueN]`` (**optional**): optionally, any entity field values delimited by # (e.g.
+  ``url=http://www.google.ca#public=true``)
+
+The following example illustrates the use of ``canari run-transform`` to execute the :py:mod:`sploitego.transforms.whatismyip`
+transform module that comes bundled with the `Sploitego <https://github.com/allfro/sploitego>`_ transform package::
+
+    $ canari run-transform sploitego.transforms.whatismyip -
+    <MaltegoMessage><MaltegoTransformResponseMessage><Entities><Entity Type="maltego.IPv4Address"><Value>192.168.0.200</Value>
+    <Weight>1</Weight><AdditionalFields><Field DisplayName="Internal" MatchingRule="strict" Name="ipaddress.internal">true</Field>
+    <Field DisplayName="Hardware Address" MatchingRule="strict" Name="ethernet.hwaddr">de:ad:be:ef:fe:ed</Field></AdditionalFields>
+    </Entity></Entities></MaltegoTransformResponseMessage></MaltegoMessage>
+
+.. _debug-transform:
+
+``debug-transform``
+^^^^^^^^^^^^^^^^^^^
+
+The ``debug-transform`` command operates in the same fashion as the :ref:`run-transform` command but outputs the result
+in a terminal friendly manner. The following example illustrates the use of ``canari debug-transform`` to execute the
+:py:mod:`sploitego.transforms.nmapfastscan` transform module on ``www.google.ca``::
+
+    $ canari run-transform sploitego.transforms.nmapfastscan www.google.com
+      `- MaltegoTransformResponseMessage:
+        `- Entities:
+          `- Entity:  {'Type': 'sploitego.Port'}
+            `- Value: 80
+            `- Weight: 1
+            `- AdditionalFields:
+              `- Field: TCP {'DisplayName': 'Protocol', 'Name': 'protocol', 'MatchingRule': 'strict'}
+              `- Field: Open {'DisplayName': 'Port Status', 'Name': 'port.status', 'MatchingRule': 'strict'}
+              `- Field: 173.194.75.147 {'DisplayName': 'Destination IP', 'Name': 'ip.destination', 'MatchingRule': 'strict'}
+              `- Field: syn-ack {'DisplayName': 'Port Response', 'Name': 'port.response', 'MatchingRule': 'strict'}
+            `- IconURL: file:///Library/Python/2.6/site-packages/canari-1.0-py2.6.egg/canari/resources/images/networking/openport.gif
+            `- DisplayInformation:
+              `- Label: http {'Type': 'text/text', 'Name': 'Service Name'}
+              `- Label: table {'Type': 'text/text', 'Name': 'Method'}
+    ...
+
+
+.. _run-server:
+
+``run-server``
+^^^^^^^^^^^^^^
+
+The ``run-server`` command loads one or more transform packages and handles remote transform requests brokered by a
+`Transform Distribution Server (TDS) <http://paterva.com>`_ via port 80 or 443 (if SSL enabled). ``run-server``
+provides similar functionality to the `Paterva Transform Application Server <http://paterva.com>`_. It accepts the
+following parameters:
+
+* ``<package>`` (**required**): The name of the transform packages you wish to host (e.g. :py:mod:`mypkg.transforms`).
+* ``--port <port>`` (**optional**): The port the server will run on (default: 443; or 80 if SSL is disabled).
+* ``--disable-ssl`` (**optional**): Any extra parameters that can be sent to the local transform.
+* ``--enable-privileged`` (**optional**): permit TAS to run packages that require elevated privileges.
+* ``--listen-on <address>`` (**optional**): The address of the interface to listen on.
+* ``--cert <certificate>`` (**optional**): The name of the certificate file used for the server in PEM format.
+* ``--hostname <hostname>`` (**optional**): The hostname of this transform server.
+* ``--daemon`` (**optional**): Daemonize server (fork to background).
+
+The following example illustrates the use of ``canari run-server`` to operate a transform application server to serve
+transform requests for transforms belonging to the :py:mod:`sploitego` transform package::
+
+    $ canari run-server sploitego --disable-ssl
+    You must run this server as root to continue...
+    Loading transform packages...
+    Loading transform package sploitego.transforms
+    WARNING: No route found for IPv6 destination :: (no default route?)
+    Loading sploitego.transforms.bcsitereview at /sploitego.transforms.bcsitereview...
+    Loading sploitego.transforms.sitereputation at /sploitego.transforms.sitereputation...
+    Starting web server on :80...
+    Really? Over regular HTTP? What a shame...
+
+
+.. note::
+
+    ``run-server`` will automatically ask for ``root`` credentials if the server is listening on ports in the reserved
+    range (0-1024) or if any of the transform modules within the specified transform package is decorated with the
+    :py:func:`@superuser` decorator and ``--enable-privileged`` is set.
+
+.. _install-package:
+
+``install-package``
+^^^^^^^^^^^^^^^^^^^
+
+The ``install-package`` command installs and configures a transform package (transforms, entities, Maltego machines) in
+the Maltego UI. It accepts the following parameters:
+
+* ``<package>`` (**required**): name of the transform package that contains transform modules (i.e. ``canari``).
+* ``-s [dir]``, ``--settings-dir=[dir]`` (**optional**): the name of the directory that contains Maltego's settings.
+
+.. note::
+
+    The Maltego settings directory is typically located in the following locations:
+
+    * **Linux**: ``~/.maltego/<version>`` (i.e. ``~/.maltego/3.2.0``)
+    * **Mac OS/X**: ``~/Library/Application\ Support/maltego/<version>`` (i.e. ``~/Library/Application\ Support/maltego/3.2.0``)
+
+* ``-w [dir]``, ``--working-dir=[dir]`` (**optional, default: current working directory**): the default working
+  directory for the Maltego transforms.
+
+The following example illustrates the use of ``canari install-package`` command to install transforms from the
+:py:mod:`sploitego` transform package::
+
+    $ canari install-package sploitego
+    Installing transform sploitego.v2.NmapReportToBanner_Amap from sploitego.transforms.amap...
+    Installing transform sploitego.v2.WebsiteToSiteCategory_BlueCoat from sploitego.transforms.bcsitereview...
+    Installing transform sploitego.v2.DomainToDNSName_Bing from sploitego.transforms.bingsubdomains...
+    Installing transform sploitego.v2.DNSNameToIPv4Address_DNS from sploitego.transforms.dnsalookup...
+    Installing transform sploitego.v2.IPv4AddressToDNSName_CacheSnoop from sploitego.transforms.dnscachesnoop...
+    Installing transform sploitego.v2.NSRecordToDNSName_CacheSnoop from sploitego.transforms.dnscachesnoop...
+    ...
+
+.. warning::
+
+    You must have initialized Maltego for the first time before attempting to install a transform package using
+    ``install-package``. Otherwise, the installation will fail.
+
+.. warning::
+
+    **DO NOT** run ``canari install-package`` as ``root`` unless you intend to run Maltego as ``root`` at all times.
+
+.. _uninstall-package:
+
+``uninstall-package``
+^^^^^^^^^^^^^^^^^^^^^
+
+The ``uninstall-package`` command uninstalls and un-configures all the local transform modules within the specified
+transform package in the Maltego UI. It accepts the following parameters:
+
+* ``<package>`` (**required**): name of the transform package that contains transform modules. (i.e. :py:mod:`sploitego`)
+* ``-s [dir]``, ``--settings-dir=[dir]`` (**optional**): the name of the directory that contains Maltego's settings
+  (i.e. ``~/.maltego/<version>`` in Linux, ``~/Library/Application\ Support/maltego/<version>`` in Mac OS X)
+
+The following example illustrates the use of ``canari uninstall-package`` to uninstall transforms from the
+:py:mod:`sploitego` transform package::
+
+    $ canari uninstall-package sploitego
+    Multiple versions of Maltego detected:
+    [0] Maltego v3.1.1
+    [1] Maltego v3.1.1CE
+    Please select which version you wish to install the transforms in [0]: 1
+    Uninstalling transform sploitego.v2.NmapReportToBanner_Amap from sploitego.transforms.amap...
+    Uninstalling transform sploitego.v2.WebsiteToSiteCategory_BlueCoat from sploitego.transforms.bcsitereview...
+    Uninstalling transform sploitego.v2.DomainToDNSName_Bing from sploitego.transforms.bingsubdomains...
+    Uninstalling transform sploitego.v2.DNSNameToIPv4Address_DNS from sploitego.transforms.dnsalookup...
+    Uninstalling transform sploitego.v2.IPv4AddressToDNSName_CacheSnoop from sploitego.transforms.dnscachesnoop...
+    Uninstalling transform sploitego.v2.NSRecordToDNSName_CacheSnoop from sploitego.transforms.dnscachesnoop...
+
+.. _shell:
+
+``shell``
+^^^^^^^^^
+
+The canari shell script offers an interactive shell for running transforms (work in progress). It accepts the following
+parameters:
+
+* ``<transform package>`` (**required**): the name of the transform package to load.
+
+The following example illustrates the use of canari shell to run transforms from the sploitego transform package::
+
+    $ canari shell sploitego
+    Welcome to Canari.
+    mtg> whatismyip('4.2.2.1')
+    `- MaltegoTransformResponseMessage:
+      `- Entities:
+        `- Entity:  {'Type': 'maltego.IPv4Address'}
+          `- Value: 10.0.1.22
+          `- Weight: 1
+          `- AdditionalFields:
+            `- Field: true {'DisplayName': 'Internal', 'Name': 'ipaddress.internal', 'MatchingRule': 'strict'}
+            `- Field: 68:a8:6d:4e:0f:72 {'DisplayName': 'Hardware Address', 'Name': 'ethernet.hwaddr', 'MatchingRule': 'strict'}
+    mtg>
+
+.. _create-package:
+
+``create-package``
+^^^^^^^^^^^^^^^^^^
+
+The ``create-package`` command generates a transform package skeleton for eager transform developers. It accepts the
+following parameters:
+
+* ``<package name>`` (**required**): the desired name of the transform package you wish to develop.
+
+The following example illustrates the use of ``canari create-package`` to create a transform package named
+:py:mod:`foobar`::
+
+    $ canari create-package foobar
+    creating skeleton in foobar
+    creating directory foobar
+    creating directory foobar/src
+    creating directory foobar/maltego
+    creating directory foobar/src/foobar
+    creating directory foobar/src/foobar/transforms
+    creating directory foobar/src/foobar/transforms/common
+    creating directory foobar/src/foobar/resources
+    creating directory foobar/src/foobar/resources/etc
+    creating directory foobar/src/foobar/resources/images
+    creating file foobar/setup.py...
+    creating file foobar/README.md...
+    creating file foobar/src/foobar/__init__.py...
+    creating file foobar/src/foobar/resources/__init__.py...
+    creating file foobar/src/foobar/resources/etc/__init__.py...
+    creating file foobar/src/foobar/resources/images/__init__.py...
+    creating file foobar/src/foobar/resources/etc/foobar.conf...
+    creating file foobar/src/foobar/transforms/__init__.py...
+    creating file foobar/src/foobar/transforms/helloworld.py...
+    creating file foobar/src/foobar/transforms/common/__init__.py...
+    creating file foobar/src/foobar/transforms/common/entities.py...
+    done!
+
+
+.. _create-transform:
+
+``create-transform``
+^^^^^^^^^^^^^^^^^^^^
+
+The ``create-transform`` command generates a transform module and automatically adds it to the ``__init__.py`` file in a
+transform package. It accepts the following parameters:
+
+* ``<transform name>`` (**required**): the desired name of the transform module to create.
+
+The following example illustrates the use of ``canari create-transform`` to create a transform module named
+:py:mod:`cooltransform`::
+
+    $ cd foobar/src/foobar/transforms/
+    $ canari create-transform cooltransform
+    creating file ./cooltransform.py...
+    updating __init__.py
+    done!
+
+.. _rename-transform:
+
+``rename-transform``
+^^^^^^^^^^^^^^^^^^^^
+
+The ``rename-transform`` command renames a transform module and automatically updates the corresponding ``__init__.py``
+file entry in a transform package. It accepts the following parameters:
+
+* ``<old transform name>`` (**required**): the name of the transform module to rename.
+* ``<new transform name>`` (**required**): the new desired name of the transform module.
+
+The following example illustrates the use of ``canari rename-transform`` to rename a transform module named
+:py:mod:`cooltransform` to :py:mod:`mytransform`::
+
+    $ cd foobar/src/foobar/transforms/
+    $ canari rename-transform cooltransform mytransform
+    renaming transform '/home/foo/foobar/src/foobar/transforms/cooltransform.py' to '/home/foo/foobar/src/foobar/transforms/mytransform.py'...
+    updating /home/foo/foobar/src/foobar/transforms/__init__.py
+    done!
+
+
+.. _delete-transform:
+
+``delete-transform``
+^^^^^^^^^^^^^^^^^^^^
+
+The ``delete-transform`` command deletes a transform module and automatically removes the corresponding ``__init__.py``
+file entry in a transform package. It accepts the following parameters:
+
+* ``<transform name>`` (**required**): the name of the transform module to delete.
+
+The following example illustrates the use of ``canari delete-transform`` to delete a transform module named
+:py:mod:`mytransform`::
+
+    $ cd foobar/src/foobar/transforms/
+    $ canari delete-transform mytransform
+    deleting transform '/home/foo/foobar/src/foobar/transforms/poop.py'...
+    updating /home/foo/foobar/src/foobar/transforms/__init__.py
+    done!
+
+
+.. _generate-entities:
+
+``generate-entities``
+^^^^^^^^^^^^^^^^^^^^^
+
+The ``generate-entities`` command generates the Python/Canari definitions of the entities contained within Maltego or a
+Maltego entity export file (``*.mtz``) and writes the result to a file. The entities within the ``maltego`` namespace
+(or builtin entities) are automatically excluded and only custom entity definitions are generated. It accepts the
+following parameters:
+
+* ``<outfile>`` (**optional**): Which file to write the output to (default: ``entities.py``).
+* ``--mtz-file <mtzfile>``, ``-m <mtzfile>`` (**optional**): A ``*.mtz`` file containing an export of Maltego entities.
+* ``--exclude-namespace <namespace>``, ``-e <namespace>`` (**optional**): Name of Maltego entity namespace to ignore.
+  Can be defined multiple times.
+* ``--namespace <namespace>``, ``-n <namespace>`` (**optional**): Name of Maltego entity namespace to generate entity
+  classes for. Can be defined multiple times.
+* ``--append``, ``-a`` (**optional**): Whether or not to append to the existing ``entities.py`` file.
+* ``--entity <entity>``, ``-E <entity>`` (**optional**): Name of Maltego entity to generate Canari python class for.
+
+If no arguments are passed, the ``generate-entities`` command will load the entity definition files from Maltego's
+setting directory and automatically generate an ``entities.py`` file in the current working directory.
+
+.. warning::
+
+    The ``generate-entities`` command will overwrite the current ``entities.py`` file if executed with no arguments in
+    the ``src/<package>/transforms/common`` directory.
+
+
+.. _mtgx2csv:
+
+``mtgx2csv``
+^^^^^^^^^^^^
+
+The ``mtgx2csv`` command generates a comma-separated report (CSV) of a Maltego-generated graph. It accepts the
+following parameters:
+
+* ``<graph>`` (**required**): the name of the Maltego graph file.
+
+The following example illustrates the use of ``canari mtgx2csv`` to create a CSV report of a Maltego graph file named
+``Graph1.mtgx``::
+
+    $ canari mtgx2csv ``Graph1.mtgx``
+    $ ls *.csv
+    Graph1.csv
+
+.. _csv2sheets:
+
+``csv2sheets``
+^^^^^^^^^^^^^^
+
+The ``csv2sheets`` command separates the CSV report file into multiple CSV files containing entities of the same type.
+It accepts the following parameters:
+
+* ``<csv report>`` (**required**): the name of the CSV report generated by ``canari mtgx2csv``
+* ``<prefix>`` (**required**): a prefix to prepend to the generated CSV files.
+
+The following example illustrates the use of ``canari csv2sheets`` to create a CSV files containing entities of the same
+type from the CSV report Graph1.csv::
+
+    $ csv2sheets Graph1.csv IRS
+    $ ls *.csv
+    Graph1.csv IRS_0.csv IRS_1.csv ...
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644 (file)
index 0000000..8c38409
--- /dev/null
@@ -0,0 +1,246 @@
+# -*- coding: utf-8 -*-
+#
+# canari documentation build configuration file, created by
+# sphinx-quickstart on Sat Aug 25 19:44:54 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../src/'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'canari'
+copyright = u'2012, Canari Project'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'canaridoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'canari.tex', u'Canari Framework Documentation',
+   u'Nadeem Douba', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'canari', u'Canari Framework Documentation',
+     [u'Nadeem Douba'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'canari', u'Canari Framework Documentation',
+   u'Nadeem Douba', 'canari', 'A slick and easy Maltego local transform framework.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/docs/development.rst b/docs/development.rst
new file mode 100644 (file)
index 0000000..07f5552
--- /dev/null
@@ -0,0 +1,433 @@
+################################
+Transform Development Quickstart
+################################
+
+Developing local and remote transforms is a cinch with :py:mod:`canari`. Whether you want to develop a whole bunch of
+transforms or just one, you'll probably want to take advantage of :py:mod:`canari`'s amazing features. So let's get
+started with a quick tutorial on how you can take advantage of :py:mod:`canari`'s powerful transform framework. The
+following sections will give you a quick-start tutorial on how to develop transforms.
+
+Creating a Transform Package
+============================
+
+We'll just go ahead and create a transform package called :py:mod:`mypackage`::
+
+    $ canari create-package mypackage
+    creating skeleton in mypackage
+    creating file setup.py...
+    creating file README.md...
+    creating file src/mypackage/transforms/common/entities.py...
+    creating file src/mypackage/transforms/helloworld.py...
+    creating file src/mypackage/__init__.py...
+    creating file src/mypackage/transforms/__init__.py...
+    creating file src/mypackage/transforms/common/__init__.py...
+    done!
+
+
+You'll notice that a simple skeleton project was generated, with a :py:mod:`helloworld` transform to get you started.
+You can test the :py:mod:`helloworld` transform module right away by running `canari debug-transform` like so::
+
+
+    $ canari debug-transform mypackage.transforms.helloworld Phil
+    %50
+    D:This was pointless!
+    %100
+    `- MaltegoTransformResponseMessage:
+      `- Entities:
+        `- Entity:  {'Type': 'test.MyTestEntity'}
+          `- Value: Hello Phil!
+          `- Weight: 1
+          `- AdditionalFields:
+            `- Field: 2 {'DisplayName': 'Field 1', 'Name': 'test.field1', 'MatchingRule': 'strict'}
+            `- Field: test {'DisplayName': 'Field N', 'Name': 'test.fieldN', 'MatchingRule': 'strict'}
+
+
+Developing a Transform
+======================
+
+Let's take a look at an abbreviated version of  ``src/mypackage/transforms/helloworld.py``, from our example above,
+to see how this transform was put together:
+
+.. code-block:: python
+
+    #!/usr/bin/env python
+
+    from canari.maltego.message import Person
+    from canari.maltego.utils import debug, progress
+    from canari.framework import configure #, superuser
+    from common.entities import MypackageEntity
+
+    # ...
+    #@superuser
+    @configure(
+        label='To MypackageEntity [Hello World]',
+        description='Returns a MyPackageEntity entity with the phrase "Hello Word!"',
+        uuids=[ 'mypackage.v2.MyPackageEntityToPhrase_HelloWorld' ],
+        inputs=[ ( 'MyPackageEntity', Person ) ],
+        debug=True
+    )
+    def dotransform(request, response):
+        # Report transform progress
+        progress(50)
+        # Send a debugging message to the Maltego UI console
+        debug('This was pointless!')
+
+        # Create MyPackageEntity entity with value set to 'Hello <request.value>!'
+        e = MypackageEntity('Hello %s!' % request.value)
+
+        # Setting field values on the entity
+        e.field1 = 2
+        e.fieldN = 'test'
+
+        # Update progress
+        progress(100)
+
+        # Add entity to response object
+        response += e
+
+        # Return response for visualization
+        return response
+
+
+    def onterminate():
+        debug('Caught signal... exiting.')
+        exit(0)
+
+
+Right away, you notice that there are a whole bunch of decorators (or annotations) and two functions
+(:py:func:`dotransform` and :py:func:`onterminate`). So what does this all mean and how does it work? Let's focus on the
+meat, shall we?
+
+The :py:func:`dotransform` function is the transform's entry point, this is where all the fun stuff happens. This
+transform isn't particularly fun, but it serves as a good example of what typically happens in a canari transform.
+:py:func:`dotransform` takes two arguments, :py:obj:`request` and :py:obj:`response`. The :py:obj:`request` object
+contains the data passed by Maltego to the local transform and is parsed and stored into the following properties:
+
+.. py:attribute:: value
+
+    A string containing the value of the input entity.
+
+.. py:attribute:: fields
+
+    A dictionary of entity field names and their respective values of the input entity.
+
+.. py:attribute:: params
+
+    A list of any additional command-line arguments to be passed to the transform.
+
+The :py:obj:`response` object is what our data mining logic will populate with entities and it is of type
+:py:class:`MaltegoTransformResponseMessage`. The :py:obj:`response` object is very neat in the sense that it can do
+magical things with data. With simple arithematic operations (``+=``, ``-=``, ``+``, ``-``), one can add/remove entities
+or Maltego UI messages. You'll probably want to use the ``+=`` or ``-=`` operators because ``-`` and ``+`` create
+a new :py:class:`MaltegoTransformResponseMessage` object and that can be costly. Let's take a look at how it works in
+the transform above:
+
+.. code-block:: python
+
+    # ...
+        e = MypackageEntity('Hello %s!' % request.value)
+    # ...
+        response += e
+    # ...
+
+
+The first line of code, creates a new :py:class:`MypackageEntity` object is created with a value
+``'Hello <request.value>!'``. The second line of code adds the newly created object, :py:data:`e`, to the
+:py:obj:`response` object. If we serialize the object into XML we'd see the following (spaced for clarity) output:
+
+.. code-block:: xml
+
+    <MaltegoMessage>
+        <MaltegoTransformResponseMessage>
+            <Entities>
+                <Entity Type="mypackage.MypackageEntity">
+                    <Value>Hello Phil!</Value>
+                        <Weight>1</Weight>
+                        <AdditionalFields>
+                            <Field DisplayName="Field 1" MatchingRule="strict" Name="mypackage.field1">2</Field>
+                            <Field DisplayName="Field N" MatchingRule="strict" Name="mypackage.fieldN">test</Field>
+                        </AdditionalFields>
+                </Entity>
+            </Entities>
+        </MaltegoTransformResponseMessage>
+    </MaltegoMessage>
+
+
+You may be wondering where those fields (``mypackage.field1`` and ``mypackage.fieldN``) came from? Simple, from here:
+
+.. code-block:: python
+
+    # ...
+        e.field1 = 2
+        e.fieldN = 'test'
+    # ...
+
+
+If your feeling eager, see :ref:`custom-entity` for more information on how those properties came to fruition.
+
+Once :py:func:`dotransform` is called, the data mining logic does it's thing and adds entities to the
+:py:obj:`response` object if necessary. Finally, the :py:obj:`response` is returned and :program:`dispatcher`
+serializes the object into XML. What about the decorators (:py:func:`@configure` and :py:func:`@superuser`)?
+Read on...
+
+
+``canari install-package`` Magic (:py:func:`@configure`)
+-----------------------------------------------------------
+
+So how does ``canari install-package`` figure out how to install and configure the transform in Maltego's UI? Simple,
+just use the :py:func:`@configure` decorator on your :py:func:`dotransform` function and ``canari install`` will take
+care of the rest. The :py:func:`@configure` decorator tells ``canari install-package`` how to install the transform
+in Maltego. It takes the following named parameters:
+
+.. py:function:: @configure(**kwargs)
+
+    :keyword str label: The name of the transform as it appears in the Maltego UI transform selection menu.
+    :keyword str description: A short description of the transform.
+    :keyword list uuids: A list of unique transform IDs, one per input type. The order of this list must match that of
+                        the inputs parameter. Make sure you account for entity type inheritance in Maltego. For example,
+                        if you choose a :py:class:`DNSName` entity type as your input type you do not need to specify it
+                        again for :py:class:`MXRecord`, :py:class:`NSRecord`, etc.
+    :keyword list inputs**: A list of tuples where the first item is the name of the transform set the transform should
+                            be part of, and the second item is the input entity type.
+    :keyword bool debug: Whether or not the debugging window should appear in Maltego's UI when running the transform.
+
+Let's take a look at the code again from the example above:
+
+.. code-block:: python
+
+    # ...
+    @configure(
+        label='To MypackageEntity [Hello World]',
+        description='Returns a MyPackageEntity entity with the phrase "Hello Word!"',
+        uuids=[ 'mypackage.v2.MyPackageEntityToPhrase_HelloWorld' ],
+        inputs=[ ( 'Mypackage', Person ) ],
+        debug=True
+    )
+    def dotransform(request, response):
+    # ...
+
+
+The example above tells ``canari install-package`` to process the transform in the following manner:
+
+#. The name of the transform in the transform selection context menu should appear as
+   ``To MypackageEntity [Hello World]`` in Maltego's UI.
+#. The short description of the transform as it appears in Maltego's UI is ``Returns a MyPackageEntity entity with the
+   phrase "Hello Word!"``.
+#. The transform ID of the transform in Maltego's UI will be ``mypackage.v2.MyPackageEntityToPhrase_HelloWorld``. and
+   will only work with an input entity type of :py:class:`Person` belonging to the ``Mypackage`` transform set.
+#. Finally, Maltego should pop a debug window on transform execution.
+
+What if we wanted this transform to work for entity types of :py:class:`Location`, as well. Simple, just add another
+``uuid`` and ``input`` tuple like so:
+
+.. code-block:: python
+
+    # ...
+    @configure(
+        label='To MypackageEntity [Hello World]',
+        description='Returns a MyPackageEntity entity with the phrase "Hello Word!"',
+        uuids=[ 'mypackage.v2.MyPackageEntityToPhrase_HelloWorld', 'mypackage.v2.MyPackageEntityToLocation_HelloWorld' ],
+        inputs=[ ( 'Mypackage', Person ), ( 'Mypackage', Location ) ],
+        debug=True
+    )
+    def dotransform(request, response):
+    # ...
+
+
+Now you have one transform configured to run on two different input entity types (:py:class:`Person` and
+:py:class:`Location`) with just a few lines of code and you can do this as many times as you like! Awesome!
+
+
+Running as Root (:py:func:`@superuser`)
+---------------------------------------
+
+At some point you may want to run your transform using a super-user account in UNIX-based environments. Maybe to run
+something cool like :program:`Metasploit` or :program:`Nmap`. You can do that simply by decorating
+:py:func:`dotransform` with :py:func:`@superuser`:
+
+.. code-block:: python
+
+    # ...
+    @superuser
+    @configure(
+    # ...
+    )
+    def dotransform(request, response):
+    # ...
+
+
+This will instruct :program:`dispatcher` to run the transform using :program:`sudo`. If :program:`dispatcher` is not
+running as ``root`` a :program:`sudo` password dialog box will appear asking the user to enter their password.
+If successful, the transform will run as root, just like that!
+
+Renaming Transforms with ``canari rename-transform``
+-------------------------------------------------------
+
+Alright, so you got a bit excited and decided to re-purpose the :py:mod:`helloworld` transform module to do something
+cool. In you're bliss you decided to change the name of the transform module to ``mycooltransform.py``. So you're all
+set to go, right? **Wrong**, you'll need to change the entry in the :py:data:`__all__` variable (i.e. ``'helloworld'``
+-> ``'mycooltransform'``) in ``src/mypackage/transforms/__init__.py``, first. Why? Because ``canari install-package``
+will only detect transforms if they are listed in the :py:data:`__all__` variable of the transform package's
+``__init__.py`` script. You can do this quite simply by running::
+
+    $ pwd
+    /home/user1/foo/src/foo/transforms
+    $ canari rename-transform helloworld mycooltransform
+    renaming transform 'helloworld' to 'mycooltransform'...
+    updating __init__.py
+    done!
+
+
+Creating and Removing Transforms
+--------------------------------
+
+So you want to create another transform but you want to be speedy like Gonzalez. You don't want to keep writing out the
+same thing for each transform. No problem, ``canari create-transform`` will give you a head start.
+``canari create-transform`` generates a bare bones transform module that you can hack up to do whatever you like.
+Just run ``canari create-transform`` in the ``src/mypackage/transforms`` directory, like so::
+
+    $ cd src/mypackage/transforms
+    $ canari create-transform mysecondcooltransform
+    creating file ./mysecondcooltransform.py...
+    updating __init__.py
+    done!
+
+
+No need to add the entry in ``__init__.py`` anymore because ``canari create-transform`` does it for you
+automagically. The same is true for ``canari delete-transform`` if you want to remove a transform from your package.
+
+
+.. _custom-entity:
+
+Creating Custom Entities
+========================
+
+Now you want to get a custom entity in. No problem! We've got that covered too. With just a few lines of code you can
+create as many entities as you wish. The only gotcha in this process is that you'll probably want to iconify these
+entities so they look good in Maltego. That's a manual process we can't get away from. On the other hand, defining
+custom entities in your code is quite simple. Take a look inside your custom package's
+``src/mypackage/transforms/common/entities.py`` file. It should look similar to this:
+
+.. code-block:: python
+
+    #!/usr/bin/env python
+
+    from canari.maltego.message import Entity, EntityField, EntityFieldType, MatchingRule
+
+    # ...
+
+    """
+    DO NOT EDIT
+    ...
+    """
+    class FooEntity(Entity):
+        namespace = 'foo'
+
+
+    """
+    TODO
+    ...
+    """
+    @EntityField(name='foo.fieldN', propname='fieldN', displayname='Field N', matchingrule=MatchingRule.Loose)
+    @EntityField(name='foo.field1', propname='field1', displayname='Field 1', type=EntityFieldType.Integer)
+    class MyFooEntity(FooEntity):
+        # ...
+        # name = my.fancy.EntityType
+        pass
+
+You may be asking yourself "That's it?" or maybe even scratching your head about what this all means. Don't worry, we'll
+go through this line-by-line. The first class, :py:class:`FooEntity` is the base entity class for all your custom
+entities. You won't want to edit this much since all it provides is a custom namespace for your entities. What is a
+namespace? If you've designed a custom entity in Maltego you probably noticed that the entity gets a suggested ID of
+``<username>.<EntityName>``. In this case the namespace is the ``<username>`` portion of the entity's ID. This is done
+to avoid conflicts between different entity definitions from various transform developers. Maltego's built-in entities
+have a namespace of ``maltego``. In our case, the namespace for all of our entities will be ``foo``.
+
+What about the other entity, :py:class:`MyFooEntity`? That's just an example entity definition that you can modify to
+your heart's content. Notice the :py:func:`@EntityField` decorators. Those define the structure of the entity in terms
+of what entity fields exist, their data-types, icon decorators, and various other elements that affect how Maltego
+compares two different entities of the same type. In addition, these decorators synthesize class fields identified by
+the ``propname`` keyword argument. Modifying their values is as easy as ``myfooentity.mypropname``.
+
+You can specify as many entity fields as you want by just adding an extra :py:func:`@EntityField` decorator to your
+entities. The :py:func:`@EntityField` decorator takes the following parameters:
+
+.. py:function:: @EntityField(**kwargs)
+
+    :keyword str name: the name of the field without spaces or special characters except for dots ('.') (required).
+    :keyword str propname: the name of the object's property used to get and set the value of the field
+                           (required, if name contains dots)
+    :keyword str displayname: the name of the entity as it appears in Maltego (optional).
+    :keyword str type: the data type of the field (optional, default: EntityFieldType.String).
+    :keyword bool required: whether or not the field's value must be set before sending back the message (optional,
+                            default: False).
+    :keyword list choices: a list of acceptable field values for this field (optional).
+    :keyword str matchingrule: whether or not the field should be loosely or strictly matched by Maltego's graphing
+                               engine (optional, default: MatchingRule.Strict).
+    :keyword callable decorator: a function that is invoked each and every time the field's value is set or changed.
+
+
+Matching Rules
+--------------
+
+Maltego currently supports two types of matching rules for entities: ``strict`` and ``loose``. These rules apply to an
+entity's fields and determine how Maltego graph two entities of the same type and value but with differing entity field
+values on a graph. For example, let's assume you've performed a transform that produced two ``IPv4Address`` entities on
+a graph with the same entity value of ``127.0.0.1``. Each ``IPv4Address`` entity has an ``internal`` boolean field
+which indicates whether or not the ``IPv4Address`` entity represents an internal IP address. Let's assume that the
+``internal`` fields are different, one is set to ``true`` and the other to ``false``. In the case where the ``internal``
+field is ``loose``'ly matched, both entities would appear as one entity on the graph. Otherwise, if the ``internal``
+field is ``strict``'ly matched, then both these entities would appear as two separate entities on the graph. If you're a
+fan of a visual example, try the following example transform out to see what the end results are:
+
+.. code-block:: python
+
+    #!/usr/bin/env python
+
+    from canari.maltego.message import Entity, MatchingRule
+    from canari.maltego.message import Phrase, Field
+    from canari.framework import configure
+
+
+    class TestEntity(Entity):
+        namespace='test'
+
+    class MyIPv4Address(TestEntity):
+        pass
+
+
+    @configure(
+        label='To IPv4Address [Matching Rules]',
+        description='Shows how matching rules work in Maltego.',
+        uuids=[ 'tests.v2.PhraseToIPv4Address_Matching_Rules' ],
+        inputs=[ ( 'Testing Matching Rules', Phrase ) ],
+        debug=True
+    )
+    def dotransform(request, response):
+
+        # What kind of matching rule are we using?
+        mr = MatchingRule.Strict
+        if request.value.lower() == 'loose':
+            mr = MatchingRule.Loose
+
+        # First IP
+        ip1 = MyIPv4Address('127.0.0.1')
+        ip1 += Field('internal', 'true', matchingrule=mr)
+        response += ip1
+
+        # Second IP
+        ip2 = MyIPv4Address('127.0.0.1')
+        ip2 += Field('internal', 'false', matchingrule=mr)
+        response += ip2
+
+        # Return response for visualization
+        return response
+
+
+The example transform runs on ``Phrase`` entities and determines its matching rule based on the ``Phrase`` entity's
+value. If it is anything other than ``loose``, the entity field ``internal`` will be ``strict``'ly matched.
+
+Entity Field Decorators
+-----------------------
+
+Say you want to provide users of your transforms with better visuals for your transform outputs. For example,
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644 (file)
index 0000000..98d42c8
--- /dev/null
@@ -0,0 +1,21 @@
+Canari Framework
+================
+
+Contents:
+
+.. toctree::
+    :maxdepth: 2
+    :numbered:
+
+    intro
+    canari
+    development
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/docs/intro.rst b/docs/intro.rst
new file mode 100644 (file)
index 0000000..d1ac540
--- /dev/null
@@ -0,0 +1,134 @@
+
+Introduction
+============
+
+Welcome to the official documentation for the `Canari Framework <http://canariproject.com>`_. The
+`Canari Framework <http://canariproject.com>`_ is a rapid transform development framework that can be used to develop
+**local and remote** transforms for `Maltego <http://paterva.com>`_ . Designed on the principles of convention over
+configuration, developing transforms using Canari is extremely fast and easy. Canari takes care of XML serialization and
+deserialization, argument or parameter parsing, as well as transform configuration and execution. Not only is Canari
+great for Maltego transform development but it is also extremely easy to test, debug, and distribute your transforms.
+Canari provides a powerful transform package specification that makes local transform distribution a cinch. Installing a
+set of Maltego transforms, entities, and Maltego Scripts (or Machines) is as easy as typing one line in your terminal.
+Even if you're not a Python developer, Canari has support for easily distributing transforms written in different
+languages (i.e. PERL, Java, Ruby, etc.). The following subsections will provide an in-depth look of Canari's features,
+libraries, and transform package specification.
+
+
+Terminology
+-----------
+
+Before we get started with the documentation, it might be useful to introduce some of the terminology that will be used
+throughout the documentation:
+
++-----------------------+----------------------------------------------------------------------------------------------+
+| Term                  | Definition                                                                                   |
++=======================+==============================================================================================+
+| **Entity**            | a piece of information on a Maltego graph represented as a node.                             |
++-----------------------+----------------------------------------------------------------------------------------------+
+| **Input Entity**      | the entity that is being passed into the transform to use for data mining purposes.          |
++-----------------------+----------------------------------------------------------------------------------------------+
+| **Output Entity**     | the entity that is being returned by the transform to be drawn on a Maltego graph.           |
++-----------------------+----------------------------------------------------------------------------------------------+
+| **Transform**         | a function that takes one *input entity* as input and returns zero or more *output entities*.|
++-----------------------+----------------------------------------------------------------------------------------------+
+| **Transform Module**  | a python module local transform code.                                                        |
++-----------------------+----------------------------------------------------------------------------------------------+
+| **Transform Package** | a python package containing one or more transform modules, entities, and Maltego machines.   |
++-----------------------+----------------------------------------------------------------------------------------------+
+
+
+Installing Canari
+-----------------
+
+Canari is officially supported on Python versions 2.6 and 2.7 with `setuptools <http://pypi.python.org/pypi/setuptools>`_
+on Linux and Mac OS/X. Canari has not yet been tested on Windows but should be able to operate in this environment as
+well. To install setuptools in your Python distribution, simply go to `<http://pypi.python.org/pypi/setuptools>`_ and
+download the corresponding Python egg distribution for your operating system and follow the instructions for
+installation. Once setuptools is installed, type the following command in your terminal::
+
+    $ sudo easy_install canari
+
+This will install of Canari's dependencies (argparse and pexpect) as well as Canari's transform development tool-suite.
+If successful, you should be able to run Canari's commander by typing ``canari list-commands`` at the command-prompt::
+
+    $ canari list-commands
+    create-package - Creates a Canari transform package skeleton.
+    create-transform - Creates a new transform in the specified directory and auto-updates __init__.py.
+    csv2sheets - Convert mixed entity type CSVs to separated CSV sheets.
+    debug-transform - Runs Canari local transforms in a terminal-friendly fashion.
+    delete-transform - Deletes a transform in the specified directory and auto-updates __init__.py.
+    generate-entities - Converts Maltego entity definition files to Canari python classes. Excludes Maltego built-in entities.
+    install-package - Installs and configures canari transform packages in Maltego's UI
+    list-commands - Lists all the available canari commands
+    mtgx2csv - Convert Maltego graph files (*.mtgx) to comma-separated values (CSV) file.
+    rename-transform - Renames a transform in the specified directory and auto-updates __init__.py.
+    run-server - Runs a transform server for the given packages.
+    run-transform - Runs Canari local transforms in a terminal-friendly fashion.
+    shell - Creates a Canari debug shell for the specified transform package.
+    uninstall-package - Uninstalls and unconfigures canari transform packages in Maltego's UI
+
+If you were unable to run the Canari commander then please refer to :ref:`ref_troubleshoot` for information. Otherwise,
+let's dive right into the :ref:`ref_canari_commander`.
+
+.. _ref_troubleshoot:
+
+Trouble-shooting Canari Installations
+-------------------------------------
+
+In some odd cases, the ``canari`` commander is inaccessible due to erroneous permission or system path definitions. To
+troubleshoot this issue ensure the following two conditions are true:
+
+* The path where ``canari`` is installed (i.e. ``/usr/local/bin``) has read and execute permissions for everyone.
+* The system's ``PATH`` environment variable includes the path where ``canari`` has been installed.
+
+The following subsections provide some pointers for trouble-shooting Canari installations on specific operating systems.
+
+
+Linux and Mac OS/X
+^^^^^^^^^^^^^^^^^^
+
+To determine the location of your ``canari`` script, check the output of ``easy_install``::
+
+    $ sudo easy_install canari
+    ...
+    Installing canari script to /usr/local/bin
+    Installing dispatcher script to /usr/local/bin
+    Installing pysudo script to /usr/local/bin
+    ...
+
+Once you've determined the location of the ``canari`` script (e.g. ``/usr/local/bin``), ensure that it is in
+your system's ``PATH`` environment variable::
+
+    $ echo $PATH
+    /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
+
+If the ``canari`` script's path is not included in your system's ``PATH`` environment variable, then check your
+operating system's documentation on how to modify your ``PATH`` environment variable. Otherwise, if the path is in your
+system's ``PATH`` environment variable and you are still unable to run ``canari`` then you'll want to ensure that the
+``canari`` script's parent directory is accessible by everyone::
+
+    $ ls -l /usr/local
+    total 0
+    drwxr-xr-x  58 root  wheel  1972  7 Jan 23:42 bin
+    ...
+
+
+Ensure that ``canari``'s parent directory (e.g. ``/usr/local/bin``) has ``755`` permissions. If not, use the following
+command to correct the directory's permissions::
+
+    $ sudo chmod 755 /usr/local/bin
+
+If none of these steps have helped correct this issue please feel free to send an email to `<bugs@canariproject.com>`_
+for additional help with the following details:
+
+    * Operating system name and version.
+    * Canari version.
+    * ``easy_install`` output.
+
+Windows
+^^^^^^^
+
+.. note::
+
+    Canari has not been tested on Windows yet.
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644 (file)
index 0000000..a0d6660
--- /dev/null
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+       set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+       set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+       set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+       :help
+       echo.Please use `make ^<target^>` where ^<target^> is one of
+       echo.  html       to make standalone HTML files
+       echo.  dirhtml    to make HTML files named index.html in directories
+       echo.  singlehtml to make a single large HTML file
+       echo.  pickle     to make pickle files
+       echo.  json       to make JSON files
+       echo.  htmlhelp   to make HTML files and a HTML help project
+       echo.  qthelp     to make HTML files and a qthelp project
+       echo.  devhelp    to make HTML files and a Devhelp project
+       echo.  epub       to make an epub
+       echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+       echo.  text       to make text files
+       echo.  man        to make manual pages
+       echo.  texinfo    to make Texinfo files
+       echo.  gettext    to make PO message catalogs
+       echo.  changes    to make an overview over all changed/added/deprecated items
+       echo.  linkcheck  to check all external links for integrity
+       echo.  doctest    to run all doctests embedded in the documentation if enabled
+       goto end
+)
+
+if "%1" == "clean" (
+       for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+       del /q /s %BUILDDIR%\*
+       goto end
+)
+
+if "%1" == "html" (
+       %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+       goto end
+)
+
+if "%1" == "dirhtml" (
+       %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+       goto end
+)
+
+if "%1" == "singlehtml" (
+       %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+       goto end
+)
+
+if "%1" == "pickle" (
+       %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished; now you can process the pickle files.
+       goto end
+)
+
+if "%1" == "json" (
+       %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished; now you can process the JSON files.
+       goto end
+)
+
+if "%1" == "htmlhelp" (
+       %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+       goto end
+)
+
+if "%1" == "qthelp" (
+       %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+       echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sploitego.qhcp
+       echo.To view the help file:
+       echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sploitego.ghc
+       goto end
+)
+
+if "%1" == "devhelp" (
+       %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished.
+       goto end
+)
+
+if "%1" == "epub" (
+       %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The epub file is in %BUILDDIR%/epub.
+       goto end
+)
+
+if "%1" == "latex" (
+       %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+       goto end
+)
+
+if "%1" == "text" (
+       %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The text files are in %BUILDDIR%/text.
+       goto end
+)
+
+if "%1" == "man" (
+       %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The manual pages are in %BUILDDIR%/man.
+       goto end
+)
+
+if "%1" == "texinfo" (
+       %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+       goto end
+)
+
+if "%1" == "gettext" (
+       %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+       goto end
+)
+
+if "%1" == "changes" (
+       %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.The overview file is in %BUILDDIR%/changes.
+       goto end
+)
+
+if "%1" == "linkcheck" (
+       %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+       goto end
+)
+
+if "%1" == "doctest" (
+       %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+       if errorlevel 1 exit /b 1
+       echo.
+       echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+       goto end
+)
+
+:end
index 6e74b3f0ba16a2d4a02fa40c8e71f308f6bd32dd..4d89ae729c80eba6d21182a317226f70ce0f9896 100644 (file)
@@ -2,7 +2,7 @@
 
 from canari.config import CanariConfigParser
 
-from os import path, listdir, sep, environ, mkdir, pathsep, getcwd
+from os import path, listdir, sep, environ, mkdir, pathsep, getcwd, walk
 from pkg_resources import resource_filename
 from distutils.dist import Distribution
 from distutils.command.install import install
@@ -91,7 +91,7 @@ def write_template(fname, data):
 
 
 def generate_all(*args):
-    return "\n__all__ = [\n    '%s'\n]" % "',\n    '".join(args)
+    return "\n\n__all__ = [\n    '%s'\n]" % "',\n    '".join(args)
 
 
 def build_skeleton(*args):
@@ -172,9 +172,10 @@ def console_message(msg, tab=-1):
 
 def init_pkg():
 
-    conf = '.canari'
+    root = project_root()
 
-    for i in range(0, 5):
+    if root is not None:
+        conf = path.join(root, '.canari')
         if path.exists(conf):
             c = CanariConfigParser()
             c.read(conf)
@@ -183,10 +184,8 @@ def init_pkg():
                 'email' : c['metadata/email'],
                 'maintainer' : c['metadata/maintainer'],
                 'project' : c['metadata/project'],
-                'year' : datetime.now().year,
-                'dir' : getcwd()
+                'year' : datetime.now().year
             }
-        conf = '..%s%s' % (sep, conf)
 
     return {
         'author' : '',
@@ -197,4 +196,49 @@ def init_pkg():
     }
 
 
+def project_root():
+
+    marker = '.canari'
+
+    for i in range(0, 5):
+        if path.exists(marker):
+            return path.dirname(path.realpath(marker))
+        marker = '..%s%s' % (sep, marker)
+
+    print 'Unable to determine project root.'
+    exit(-1)
+
+
+def project_tree():
+
+    root = project_root()
+
+    tree = dict(
+        root=root,
+        src=None,
+        pkg=None,
+        resources=None,
+        transforms=None
+    )
+
+    for base, dirs, files in walk(root):
+        if base.endswith('src'):
+            tree['src'] = base
+        elif 'resources' in dirs:
+            tree['pkg'] = base
+        elif base.endswith('resources'):
+            tree['resources'] = base
+        elif base.endswith('transforms'):
+            tree['transforms'] = base
+
+    return tree
+
+
+def parse_bool(ans, default='y'):
 
+    while True:
+        ans = raw_input(ans).lower() or default
+        if ans.startswith('y'):
+            return True
+        elif ans.startswith('n'):
+            return False
\ No newline at end of file
index d6b11e6ec6b5926e6a033a8ccfe544c7c1da408a..2bcb2eda102abcca9783552ad035548f793fe916 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-from common import read_template, write_template, generate_all, build_skeleton, cmd_name
+from common import read_template, write_template, generate_all, build_skeleton, cmd_name, parse_bool
 
 from argparse import ArgumentParser
 from datetime import datetime
@@ -114,16 +114,6 @@ def description():
     return parser.description
 
 
-def parse_bool(ans, default='y'):
-
-    while True:
-        ans = raw_input(ans).lower() or default
-        if ans.startswith('y'):
-            return True
-        elif ans.startswith('n'):
-            return False
-
-
 def ask_user(defaults):
 
     print('Welcome to the Canari transform package wizard.')
index c9a35d550383f73da3daa6b3ce2d81f8b43a941d..9e2c39eaf7ea005b851bb40b7b6711943043509a 100644 (file)
@@ -1,10 +1,9 @@
 #!/usr/bin/env python
 
-from common import write_template, read_template, cmd_name, init_pkg
-
+from common import write_template, read_template, cmd_name, init_pkg, project_tree
 
 from argparse import ArgumentParser
-from os import path, getcwd
+from os import path
 from re import sub
 
 
@@ -35,7 +34,7 @@ parser.add_argument(
     '--transform-dir',
     metavar='<dir>',
     help='The directory in which you wish to create the transform.',
-    default=getcwd()
+    default=None
 )
 
 
@@ -49,6 +48,8 @@ def description():
 
 def parse_args(args):
     args = parser.parse_args(args)
+    if args.transform_dir is None:
+        args.transform_dir= project_tree()['transforms']
     return args
 
 
index ae0f01734f2f6f0e74a2f2de6b4901456be7ef4d..f2ea3e7fb4c80e095f6ff5c0383d148fb257db2f 100644 (file)
@@ -30,7 +30,7 @@ parser = ArgumentParser(
 parser.add_argument(
     'transform',
     metavar='<transform>',
-    help='The name of the transform you wish to run (e.g. canari.transforms.nmapfastscan).'
+    help='The name of the transform you wish to run (e.g. sploitego.transforms.nmapfastscan).'
 )
 
 parser.add_argument(
index 6bed2645a000d6a413731b0424b1761a3afecb93..acbf80605565f7c273c3037182fc90fd5c508716 100644 (file)
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 
-from common import cmd_name
+from common import cmd_name, project_tree
 
-from os import path, getcwd, unlink
 from argparse import ArgumentParser
+from os import path, unlink
 from re import sub
 
 
@@ -34,7 +34,7 @@ parser.add_argument(
     '--transform-dir',
     metavar='<dir>',
     help='The directory from which you wish to delete the transform.',
-    default=getcwd()
+    default=None
 )
 
 
@@ -48,6 +48,8 @@ def description():
 
 def parse_args(args):
     args = parser.parse_args(args)
+    if args.transform_dir is None:
+        args.transform_dir = project_tree()['transforms']
     return args
 
 
index 3a8e2a8ce5fe99f9e5ca2f6eb26654ab1dd7de3d..3d5981206020e2113e0a152b35bd693c46a355e0 100644 (file)
@@ -1,11 +1,11 @@
 #!/usr/bin/env python
 
-from common import detect_settings_dir, cmd_name
+from common import detect_settings_dir, cmd_name, project_tree, parse_bool
 from canari.maltego.entities import Entity
 
 from xml.etree.cElementTree import XML
 from argparse import ArgumentParser
-from os import walk, path as ospath
+from os import walk, path
 from zipfile import ZipFile
 from imp import load_source
 from re import sub
@@ -36,15 +36,15 @@ __status__ = 'Development'
 
 parser = ArgumentParser(
     description='Converts Maltego entity definition files to Canari python classes. Excludes Maltego built-in entities.',
-    usage='canari %s <outfile> [options]' % cmd_name(__name__)
+    usage='canari %s [output file] [options]' % cmd_name(__name__)
 )
 
 
 parser.add_argument(
     'outfile',
-    metavar='<outfile>',
+    metavar='[output file]',
     help='Which file to write the output to.',
-    default='entities.py',
+    default=None,
     nargs='?'
 )
 
@@ -104,7 +104,10 @@ def description():
 
 
 def parse_args(args):
-    return parser.parse_args(args)
+    args = parser.parse_args(args)
+    if args.outfile is None:
+        args.outfile = path.join(project_tree()['transforms'], 'common', 'entities.py')
+    return args
 
 
 def normalize_fn(fn):
@@ -133,7 +136,7 @@ class DirFile(object):
     def namelist(self):
         l = []
         for base, dirs, files in walk(self.path):
-            l.extend([ ospath.join(base, f) for f in files ])
+            l.extend([ path.join(base, f) for f in files ])
         return l
 
     def open(self, fname):
@@ -144,8 +147,13 @@ def run(args):
 
     opts = parse_args(args)
 
+    if path.exists(opts.outfile) and not opts.append and not \
+       parse_bool('%s already exists. Are you sure you want to overwrite it? [y/N]: ' % repr(opts.outfile), default='n'):
+        exit(-1)
+
+
     ar = DirFile(
-        ospath.join(detect_settings_dir(), 'config', 'Maltego', 'Entities')
+        path.join(detect_settings_dir(), 'config', 'Maltego', 'Entities')
     ) if opts.mtz_file is None else ZipFile(opts.mtz_file)
 
     entities = filter(lambda x: x.endswith('.entity'), ar.namelist())
@@ -160,6 +168,7 @@ def run(args):
             if i.type.endswith('Entity'):
                 nses[i.namespace] = i.__class__.__name__
 
+    print 'Generating %s...' % repr(opts.outfile)
     fd = open(opts.outfile, 'ab' if opts.append else 'wb')
 
     if opts.append:
@@ -204,4 +213,5 @@ def run(args):
 
         fd.write('class %s(%s):\n    pass\n\n\n' % (classname, base_classname))
 
-    fd.close()
\ No newline at end of file
+    fd.close()
+    print 'done.'
\ No newline at end of file
index 416b2324908f9dc8eb3ff41c706fc7d1d0200353..39b93a94fca6202098b84a2d1626b6aca05b0391 100644 (file)
@@ -23,6 +23,7 @@ parser = ArgumentParser(
     description='Shows help related to various canari commands',
     usage='canari %s <command>' % cmd_name(__name__)
 )
+
 parser.add_argument(
     'command',
     metavar='<command>',
index cd3edacd9a8cb75c8a31117b3d12d2e93a7ddf7c..b78dc495fd5980fab5cae546d3274272ffea0f58 100644 (file)
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 
-from common import cmd_name
+from common import cmd_name, project_tree
 
-from os import path, getcwd, rename
 from argparse import ArgumentParser
+from os import path, rename
 from re import sub
 
 
@@ -40,7 +40,7 @@ parser.add_argument(
     '--transform-dir',
     metavar='<dir>',
     help='The directory from which you wish to rename the transform.',
-    default=getcwd()
+    default=None
 )
 
 
@@ -54,6 +54,8 @@ def description():
 
 def parse_args(args):
     args = parser.parse_args(args)
+    if args.transform_dir is None:
+        args.transform_dir = project_tree()['transforms']
     return args
 
 
index 49aff4aa55d1c31ebc5c94a9b85fa87094a67395..13e6cceba4e0f4d0e2f261889ab27f2c3ad82c13 100755 (executable)
@@ -82,7 +82,7 @@ parser.add_argument(
 parser.add_argument(
     '--hostname',
     metavar='[hostname]',
-    default=getfqdn(),
+    default=None,
     help='The hostname of this transform server.'
 )
 
@@ -276,10 +276,16 @@ class AsyncMaltegoHTTPServer(ThreadingMixIn, MaltegoHTTPServer):
     pass
 
 
+def parse_args(args):
+    args = parser.parse_args(args)
+    if args.hostname is None:
+        args.hostname = getfqdn()
+    return args
+
 
 def run(args):
 
-    opts = parser.parse_args(args)
+    opts = parse_args(args)
 
     fix_pypath()
 
index 0aefa78f887b83cb18d13767497c6f4ce56b5397..3e1c83b4af10650dcb82a1ba010f888b92a6860a 100644 (file)
@@ -30,7 +30,7 @@ parser = ArgumentParser(
 parser.add_argument(
     'transform',
     metavar='<transform>',
-    help='The name of the transform you wish to run (e.g. canari.transforms.nmapfastscan).'
+    help='The name of the transform you wish to run (e.g. sploitego.transforms.nmapfastscan).'
 )
 
 parser.add_argument(