If XML-RPC is enabled, an external program written in many different programming languages can communicate with POPFile to use its services. The POPFile API is exposed via the UI::XMLRPC module which was first shipped with the 0.22.0 release. The UI::XMLRPC module requires some extra Perl components not used by a standard POPFile installation.
Full details of the API and methods can be found here: popfile_xml-rpc_api
General information about XML-RPC can be found here: XMLRPC.com
The Windows installer offers the UI::XMLRPC module as an optional component (it is not part of the default installation). When the optional UI::XMLRPC module is installed, the Windows installer will also install the extra Perl components the module requires.
Your XMLRPC client can be run on any machine and can be written in any language. The client is not supplied, you must supply your own. Sample Perl, Python, Delphi and NSBasic/CE clients are provided below.
The XML-RPC listen port can be configured on POPFile's Configuration page in the Module Options section. Note that the configuration option will not be displayed unless the UI::XMLRPC.pm module is installed and POPFile has been restarted to recognize the module's presence.
When installed, the module will add a new security option to the POPFile UI's Security Page under the server section. The option “Accept XML-RPC connections from remote machines (requires POPFile restart)” will appear. To permit access from non-localhost machines, you must set this option to yes.
Note: If you use the Windows installer to install the UI::XMLRPC module then these Perl components will automatically be installed for you.
The following Perl modules must be installed on the machine running POPFile. Additionally, the SOAP::Lite module would be required on any client machine using a Perl client to access POPFile via XMLRPC.
ppm >install SOAP-Lite
use strict; use XMLRPC::Lite; my $sk = XMLRPC::Lite ->proxy('http://localhost:8081/RPC2') -> call('POPFile/API.get_session_key','admin', '') -> result; print XMLRPC::Lite ->proxy('http://localhost:8081/RPC2') -> call('POPFile/API.classify',$sk,'spam.txt') -> result; XMLRPC::Lite ->proxy('http://localhost:8081/RPC2') -> call('POPFile/API.release_session_key',$sk);
Saving the above as testxml.pl and running it with test message 'spam.txt' with a properly configured system will result in the following output:
perl testxml.pl spam
from xmlrpclib import ServerProxy POPFile = ServerProxy("http://localhost:8081") pf = POPFile.POPFile.API # naming shortcut to make things easier key = pf.get_session_key("admin","") print pf.classify(key, "spam.txt") pf.release_session_key(key)
Saving the above as testxml.py and running it with test message 'spam.txt' with a properly configured system will result in the following output:
python testxml.py spam
program popdelphi; {$APPTYPE CONSOLE} uses sysutils, xmlrpctypes, xmlrpcclient; var caller: TCaller; func: TFunction; rslt: TResult; SessionKey: String; MessageBucket: String; begin caller := TCaller.Create; caller.EndPoint := '/RPC2'; caller.HostName := '127.0.0.1'; caller.HostPort := 8081; func := TFunction.Create; func.ObjectMethod := 'POPFile/API.get_session_key'; func.AddParam('admin'); func.AddParam(//); rslt := caller.Execute(func); SessionKey := rslt.GetString; func.ObjectMethod := 'POPFile/API.classify'; func.AddParam(SessionKey); func.AddParam(ExpandFileName(ParamStr(1))); rslt := caller.Execute(func); MessageBucket := rslt.GetString; Writeln(MessageBucket); func.ObjectMethod := 'POPFile/API.release_session_key'; func.AddParam(SessionKey); caller.Free; func.Free; end.
This implementation uses xmlrpctypes and xmlrpcclient which are available in Delphi XML-RPC library. You will also need Indy - Internet Direct Components.
Saving and compiling the above will create popdelphi.exe. Running it in a DOS prompt (a default path would be interesting), passing a message file name as argument and using a properly configured system, will result in the following output example:
popdelphi popfile99.msg spam
AddObject "PocketXMLRPC.Factory","xmlrpc" Set popfile = xmlrpc.proxy("http://192.168.200.1:8081/RPC2","POPFile/API.") sessionKey = popfile.get_session_key("admin", "") message = MsgBox("POPFile Session Key is " & sessionKey, vbInformation, "POPFile Message") Print popfile.classify(sessionKey,"C:\spam.txt") popfile.release_session_key(sessionKey)
This implementation uses NS Basic/CE for Windows CE. You will also need PocketHTTP and PocketXML-RPC COM components.
Remember that, in this example, you are not accessing localhost, you are outside your POPFile default installation. So, you will need to point your mobile device to a valid network IP where your POPFile is running. In this case, 192.168.200.1 is the desktop IP where POPFile is running. Your mobile device will be accessing XMLRPC interface via bluetooth network or WiFI. Considering that, you will also need to Accept XML-RPC connections from remote machines. This may be done using Security tab and setting this feature to Yes.
use strict; use XMLRPC::Lite; my $xml= XMLRPC::Lite -> proxy('http://localhost:8081/RPC2')->on_fault(sub{}); # # Get a session key from POPFile # my $sk = $xml->call("POPFile/API.get_session_key",'admin',''); my $key = $sk->result; my $method = "POPFile/API.$ARGV[0]"; my @params = @ARGV[1..10]; unshift @params,$key; my $can = $xml->can($method); my $res = eval {$xml->call($method,@params)}; if ($@) { print join("\n","syntax error: " ,$@); exit(1); } elsif ($can && !UNIVERSAL::isa($res => 'XMLRPC::SOM')) { print $res; } elsif (defined($res) && $res->fault) { print join ("\n","XMLRPC FAULT: ", @{$res->fault}{'faultCode','faultString'}); exit(1); } elsif (!$xml->transport->is_success) { print join ("\n","TRANSPORT ERROR: ", $xml->transport->status); } else { if ( ref $res->paramsall eq 'ARRAY' ) { print join "\n", @{$res->paramsall}; } else { print $res->paramsall; } } print "\n"; # # Release the session key # $xml->call("POPFile/API.release_session_key",$key); # # All Done # exit(0);
Saving the above as testxml.pl and running it with commandline parameters shown returns the result of the API call.
perl testxml.pl get_bucket_parameter spam count 9418 perl testxml.pl get_bucket_parameter spam fpcount 24 perl testxml.pl get_bucket_parameter spam fncount 43 perl testxml.pl get_bucket_color spam red perl testxml.pl get_bucket_word_count spam 37135 perl testxml.pl get_bucket_unique_count spam 9407 perl testxml.pl get_buckets magnet normal spam
Implement pipe.pl as an XMLRPC client
#!/usr/bin/perl use strict; use XMLRPC::Lite; # we want secure temporary files, though this script will usually be run as a user use File::Temp qw/tempfile tempdir/; # a folder we can access that will go away when we exit my $temp_dir = tempdir( CLEANUP => 1); # and a temporary file, with the full path specified my ($fh_in, $filename_in) = tempfile('popfileinXXXXXXX', SUFFIX => ".msg", UNLINK => 1 , DIR => $temp_dir); # act like a pipe, reading from STDIN while (<STDIN>) { print $fh_in $_; } # POPFile expects a closed file close $fh_in; # create a secure output file my ($fh_out, $filename_out) = tempfile('popfileoutXXXXXXX', SUFFIX => ".msg", UNLINK => 1, DIR => $temp_dir); # our XMLRPC proxy my $xmlrpc = XMLRPC::Lite ->proxy('http://localhost:8086/RPC2'); # say hello and get a session key my $sk = $xmlrpc-> call('POPFile/API.get_session_key','admin','') -> result; # this does the work $xmlrpc-> call('POPFile/API.handle_message',$sk,$filename_in,$filename_out) -> result; # say goodbye $xmlrpc-> call('POPFile/API.release_session_key',$sk); # continue acting like a pipe, and print to STDOUT while (<$fh_out>) { print $_; } # exit, and File::Temp cleans up exit(0);
Full access to POPFile's API (declared in POPFile::API module) through UI::XMLRPC module. For further documentation on API syntax, see the Classifier::Bayes module that ships with POPFile.
Note that you must obtain a session_key using the get_session_key API call in order to use any of the API's. You should release the key using release_session_key when you are finished.
The XML-RPC available methods are:
Subroutine Name | Usage comments | ||
get_session_key | call('POPFile/API.get_session_key','admin','') returns a session_key |
||
release_session_key | call('POPFile/API.release_session_key','session_key') releases the session key |
||
classify | call('POPFile/API.classify', 'session_key', 'filename') returns bucket name, note that filename must exist in the popfile directory (or the full path must be specified) on the machine that is running POPFile. |
||
classify_and_modify | Does not work for XmlRpc, expects filehandles, use handle_message instead. | ||
handle_message | call('POPFile/API.handle_message', 'session_key', 'inputfilename', 'outputfilename') returns bucketname, the history slot-id, and a Boolean specifying whether a magnet was used for classification, similar to classify but adds message to POPFile history and writes message with POPFile headers to output file. Note, there is a known issue with this call. It presently adds a . and 0x0d0a to the end of output file. |
||
get_buckets | call('POPFile/API.get_buckets','session_key') returns an array of bucket names (exclude 'unclassified' bucket) |
||
get_pseudo_buckets | call('POPFile/API.get_pseudo_buckets','session_key') returns an array of pseudo-bucket names ('unclassified' bucket) |
||
get_all_buckets | call('POPFile/API.get_all_buckets','session_key') returns an array of bucket names (include 'unclassified' bucket) |
||
is_bucket | call('POPFile/API.is_bucket','session_key', 'bucketname') returns 1 if the bucketname exists, returns 0 if the bucketname does not exist, or the bucketname is a pseudo-bucket ('unclassified' bucket) |
||
is_pseudo_bucket | call('POPFile/API.is_pseudo_bucket','session_key', 'bucketname') returns 1 if the bucketname exists and it is a pseudo-bucket ('unclassified' bucket), returns 0 if the bucketname does not exist, or the bucketname is not a pseudo-bucket |
||
get_bucket_word_count | call('POPFile/API.get_bucket_word_count', 'session_key', 'bucketname') returns word count of bucket |
||
get_bucket_word_list | call('POPFile/API.get_bucket_word_list', 'session_key', 'bucketname') returns array of words found in bucket |
||
get_bucket_word_prefixes | call('POPFile/API.get_bucket_word_prefixes', 'session_key', 'bucketname') returns array of initial letters for words found in bucket |
||
get_count_for_word | call('POPFile/API.get_cont_for_word', 'session_key', 'bucketname', 'someword') returns word count for someword in bucket |
||
get_word_count | call('POPFile/API.get_word_count','session_key') returns word count of all buckets combined |
||
get_bucket_unique_count | call('POPFile/API.get_bucket_unique_count', 'session_key', 'bucketname') returns unique words in bucket |
||
get_bucket_color | call('POPFile/API.get_bucket_color', 'session_key', 'bucketname') returns color as string. Note: this API is DEPRECATED in favor of calling get_bucket_parameter for the parameter named 'color' |
||
set_bucket_color | call('POPFile/API.set_bucket_color', 'session_key', 'bucketname', 'colorstring') set the color of bucket. Returns 1 if succeeded. Note: this API is DEPRECATED in favor of calling set_bucket_parameter for the parameter named 'color' |
||
get_bucket_parameter | call('POPFile/API.get_bucket_parameter', 'session_key', 'bucketname', 'parameter') returns parameter value. Parameter can be one of count (classification count), fpcount (false positives), fncount (false negatives), subject (subject header modification), xtc (X-Text-Classification header), xpl (X-POPFile-Link header), quarantine (quarantine messages), or color (bucket color) |
||
set_bucket_parameter | call('POPFile/API.set_bucket_parameter', 'session_key', 'bucketname', 'parameter', 'value') sets the parameter to value, returns 1 if succeeded. Parameter can be one of count (classification count), fpcount (false positives), fncount (false negatives), subject (subject header modification), xtc (X-Text-Classification header), xpl (X-POPFile-Link header), quarantine (quarantine messages), or color (bucket color) |
||
get_html_colored_message | Note: get_html_colored_message was accidently left out of 0.22 but has been back in 0.22.1. call('POPFile/API.get_html_colored_message', 'session_key', 'filename') returns string containing colored message, note that filename must exist in the popfile directory or the full path must be specified |
||
create_bucket | call('POPFile/API.create_bucket', 'session_key', 'bucketname') returns 1 if succeeded |
||
delete_bucket | call('POPFile/API.delete_bucket', 'session_key', 'bucketname') returns 1 if succeeded. Note that you cannot delete 'unclassified' bucket |
||
rename_bucket | call('POPFile/API.rename_bucket', 'session_key', 'bucketname', 'newname') returns 0 on failure, 1 on success |
||
add_message_to_bucket | call('POPFile/API.add_message_to_bucket', 'session_key', 'bucketname', 'filename') Train POPFile with a mail file (reclassify a mail file to bucketname). Returns 0 on failure, 1 on success, note that filename must exist in the popfile directory or the full path must be specified |
||
add_messages_to_bucket | call('POPFile/API.add_messages_to_bucket', 'session_key', 'bucketname', 'filelist') Train POPFile with mail files (reclassify mail files to bucketname). Returns 0 on failure, 1 on success, note that filenames must exist in the popfile directory or the full path must be specified |
||
remove_message_from_bucket | call('POPFile/API.remove_message_from_bucket', 'session_key', 'bucketname', 'filename') Undo training POPFile. Returns 0 on failure, 1 on success, note that filename must exist in the popfile directory or the full path must be specified |
||
magnet_count | call('POPFile/API.magnet_count', 'session_key') returns magnet count of all bucket combined |
||
get_buckets_with_magnets | call('POPFile/API.get_buckets_with_magnets', 'session_key') returns array of bucket names specified by any magnets |
||
get_magnet_types_in_bucket | call('POPFile/API.get_magnet_types_in_bucket', 'session_key', 'bucketname') returns array of magnet types for the bucket |
||
clear_bucket | call('POPFile/API.clear_bucket', 'session_key', 'bucketname') empties the bucket. Returns 1 if succeeded |
||
clear_magnets | call('POPFile/API.clear_magnets','session_key') removes all magnets. Returns 1 if succeeded |
||
get_magnets | call('POPFile/API.get_magnets', 'session_key', 'bucketname', 'type') returns array of magnets of the specified type for the bucket |
||
create_magnet | call('POPFile/API.create_magnet', 'session_key', 'bucketname', 'magnettype', 'magnetvalue') creates a new magnet. Returns 1 if succeeded |
||
get_magnet_types | call('POPFile/API.get_magnet_types','session_key') returns a hash list of valid POPFile magnet types and mail headers |
||
delete_magnet | call('POPFile/API.delete_magnet', 'session_key', 'bucketname', 'magnettype','magnetvalue') deletes the magnet. Returns 1 if succeeded |
||
get_stopword_list | call('POPFile/API.get_stopword_list','session_key') returns array of stop words |
||
add_stopword | call('POPFile/API.add_stopword', 'session_key', 'mystopword') adds a word to stop words. Returns 0 if failed, 1 if succeeded |
||
remove_stopword | call('POPFile/API.remove_stopword', 'session_key', 'mystopword') removes a word from stop words. Returns 0 if failed, 1 if succeeded |
Note: In the API calls above, the 'session_key' is the key that is returned to you by the API call get_session_key.
For older versions of POPFile please replace “POPFile/API.” with “Classifier/Bayes.”.
Should you find anything in the documentation that is incomplete, unclear, outdated or just plain wrong, please let us know and leave a note in the Documentation Forum.