Connect to piFilter: Technical manual
General Information
piFilter is the online engine, which receives your request for each image and generates the adult content estimation for each image. piFilter responds with the estimation value equal to 'porn', 'no porn' or 'suspicious'. Then you are able to handle this result as it is needed for your business. You should develop the simple software code to access piFilter from your service.
Three simple steps to use piFilter:
- Subscribe
- Receive the customer ID string
- Start using piFilter. Read this page for more info.
HTTP protocol must be used to get access to piFilter. The data is encoded into multipart/form-data and sent to piFilter engine via API. The service responds by text/plain.
piFilter supports two types of requests:
- request, containing the image URL (URL-based request)
- request, containing the image itself (Image-based request)
If you use URL-based requests, you have to make sure that URL grants direct access to the image from the external query. Some images are not accessible by URLs.
You must use the ID string in any type of the request. The ID string identifies the customer. It is issued after the first subscriber registration. In addition to that, you can use your IP-s to limit the access and ensure better protection. The default method of user identification is the ID string only.
URL-based request must contain following parameters:
- ControlStr - ID string
- Url - URL of the image
Image-based request must contain following parameters:
- ControlStr - ID string
- ImageFile - image file
ImageFile transfers as it is, as binary.
The requests to the service looks like the browser-generated requests.
For instance, the form querying piFilter by URL of the image, can look as:
<form name="URLform" method="post" action="http://service.pifilter.com/Url.ashx" enctype="multipart/form-data"> <input name="Url" type="text" value="" /> <input name="ControlStr" type="text" value="" /> <input type="submit" name="Send" value="Send" /> </form>
The form querying piFilter by the image file, can look as:
<form name="Imageform" method="post" action="http://service.pifilter.com/Image.ashx" enctype="multipart/form-data"> <input type="file" name="ImageFile"/> <input name="ControlStr" type="text" value="" /> <input type="submit" name="Send" value="Send" /> </form>
You can try the forms above to perform test requests to piFilter.
In response to your request, piFilter returns the text string consisting of:
- Porn estimation - positive integer, if the request has been processed successfully
- Error code - negative integer and the text with the error description, if the request has failed by some reason.
Porn estimation values:
| Value | Description |
| 1 | No porn |
| 2 | Porn |
| 3 | Suspicious |
Error codes:
| Value | Description |
| Billing | |
| -10 | Query limit is over |
| -11 | Unknown Control String |
| -12 | Incorrect IP address |
| -13 | Bandwidth limit is exceeded |
| Data errors | |
| -20 | Incorrect URL |
| -30 | Image is corrupt |
| -31 | Image too small |
| -32 | Image too big |
| Others | |
| -40 | Unknown error |
If you have set up IP-s to limit the access, then you can connect only from those IP-s. Otherwise the service issues the error code -12
Software Code Samples
Most of high-level languages have the standard libraries to compose, send and process HTTP requests.
Common algorithm of using such libraries is following:
- Make objects to compose http-requests to the HTTP service
- Initiate objects to establish the connection
- Generate the query using the available data
- Send the query
- Process the query results received from the service.
Using Perl to query piFilter
URL-based query
#!perl -w
use HTTP::Request::Common;
require LWP::UserAgent;
# Url of image
my $url='http://someserver.com/someimage.jpg';
# Create a user agent object
$ua = LWP::UserAgent->new;
# Create a request, send to user agent and get a response back
$response = $ua->request(POST 'http://service.pifilter.com/Url.ashx',
Content_Type => 'form-data',
Content => [Url => $url,
ControlStr => 'abcdefghijklmnopqrstuvwxyz0123']);
# Check the outcome of the response
if ($response->is_success)
# if request processed successfully
{
($result,$error_mesg) = split /,/,$response->content;
# Check errors
if ($result > 0)
# if no errors
{
print "PRating for url $url is $result.";
}
else
# if error
{
print "Error for url $url! Error code is $result, $error_mesg.";
}
}
# if request processed unsuccessfully
else { $mesg=$response->status_line; print "Error executing query. $mesg"; }
Image-based query
#!perl -w
use HTTP::Request::Common;
require LWP::UserAgent;
# Full name of file
my $full_filename = '/somedir/somefile.jpg';
# Create a user agent object
$ua = LWP::UserAgent->new;
# Create a request, send to user agent and get a response back
$response = $ua->request(POST 'http://service.pifilter.com/Image.ashx',
Content_Type => 'form-data',
Content => [ImageFile => [$full_filename;],
ControlStr => 'abcdefghijklmnopqrstuvwxyz0123']);
# Check the outcome of the response
if ($response->is_success)
# if request processed successfully
{
($result,$error_mesg) = split /,/,$response->content;
# Check errors
if ($result > 0)
# if no errors
{
print "PRating for url $url is $result.";
}
else
# if error
{
print "Error for url $url! Error code is $result, $error_mesg.";
}
}
# if request processed unsuccessfully
else { $mesg=$response->status_line; print "Error executing query. $mesg"; }
If you have the image itself and you do not need saving it on the hard disk , you can send a direct request to API replacing
Content => [ImageFile => [$full_filename;],
by following lines
Content => [ImageFile =>
undef,
"$session",
'Content_Type' => 'image/jpeg;',
'Content' => $imagecontent],
Using MS Visual C# to query piFilter
Two classes made in MS .NET platform can be used to work with piFilter:
- PFilterRequest – performs the query
- PFilterRequestResult – represents the result of the query.
Both methods, URL-based and Image-based queries are realized by those classes.
using System;
using System.IO;
using System.Net;
using System.Text;
class Program
{
static void Main( String[] args )
{
// Image Url
const String sampleUrl = "http://someserver.com/someimage.jpg";
// Service Url
const String serverUrl = "http://service.pifilter.com";
// Control string
const String controlString = "abcdefghijklmnopqrstuvwxyz0123";
// Make query manager
PFilterRequest request = new PFilterRequest( serverUrl, controlString );
// Example #1. URL-based query
// Request for estimation by the URL
PFilterRequestResult result = request.GetPRatingByUrl( sampleUrl );
// Result analysis
if( result.ErrorCode < 0 )
{ Console.WriteLine("Error for url {0}!\r\nError code is {1}, {2}.",
sampleUrl, result.ErrorCode, result.ErrorMessage );
}
else
{ Console.WriteLine( "PRating for url {0} is {1}.", sampleUrl, result.PRating ); }
// Example #2. Image-based query
// Load the image
// Make the query
WebRequest imageRequest = WebRequest.Create( sampleUrl );
imageRequest.Method = WebRequestMethods.Http.Get;
// Receives the response
using( HttpWebResponse response = (HttpWebResponse)imageRequest.GetResponse() )
{
// Make local stream for the image
using( MemoryStream localStream = new MemoryStream() )
{
// Receives the response stream from the service
using( Stream stream = response.GetResponseStream() )
{
// Copy the service response to the local stream
Byte[] buffer = new Byte[65546];
Int32 bytesCount;
while( (bytesCount = stream.Read( buffer, 0, buffer.Length )) > 0 )
{ localStream.Write( buffer, 0, bytesCount ); }
}
localStream.Position = 0;
// Request for estimation by the image
result = request.GetPRatingByImage( localStream );
}
}
// Result analysis
if( result.ErrorCode < 0 )
{ Console.WriteLine("Error for url {0}!\r\nError code is {1}, {2}.",
sampleUrl, result.ErrorCode, result.ErrorMessage );}
else
{ Console.WriteLine( "PRating for url {0} is {1}.", sampleUrl, result.PRating );}
Console.ReadLine();
}
}
public class PFilterRequest
{
///
/// Service Url
///
private readonly String serverUrl;
///
/// ID string
///
private readonly String controlString;
///
/// Make query manager
///
/// service Url
/// Control string
public PFilterRequest( String serverUrl, String controlString )
{ this.serverUrl = serverUrl;
this.controlString = controlString;
}
///
/// Request for estimation for this url
///
/// image Url
/// Porn value
public PFilterRequestResult GetPRatingByUrl( String url )
{
// Delimiter
String boundary = "----" + DateTime.Now.Ticks.ToString( "x" );
Byte[] openBoundary = Encoding.ASCII.GetBytes( "--" + boundary + "\r\n" );
// Make the query header
WebRequest request = WebRequest.Create( serverUrl + "/Url.ashx" );
request.Method = WebRequestMethods.Http.Post;
request.ContentType = String.Format( "multipart/form-data; boundary={0}", boundary );
request.Timeout = 30000;
// Write sections into the query stream
using( Stream reqStream = request.GetRequestStream() )
{
// Initial delimiter
reqStream.Write( openBoundary, 0, openBoundary.Length );
// 1-st section. Control word
String part1 = String.Format(
"Content-Disposition: form-data; name=\"ControlStr\"\r\n\r\n{0}\r\n", controlString );
Byte[] part1Bytes = Encoding.UTF8.GetBytes( part1 );
reqStream.Write( part1Bytes, 0, part1Bytes.Length );
// Delimiter
reqStream.Write( openBoundary, 0, openBoundary.Length );
// 2-nd section. Image Url
String part2 = String.Format(
"Content-Disposition: form-data; name=\"Url\"\r\n\r\n{0}\r\n", url );
Byte[] part2Bytes = Encoding.UTF8.GetBytes( part2 );
reqStream.Write( part2Bytes, 0, part2Bytes.Length );
// Final delimiter
Byte[] closeBoundary = Encoding.ASCII.GetBytes( "--" + boundary + "--" + "\r\n" );
reqStream.Write( closeBoundary, 0, closeBoundary.Length );
}
Byte[] resBytes;
// Receive service response
using( WebResponse response = request.GetResponse() )
{
// Receive response stream
using( Stream resStream = response.GetResponseStream() )
{
// Copy the response stream to the memory stream
using( MemoryStream ms = new MemoryStream() )
{ Int32 nread;
Byte[] buffer = new Byte[4096];
while( (nread = resStream.Read( buffer, 0, 4096 )) != 0 )
{ ms.Write( buffer, 0, nread ); }
// Encode the memory stream to the byte array
resBytes = ms.ToArray();
}
}
}
// Decode the response to the string
String resString = Encoding.UTF8.GetString( resBytes );
// Split into words
String[] results = resString.Split( ",".ToCharArray() );
// No words mean the error response
if( results.Length == 0 )
{ throw new ApplicationException( "Invalid response!" ); }
// Encode the first word into the porn value
Int32 prating = Int32.Parse( results[0] );
// If value < 0, then generate the error,
// if value >= 0, then generate the porn estimation result
PFilterRequestResult result = prating < 0
? new PFilterRequestResult( prating, results[1] )
: new PFilterRequestResult( prating );
return result;
}
///
/// Request for porn estimation for the image
///
/// Изображение (поток)
/// Porn estimation value
public PFilterRequestResult GetPRatingByImage( Stream image )
{
// Query string delimiter
String boundary = "----" + DateTime.Now.Ticks.ToString( "x" );
Byte[] openBoundary = Encoding.ASCII.GetBytes( "--" + boundary + "\r\n" );
// Query header
WebRequest request = WebRequest.Create( serverUrl + "/Image.ashx" );
request.Method = WebRequestMethods.Http.Post;
request.ContentType = String.Format( "multipart/form-data; boundary={0}", boundary );
request.Timeout = 30000;
// Write sections into the query string
using( Stream reqStream = request.GetRequestStream() )
{
// Initial delimiter
reqStream.Write( openBoundary, 0, openBoundary.Length );
// First section. Control word
String part1 = String.Format(
"Content-Disposition: form-data; name=\"ControlStr\"\r\n\r\n{0}\r\n", controlString );
Byte[] part1Bytes = Encoding.UTF8.GetBytes( part1 );
reqStream.Write( part1Bytes, 0, part1Bytes.Length );
// Delimiter
reqStream.Write( openBoundary, 0, openBoundary.Length );
// Second section. Image
// Section header
String part2 =
"Content-Disposition: form-data; name=\"ImageFile\"; filename=\"ImageFile\"\r\n" +
"Content-Type: application/octet-stream\r\n" +
"Content-Transfer-Encoding: binary\r\n\r\n";
Byte[] part2Bytes = Encoding.UTF8.GetBytes( part2 );
reqStream.Write( part2Bytes, 0, part2Bytes.Length );
// Image stream
Int32 nread;
Byte[] buffer = new Byte[4096];
while( (nread = image.Read( buffer, 0, 4096 )) != 0 )
{ reqStream.Write( buffer, 0, nread ); }
// Line feed
reqStream.WriteByte( (Byte)'\r' );
reqStream.WriteByte( (Byte)'\n' );
// Final delimiter
Byte[] closeBoundary = Encoding.ASCII.GetBytes( "--" + boundary + "--" + "\r\n" );
reqStream.Write( closeBoundary, 0, closeBoundary.Length );
}
Byte[] resBytes;
// Receive the server response
using( WebResponse response = request.GetResponse() )
{
// Receive the response stream
using( Stream resStream = response.GetResponseStream() )
{
// Copy the response stream to the memory
using( MemoryStream ms = new MemoryStream() )
{ Int32 nread;
Byte[] buffer = new Byte[4096];
while( (nread = resStream.Read( buffer, 0, 4096 )) != 0 )
{ ms.Write( buffer, 0, nread ); }
// Encode the memory stream to the byte array
resBytes = ms.ToArray();
}
}
}
// Decode the response to the string
String resString = Encoding.UTF8.GetString( resBytes );
// Split the string to words
String[] results = resString.Split( ",".ToCharArray() );
// No words means the error
if( results.Length == 0 )
{ throw new ApplicationException( "Invalid response!" ); }
// Encode first word into the estimation value
Int32 prating = Int32.Parse( results[0] );
// If value < 0, then generate the error,
// if value >= 0, then generate the porn estimation result
PFilterRequestResult result = prating < 0
? new PFilterRequestResult( prating, results[1] )
: new PFilterRequestResult( prating );
return result;
}
}
public class PFilterRequestResult
{
///
/// False value if the error occurs
///
public const Int32 ErrorPRating = -1;
///
/// Error code if no errors
///
public const Int32 NoErrorCode = 0;
///
/// Error description
///
public const String NoErrorMessage = "No error";
///
/// Porn estimation value
///
private readonly Int32 pRating;
///
/// Error code
///
private readonly Int32 errorCode;
///
/// Error description
///
private readonly String errorMessage;
///
/// Common constructor
///
/// Porn estimation value
/// Error code
/// Error description
public PFilterRequestResult( Int32 pRating, Int32 errorCode, String errorMessage )
{ this.pRating = pRating;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
///
/// Valid result constructor
///
/// Porn estimation value
public PFilterRequestResult( Int32 pRating )
{ this.pRating = pRating;
this.errorCode = NoErrorCode;
this.errorMessage = NoErrorMessage;
}
///
/// Constructor if error occurs
///
/// Error code
/// Error description
public PFilterRequestResult( Int32 errorCode, String errorMessage )
{ this.pRating = ErrorPRating;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
///
/// Porn estimation value
///
public Int32 PRating
{ get { return pRating; } }
///
/// Error code
///
public Int32 ErrorCode
{ get { return errorCode; } }
///
/// Error description
///
public String ErrorMessage
{ get { return errorMessage; } }
}