# $Id: HACKING 11885 2011-03-06 06:49:00Z scriptjunkie $

This file contains some brief instructions on contributing to the
Metasploit Framework.


Code Style
==========

In order to maintain consistency and readability, we ask that you
adhere to the following style guidelines:

 - Hard tabs, not spaces
 - Try to keep your lines under 100 columns (assuming four-space tabs)
 - do; end instead of {} for a block
 - Always use str[0,1] instead of str[0]
   (This avoids a known ruby 1.8/1.9 incompatability.)

You can use the the "./tools/msftidy.rb" script to do some rudimentary
checking for various violations.


Code No-Nos
===========

1. Don't print to standard output.  Doing so means that users of
interfaces other than msfconsole, such as msfrpc and msfgui, won't see
your output.  You can use print_line to accomplish the same thing as
puts. 

2. Don't use "sleep". It has been known to cause issues with
multi-threaded programs on various platforms. Instead, we use
"select(nil, nil, nil, <time>)" throughout the framework. We have
found this works around the underlying issue.

3. Always use Rex sockets, not ruby sockets.  This includes
third-party libraries such as Net::Http.  There are several very good
reasons for this rule.  First, the framework doesn't get notified on
the creation of ruby sockets and won't know how to clean them up in
case your module raises an exception without cleaning up after itself.
Secondly, non-Rex sockets do not know about routes and therefore can't
be used through a meterpreter tunnel.  Lastly, regular sockets miss
out on msf's proxy and ssl features.  Msf includes many protocols
already implemented with Rex and if the protocol you need is missing,
porting another library to use them is straight-forward.  See our
Net::SSH modifications in lib/net/ssh/ for an example.

4. When opening an IO stream, always force binary with "b" mode (or
using IO#binmode). This not only helps keep Windows and non-Windows
runtime environments consistent with each other, but also guarantees
that files will be treated as ASCII-8BIT instead of UTF-8.

5. Don't use String#[] for a single character.  This returns a Fixnum in
ruby 1.8 and a String in 1.9, so it's safer to use the following idiom:
	str[idx,1]
which always returns a String.  If you need the ASCII byte, unpack it like
so: 
	str[idx,1].unpack("C")

6. Whenever possible, avoid using '+' or '+=' to concatenate strings.
The '<<' operator is significantly faster. The difference will become
even more apparent when doing string manipulation in a loop. The
following table approximates the underlying implementation:
	Ruby 		Pseudo-C
	----------- 	----------------
	a = b + c 	a = malloc(b.len+c.len+1);
			strcpy(a, b);
			memcpy(a+b.len, c, c.len);
			a[b.len + c.len] = '\0';
	a = b 		a = b;
	a << c 		a = realloc(a, a.len+c.len+1);
			memcpy(a+a.len, c, c.len);
			a[a.len + c.len] = '\0';
Note that the original value of 'b' is lost in the second case. Care
must be taken to duplicate strings that you do not want to modify.

7. For other Ruby 1.8.x/1.9.x compat issues, please see Sam Ruby's
excellent slide show at <http://slideshow.rubyforge.org/ruby19.html>
for an overview of common and not-so-common Ruby version related gotchas.

Creating New Modules
====================

When creating a new module, the simplest way to start is to copy
another module that uses the same protocol and modify it to your
needs.  If you're creating an exploit module, generally you'll want
to edit the exploit() method.  Auxiliary Scanner modules use one of
run_host(), run_range(), or run_batch() instead of exploit().
Non-scanner aux modules use run().


Submitting Your Code
====================

When you've finished fixing a bug, adding a feature, or creating a
new module, build a patch by using the following command from the
base installation directory: 
    svn diff > something-descriptive.patch
Make sure you add any new files with 'svn add filename' first.  If
you have just a single new file (such as when creating a new module)
feel free to just send that file.  Once you've created the patch,
there are a couple ways to submit it.  The first is to add it as an
attachment to a ticket in our Redmine tracker
(https://www.metasploit.com/redmine/projects/framework); you can
create a ticket if one does not exist.  Secondly, you can email it
framework@metasploit.com, which is the main mailinglist for
framework users, or msfdev@metasploit.com which only goes to
developers.


Licensing
=========
By submitting code contributions to the Metasploit Project it is
assumed that you are offering your code under a BSD or similar
license.  MIT and Ruby Licenses are also fine.  We specifically cannot
include GPL code. 

When possible, such as aux and exploit modules, be sure to include
your license designation in the file in the appropriate place.

