'''
textFile.py

Copyright 2006 Andres Riancho

This file is part of w3af, w3af.sourceforge.net .

w3af is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

w3af is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with w3af; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

'''

from core.controllers.basePlugin.baseOutputPlugin import baseOutputPlugin
from core.controllers.w3afException import w3afException
import sys, os
import time

class textFile(baseOutputPlugin):
	'''
	This plugin prints all messages to a text file.
	@author: Andres Riancho ( andres.riancho@gmail.com )
	'''
	
	def __init__(self):
		baseOutputPlugin.__init__(self)
		self._filename = 'output.txt'
		self._httpFilename = 'output-http.txt'
		self._flushCounter = 0
		self._flushNumber = 10
		self._initialized = False
		self._file = None
	
	def _init( self ):
		self._initialized = True
		try:
			self._file = open( self._filename, "w" )
		except:
			raise w3afException('Cant open file ' + self._filename + ' for output.')
			self._error = True
			
		try:
			self._http = open( self._httpFilename, "w" )
		except:
			raise w3afException('Cant open file ' + self._httpFilename + ' for output.')
			self._error = True
		
	def __del__(self):
		if self._file != None:
			self._file.close()

	def debug(self, message, newLine = True ):
		'''
		This method is called from the output object. The output object was called from a plugin
		or from the framework. This method should take an action for debug messages.
		'''
		if not self._initialized:
			self._init()
			
		if self.verbosity > 5:
			toPrint = str ( message )
			if newLine == True:
				toPrint += '\n'
			
			now = time.localtime(time.time())
			theTime = time.strftime("%c", now)
			
			self._file.write( '[ ' + theTime + ' - debug ] ' + toPrint )
			self._flush()

	
	def information(self, message , newLine = True ):
		'''
		This method is called from the output object. The output object was called from a plugin
		or from the framework. This method should take an action for informational messages.
		'''
		if not self._initialized:
			self._init()
			
		toPrint = str ( message )
		if newLine == True:
			toPrint += '\n'
		
		now = time.localtime(time.time())
		theTime = time.strftime("%c", now)
		
		self._file.write( '[ ' + theTime + ' - information ] ' + toPrint )

		self._flush()


	def error(self, message , newLine = True ):
		'''
		This method is called from the output object. The output object was called from a plugin
		or from the framework. This method should take an action for error messages.
		'''		
		if not self._initialized:
			self._init()
		
		toPrint = str ( message )
		if newLine == True:
			toPrint += '\n'
		
		now = time.localtime(time.time())
		theTime = time.strftime("%c", now)
		
		self._file.write( '[ ' + theTime + ' - error ] ' + toPrint )

		self._flush()

	def vulnerability(self, message , newLine = True ):
		'''
		This method is called from the output object. The output object was called from a plugin
		or from the framework. This method should take an action when a vulnerability is found.
		'''		
		if not self._initialized:
			self._init()
		
		toPrint = str ( message )
		if newLine == True:
			toPrint += '\n'
		now = time.localtime(time.time())
		theTime = time.strftime("%c", now)
		
		self._file.write( '[ ' + theTime + ' - vulnerability ] ' + toPrint )

		self._flush()
		
	def console( self, message, newLine = True ):
		'''
		This method is used by the w3af console to print messages to the outside.
		'''
		if not self._initialized:
			self._init()
		toPrint = str ( message )
		if newLine == True:
			toPrint += '\n'
		now = time.localtime(time.time())
		theTime = time.strftime("%c", now)
		
		self._file.write( '[ ' + theTime + ' - console ] ' + toPrint )
		self._flush()
		
	def _flush(self):
		'''
		textfile.flush is called every time a message is sent to this plugin.
		self._file.flush() is called every self._flushNumber
		'''
		if self._flushCounter % self._flushNumber == 0:
			self._file.flush()
			
	def setOptions( self, OptionList ):
		'''
		Sets the Options given on the OptionList to self. The options are the result of a user
		entering some data on a window that was constructed using the XML Options that was
		retrieved from the plugin using getOptionsXML()
		
		This method MUST be implemented on every plugin. 
		
		@return: No value is returned.
		'''	
		if 'verbosity' in OptionList.keys():
			self.verbosity = OptionList['verbosity']
			
		if 'fileName' in OptionList.keys():
			self._filename = OptionList['fileName']

		if 'httpFileName' in OptionList.keys():
			self._httpFilename = OptionList['httpFileName']
		
	def getOptionsXML(self):
		'''
		This method returns a XML containing the Options that the plugin has.
		Using this XML the framework will build a window, a menu, or some other input method to retrieve
		the info from the user. The XML has to validate against the xml schema file located at :
		w3af/core/display.xsd
		
		This method MUST be implemented on every plugin. 
		
		@return: XML String
		@see: core/display.xsd
		'''
		return	'<?xml version="1.0" encoding="ISO-8859-1"?>\
		<OptionList>\
			<Option name="verbosity">\
				<default>'+str(self.verbosity)+'</default>\
				<desc>Verbosity level for this plugin.</desc>\
				<type>integer</type>\
			</Option>\
			<Option name="fileName">\
				<default>'+str(self._filename)+'</default>\
				<desc>File name where this plugin will write to</desc>\
				<type>string</type>\
			</Option>\
			<Option name="httpFileName">\
				<default>'+str(self._httpFilename)+'</default>\
				<desc>File name where this plugin will write HTTP requests and responses</desc>\
				<type>string</type>\
			</Option>\
		</OptionList>\
		'

	def logHttp( self, request, response):
		'''
		log the http req / res to file.
		@parameter request: A fuzzable request object
		@parameter response: A httpResponse object
		'''
		now = time.localtime(time.time())
		theTime = time.strftime("%c", now)
		
		msg = '='*40  + 'Request ' + str(response.id) + ' - '+ theTime+'='*40 + '\n'
		self._http.write(  msg )
		self._http.write( request.dump() )
		msg2 = '\n' + '='*40  + 'Response ' + str(response.id) + ' - '+ theTime+'='*39 + '\n'
		self._http.write( msg2 )
		self._http.write( response.dump() )
		
		self._http.write( '\n' + '='*(len(msg)-1) + '\n')
		self._http.flush()

	def getLongDesc( self ):
		'''
		@return: A DETAILED description of the plugin functions and features.
		'''
		return '''
		This plugin writes the framework messages to a text file.
		
		Four configurable parameters exist:
			- fileName
			- httpFileName
			- verbosity
		'''
