GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
Validator::Custom::Document::Version0(3) User Contributed Perl Documentation Validator::Custom::Document::Version0(3)

Validator::Custom::Document::Version0 - Documentation in Version 0.xx

  use Validator::Custom;
  my $vc = Validator::Custom->new;
  
  # Data
  my $data = {id => 1, name => 'Ken Suzuki', age => ' 19 '};

  # Create Rule
  my $rule = $vc->create_rule;
  
  # Rule syntax - integer, have error message
  $rule->require('id')->check('int')->message('id should be integer');
  
  # Rule syntax - string, not blank, length is 1 to 5, have error messages
  $rule->require('name')
    ->check('string')->message('name should be string')
    ->check('not_blank')->message('name should be not blank')
    ->check({length => [1, 5]})->message('name is too long');
  
  # Rule syntax - value is optional, default is 20
  $rule->optional('age')->filter('trim')->check('int')->default(20);
  
  # Validation
  my $result = $vc->validate($data, $rule);
  if ($result->is_ok) {
    # Safety data
    my $safe_data = $vresult->data;
  }
  else {
    # Error messgaes
    my $errors = $vresult->messages;
  }
  
  # You original constraint(you can call constraint from $_)
  my $blank_or_number = sub {
    my $value = shift;
    return $_->blank($value) || $_->regex($value, qr/[0-9]+/);
  };
  $rule->require('age')
    ->check($blank_or_number)->message('age must be blank or number')
  
  # Rule old syntax, please use above new syntax.
  # Old syntax take many miss-typing.
  my $rule = [
    id => {message => 'id should be integer'} => [
      'int'
    ],
    name => [
      ['not_blank' => 'name is emtpy'],
      [{length => [1, 5]} => 'name is too long']
    ],
    age => {require => 0, default => 20} => [
      ['not_blank' => 'age is empty.'],
      ['int' => 'age must be integer']
    ]
  ];

Validator::Custom validate HTML form data easy and flexibly. The features are the following ones.
  • Many constraint functions are available by default, such as "not_blank", "int", "defined", "in_array", "length".
  • Several filter functions are available by default, such as "trim", "datetime_to_timepiece", "date_to_timepiece".
  • You can register your constraint function.
  • You can set error messages for invalid parameter value. The order of messages is kept.
  • Support "OR" condition constraint and negative constraint,

1. Create a new Validator::Custom object

  use Validator::Custom;
  my $vc = Validator::Custom->new;

2. Prepare data for validation

  my $data = {age => 19, name => 'Ken Suzuki'};

Data must be hash reference.

3. Prepare a rule for validation

  my $ruel = $vc->create_rule;
  $rule->require('age')
    ->check('not_blank')
    ->check('int')->message('age must be integer');
  
  $rule->require('name')
    ->check('not_blank')->message('name is empty')
    ->check({length => [1, 5]})->message('name must be length 1 to 5');

Please see "RULE" in Validator::Custom about rule syntax.

You can use many constraint function, such as "int", "not_blank", "length". See "CONSTRAINTS" in Validator::Custom to know all constraint functions.

Rule details is explained in "3. Rule syntax" section.

4. Validate data

  my $result = $vc->validate($data, $rule);

use "validate()" to validate the data applying the rule. "validate()" return Validator::Custom::Result object.

5. Manipulate the validation result

  unless ($result->is_ok) {
    if ($result->has_missing) {
      my $missing_params = $result->missing_params;
    }
    
    if ($result->has_invalid) {
      my $messages = $result->messages_to_hash;
    }
  }

If you check the data is completely valid, use "is_ok()". "is_ok()" return true value if invalid parameter values is not found and all parameter names specified in the rule is found in the data.

If at least one of parameter names specified in the rule is not found in the data, "has_missing()" return true value.

You can get missing parameter names using "missing_params()". In this example, return value is the following one.

  ['price']

If at least one of parameter value is invalid, "has_invalid()" return true value.

You can get the pairs of invalid parameter name and message using "messages_to_hash()". In this example, return value is the following one.

  {
    name => 'name must be string. the length 1 to 5'
  }

Validator::Custom::Result details is explained in "2. Validation result".

"validate()" return Validator::Custom::Result object. You can manipulate the result by various methods.

"is_ok()", "has_missing()", "has_invalid()", "missing_params()", "messages_to_hash()" is already explained in "1. Basic"

The following ones is often used methods.

data()

  my $data = $result->data;

Get the data in the end state. Validator::Custom has filtering ability. The parameter values in data passed to "validate()" is maybe converted to other data by filter. You can get filtered data using "data()".

messages()

  my $messages = $result->messages;

Get messages corresponding to the parameter names which value is invalid. Messages keep the order of parameter names of the rule.

message()

  my $message = $result->message('name');

Get a message corresponding to the parameter name which value is invalid.

All Validator::Custom::Result's APIs is explained in the POD of Validator::Custom::Result

  # Create Rule
  my $rule = $vc->create_rule;
  
  # Rule syntax - integer, have error message
  $rule->require('id')->check('int')->message('id should be integer');
  
  # Rule syntax - not blank, length is 1 to 5, have error messages
  $rule->require('name')
    ->check('not_blank')->message('name is emtpy')
    ->check({length => [1, 5]})->message('name is too long');
  
  # Rule syntax - value is optional, default is 20
  $rule->optional('age')->check('int')->default(20);

Rule is Validator::Custom::Rule ojbect. You can create "create_rule" method of Validator::Custom.

  my $rule = $vc->create_rule

At first you set topic, "require" method or "optional" method. If the value is required, you use "require" method. If the value is not always required, you use "optional" method.

  # Required
  $rule->require('age');
  
  # Optional
  $rule->optional('age');

If you set topic to multiple keys, you should set key name by "name" method.

  # Key name
  $rule->require(['mail1', 'mail2'])->name('mail');

You can set options, "message", "default", and "copy".

1. message
 $rule->require('age')->message('age is invalid');
    

Message corresponding to the parameter name which value is invalid.

2. default
  $rule->require('age')->default(5)
    

Default value. This value is automatically set to result data if the parameter value is invalid or the parameter name specified in rule is missing in the data.

If you set not string or number value, you should the value which surrounded by code reference

  $rule->require('age')->default(sub { [] })
    
3. copy
  $rule->require('age')->copy(0)
    

If this value is 0, The parameter value is not copied to result data. Default to 1. Parameter value is copied to the data.

You set constraints by "check" method.

  $rule->require('age')->check({'length' => [1, 5]});

You can set message for each constraint function

  $rule->require('name')
    ->check('not_blank')->message('name must be not blank')
    ->check({length => [1, 5]})->message('name must be 1 to 5 length');

You can create original constraint function using original constraints. you can call constraints from $_ in subroutine.

  # You original constraint(you can call constraint from $_)
  my $blank_or_number = sub {
    my $value = shift;
    return $_->blank($value) || $_->regex($value, qr/[0-9]+/);
  };
  my $rule = [
    name => [
      [$blank_or_number => 'name must be blank or number']
    ]
  ];

Multiple parameters validation

Multiple parameters validation is available.

  Data: {password1 => 'xxx', password2 => 'xxx'}
  Rule: $rule->require([qw/password1 password2/])->name('password_check)
          ->check('duplication')

In this example, We check if 'password1' and 'password2' is same. The following value is passed to constraint function "duplication".

  ['xxx', 'xxx']

You must specify new key, such as "password_check". This is used by Validator::Result object.

You can also use the reference of regular expression if you need.

  Data: {person1 => 'Taro', person2 => 'Rika', person3 => 'Ken'}
  Rule: $rule->require(qr/^person/)->name('merged_person')
          ->check('merge') # TaroRikaKen

All matched value is passed to constraint function as array reference. In this example, the following value is passed.

  ['Taro', 'Rika', 'Ken']

Negative constraint function

You can negative a constraint function

  Rule: $rule->require('age')->check('!int')

"!" is added to the head of the constraint name if you negative a constraint function. '!int' means not 'int'.

In this example,

"OR" condition

You can create "OR" condition by using "check_or" method.

  Rule: $rule->require('email')->check_or('blank', 'email');

Check is ok if email value is blank or email.

The folloing way is old syntax. Please use above syntax.

  Rule: $rule->require('email')->check('blank || email')

Array validation

You can check if all the elements of array is valid.

  Data: {nums => [1, 2, 3]}
  Rule: $rule->require('nums')->array(1)->check('int')

If nums is one value, this is automatically convert to array.

The following is old syntax. Please use above syntax.

  Data: {nums => [1, 2, 3]}
  Rule: $rule->require('nums')->check('@int')

"@" is added to the head of constraint function name to validate all the elements of array.

Register constraint function

Validator::Custom has various constraint functions. You can see constraint functions registered by default "CONSTRAINTS" in Validator::Custom.

and you can register your constraint function if you need.

  $vc->register_constraint(
    telephone => sub {
      my $value = shift;
      
      my $is_valid;
      if ($value =~ /^[\d-]+$/) {
        $is_valid = 1;
      }
      return $is_valid;
    }
  );

Constraint function for telephone number is registered.

Constraint function receive a scalar value as first argument and return boolean value which check if the value is valid.

Constraint function receive argument of constraint function as second argument and Validator::Custom object as third argument.

  $vc->register_constraint(
    telephone => sub {
      my ($value, $arg, $vc) = @_;
      
      return $is_valid;
    }
  );

If you know the implementations of constraint functions, see the source of Validator::Custom::Constraint.

If you want to return custom message, you can use hash reference as return value.

  $vc->register_constraint(
    telephone => sub {
      my ($value, $arg, $vc) = @_;
      
      # Process
      my $is_valid = ...;
      
      if ($is_valid) {
        return 1;
      }
      else {
        return {result => 0, message => 'Custom error message'};
      }
    }
  );

Register filter function

"register_constraint()" is also used to register filter function.

Filter function is same as constraint function except for return value;

  $vc->register_constraint(
    to_upper_case => sub {
      my $value = shift;
      
      $value = uc $value;
                  
      return {result => 1, output => $value};
    }
  );

Return value of filter function must be array reference. First element is boolean value which check if the value is valid. Second element is filtered value.

In this example, First element of array reference is set to 1 because this function is intended to filter only.

You can also use array reference representation. This is old syntax. I recommend hash reference.

  # This is old syntax
  $vc->register_constraint(
    to_upper_case => sub {
      my $value = shift;
      
      $value = uc $value;
                  
      return [1, $value];
    }
  );

This is rule old syntax. Plese use new rule syntax.

Basic

Rule has specified structure.

Rule must be array reference.

  my $rule = [
  
  ];

This is for keeping the order of parameter names.

Rule has pairs of parameter name and constraint functions.

  my $rule = [
    age =>  [            # parameter name1
      'not_blank',       #   constraint function1
      'int'              #   constraint function2
    ],                                                   
                                                         
    name => [              # parameter name2       
      'not_blank',         #   constraint function1
      {'length' => [1, 5]} #   constraint function2
    ]
  ];

Constraint function can receive arguments using hash reference.

  my $rule = [
    name => [
        {'length' => [1, 5]}
    ]
  ];

You can set message for each constraint function

  my $rule = [
    name => [
        ['not_blank', 'name must be not blank'],
        [{length => [1, 5]}, 'name must be 1 to 5 length']
    ]
  ];

You can pass subroutine reference as constraint.

  # You original constraint(you can call constraint from $_)
  my $blank_or_number = sub {
    my $value = shift;
    return $_->blank($value) || $_->regex($value, qr/[0-9]+/);
  };
  my $rule = [
    name => [
      [$blank_or_number => 'name must be blank or number']
    ]
  ];

Option

You can set options for each parameter name.

  my $rule = [
           # Option
    age => {message => 'age must be integer'} => [
        'not_blank',
    ]
  ];

Option is located after the parameter name, and option must be hash reference.

The following options is available.

1. message
 {message => "This is invalid"}
    

Message corresponding to the parameter name which value is invalid.

2. default
  {default => 5}
    

Default value. This value is automatically set to result data if the parameter value is invalid or the parameter name specified in rule is missing in the data.

If you set not string or number value, you should the value which surrounded by code reference

  {default => sub { [] }}
    
3. copy
  {copy => 0}
    

If this value is 0, The parameter value is not copied to result data.

Default to 1. Parameter value is copied to the data.

4. require
If this value is 0 and parameter value is not found, the parameter is not added to missing parameter list.

Default to 1.

  Data: {name => 'Ken'}
  Rule: $rule->require('name')->check('ascii')

Ascii graphic characters(hex 21-7e).

  # Check (1, 2, .. 19, 20)
  Data: {age => 19}
  Rule: $rule->require('age')->check({between => [1, 20]})

Between A and B.

  Data: {name => ''}
  Rule: $rule->require('name')->check('blank')

Blank.

  Data: {num1 => '123', num2 => '1.45'}
  Rule: $rule->require('num1')->check({'decimal' => 3})
        $rule->require('num2')->check({'decimal' => [1, 2]})

Decimal. You can specify maximum digits number at before and after '.'.

If you set undef value or don't set any value, that means there is no maximum limit.

  Data: {num1 => '1233555.89345', num2 => '1121111.45', num3 => '12.555555555'}
  Rule: $rule->require('num1')->check('decimal')
        $rule->require('num2')->check({'decimal' => [undef, 2]})
        $rule->require('num2')->check({'decimal' => [2, undef]})

  Data: {name => 'Ken'}
  Rule: $rule->require('name')->check('defined')

Defined.

  Data: {mail1 => 'a@somehost.com', mail2 => 'a@somehost.com'};
  Rule: $rule->require(['mail1', 'mail2'])->name('mail')->check('duplication)

Check if the two data are same or not.

You can get result value

  my $mail = $vresult->data->{mail};

Note that if one value is not defined or both values are not defined, result of validation is false.

  Data: {price => 1000}
  Rule: $rule->require('price')->check({'equal_to' => 1000})

Numeric equal comparison.

  Data: {price => 1000}
  Rule: $rule->require('price')->check({'greater_than' => 900})

Numeric "greater than" comparison

  Data: {url => 'http://somehost.com'};
  Rule: $rule->require('url')->check('http_url')

HTTP(or HTTPS) URL.

  Data: {age => 19};
  Rule: $rule->require('age')->check('int')

Integer.

  Data: {food => 'sushi'};
  Rule: $rule->require('food')->check({'in_array' => [qw/sushi bread apple/]})

Check if the values is in array.

  Data: {value1 => 'aaa', value2 => 'bbbbb'};
  Rule: # length is equal to 3
        require('value1')->check({'length' => 3}) 
        # length is greater than or equal to 2 and lower than or equeal to 5
        require('value2')->check({'length' => [2, 5]}) 
        # length is greater than or equal to 2 and lower than or equeal to 5
        require('value3')->check({'length' => {min => 2, max => 5}}) 
        # greater than or equal to 2
        require('value4')->check({'length' => {min => 2}}) 
        # lower than or equal to 5
        require('value5')->check({'length' => {max => 5}})

Length of the value.

Not that if value is internal string, length is character length. if value is byte string, length is byte length.

  Data: {num => 20}
  Rule: $rule->require('num')->check({'less_than' => 25});

Numeric "less than" comparison.

  Data: {name => 'Ken'}
  Rule: $rule->require('name')->check('not_blank') # Except for ''

Not blank.

  Data: {name => 'Ken'}
  Rule: $rule->require('name')->check('not_defined')

Not defined.

  Data: {name => 'Ken'}
  Rule: $rule->require('name')->check('not_space') # Except for '', ' ', '   '

Not contain only space characters. Not that space is only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => '   '}
  Rule: $rule->require('name')->check('space') # '', ' ', '   '

White space or empty string. Not that space is only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => 'abc'}
  Rule: $rule->require('name')->check('string') # '', 'abc', 0, 1, 1.23

Check if the value is string, which contain numeric value. if value is not defined or reference, this check return false.

  Data: {age => 19}
  Rule: $rule->require('age')->check('uint')

Unsigned integer(contain zero).

  Data: {num => '123'}
  Rule: $rule->require('num')->check({'regex' => qr/\d{0,3}/})

Match a regular expression.

  Data: {hobby => ['music', 'movie' ]}
  Rule: $rule->require('hobby')->check({selected_at_least => 1})

Selected at least specified count item. In other word, the array contains at least specified count element.

You can use the following filter by default. "filter" method is only alias for "check" method for readability.

  Data: {date => '2010/11/12'}
  Rule: $rule->require('date')->filter('date_to_timepiece')

The value which looks like date is converted to Time::Piece object. If the value contains 8 digits, the value is assumed date.

  2010/11/12 # ok
  2010-11-12 # ok
  20101112   # ok
  2010       # NG
  2010111106 # NG

And year and month and mday combination is ok.

  Data: {year => 2011, month => 3, mday => 9}
  Rule: $rule->require(['year', 'month', 'mday'])->name('date')
                                          ->filter('date_to_timepiece')

You can get result value.

  my $date = $vresult->data->{date};

Note that Time::Piece is required.

  Data: {datetime => '2010/11/12 12:14:45'}
  Rule: $rule->require('datetime')->filter('datetime_to_timepiece');

The value which looks like date and time is converted to Time::Piece object. If the value contains 14 digits, the value is assumed date and time.

  2010/11/12 12:14:45 # ok
  2010-11-12 12:14:45 # ok
  20101112 121445     # ok
  2010                # NG
  2010111106 12       # NG

And year and month and mday combination is ok.

  Data: {year => 2011, month => 3, mday => 9
         hour => 10, min => 30, sec => 30}
  Rule: $rule->require(['year', 'month', 'mday', 'hour', 'min', 'sec'])
          ->name('datetime')->filter('datetime_to_timepiece')

You can get result value.

  my $date = $vresult->data->{datetime};

Note that Time::Piece is required.

  Data: {name1 => 'Ken', name2 => 'Rika', name3 => 'Taro'}
  Rule: $rule->require(['name1', 'name2', 'name3'])->name('mergd_name')
          ->filter('merge') # KenRikaTaro

Merge the values.

You can get result value.

  my $merged_name = $vresult->data->{merged_name};

Note that if one value is not defined, merged value become undefined.

  Data: {names => ['Ken', 'Taro']}
  Rule: $rule->require('names')->filter('shift') # 'Ken'

Shift the head element of array.

  Data: {languages => 'Japanese'}
  Rule: $rule->require('languages')->filter('to_array') # ['Japanese']

Convert non array reference data to array reference. This is useful to check checkbox values or select multiple values.

  Data: {name => '  Ken  '}
  Rule: $rule->require('name')->filter('trim') # 'Ken'

Trim leading and trailing white space. Not that trim only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => '  Ken   Takagi  '}
  Rule: $rule->require('name')->filter('trim_collapse') # 'Ken Takagi'

Trim leading and trailing white space, and collapse all whitespace characters into a single space. Not that trim only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => '  Ken  '}
  Rule: $rule->require('name')->filter('trim_lead') # 'Ken  '

Trim leading white space. Not that trim only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => '  Ken  '}
  Rule: $rule->require('name')->filter('trim_trail') # '  Ken'

Trim trailing white space. Not that trim only "[ \t\n\r\f]" which don't contain unicode space character.

  Data: {name => '  Ken  '}
  Rule: $rule->require('name')->filter('trim_uni') # 'Ken'

Trim leading and trailing white space, which contain unicode space character.

  Data: {name => '  Ken   Takagi  '};
  Rule: $rule->require('name')->filter('trim_uni_collapse') # 'Ken Takagi'

Trim leading and trailing white space, which contain unicode space character.

  Data: {name => '  Ken  '};
  Rule: $rule->require('name')->filter('trim_uni_lead') # 'Ken  '

Trim leading white space, which contain unicode space character.

  Data: {name => '  Ken  '};
  Rule: $rule->require('name')->filter('trim_uni_trail') # '  Ken'

Trim trailing white space, which contain unicode space character.

  my $constraints = $vc->constraints;
  $vc             = $vc->constraints(\%constraints);

Constraint functions.

  my $filter = $vc->data_filter;
  $vc        = $vc->data_filter(\&data_filter);

Filter for input data. If data is not hash reference, you can convert the data to hash reference.

  $vc->data_filter(sub {
    my $data = shift;
    
    my $hash = {};
    
    # Convert data to hash reference
    
    return $hash;
  });

  my $error_stock = $vc->error_stcok;
  $vc             = $vc->error_stock(1);

If error_stock is set to 0, "validate()" return soon after invalid value is found.

Default to 1.

  my $rule_obj = $vc->rule_obj($rule);

Validator::Custom rule is a little complex. You maybe make mistakes often. If you want to know that how Validator::Custom parse rule, See "rule_obj" attribute after calling "validate" method. This is Validator::Custom::Rule object.

  my $vresult = $vc->validate($data, $rule);

  use Data::Dumper;
  print Dumper $vc->rule_obj->rule;

If you see "ERROR" key, rule syntax is wrong.

  my $rule = $vc->rule;
  $vc      = $vc->rule(\@rule);

Validation rule. If second argument of "validate()" is not specified. this rule is used.

Validator::Custom inherits all methods from Object::Simple and implements the following new ones.

  my $vc = Validator::Custom->new;

Create a new Validator::Custom object.

  my $button = $self->js_fill_form_button(
    mail => '[abc]{3}@[abc]{2}.com,
    title => '[pqr]{5}'
  );

Create javascript button source code to fill form. You can specify string or pattern like regular expression.

If you click this button, each text box is filled with the specified pattern string, and checkbox, radio button, and list box is automatically selected.

Note that this methods require JSON module.

  $result = $vc->validate($data, $rule);
  $result = $vc->validate($data);

Validate the data. Return value is Validator::Custom::Result object. If second argument isn't passed, "rule" attribute is used as rule.

$rule is array reference (or Validator::Custom::Rule object, this is EXPERIMENTAL).

  $vc->register_constraint(%constraint);
  $vc->register_constraint(\%constraint);

Register constraint function.

  $vc->register_constraint(
    int => sub {
      my $value    = shift;
      my $is_valid = $value =~ /^\-?[\d]+$/;
      return $is_valid;
    },
    ascii => sub {
      my $value    = shift;
      my $is_valid = $value =~ /^[\x21-\x7E]+$/;
      return $is_valid;
    }
  );

You can register filter function.

  $vc->register_constraint(
    trim => sub {
      my $value = shift;
      $value =~ s/^\s+//;
      $value =~ s/\s+$//;
      
      return {result => 1, output => $value];
    }
  );

Filter function return array reference, first element is the value if the value is valid or not, second element is the converted value by filter function.

Check box validation is a little difficult because check box value is not exists or one or multiple.

  # Data
  my $data = {}
  my $data = {feature => 1}
  my $data = {feature => [1, 2]}

You can do the following way.

  $rule->require('feature')
    ->filter('to_array')
    ->check({selected_at_least => 1})->message('feature should select at least 1')
    ->each(1)
    ->check('int')->message('features should be integer');

Validator::Custom

  # Atrribute methods
  shared_rule # Removed at 2017/1/1
  
  # Methods
  __PACKAGE__->constraints(...); # Call constraints method as class method
                                 # Removed at 2017/1/1
L<Validator::Custom::Result>

  # Attribute methods
  error_infos # Removed at 2017/1/1 

  # Methods
  error_reason # Removed at 2017/1/1
  add_error_info # Removed at 2017/1/1
  error # Removed at 2017/1/1
  errors # Removed at 2017/1/1
  errors_to_hash # Removed at 2017/1/1
  invalid_keys # Removed at 2017/1/1
  remove_error_info # Removed at 2017/1/1

If a functionality is DEPRECATED, you can know it by DEPRECATED warnings. DEPRECATED functionality is removed after five years, but if at least one person use the functionality and tell me that thing I extend one year each time you tell me it.

EXPERIMENTAL functionality will be changed without warnings.

Yuki Kimoto, "<kimoto.yuki at gmail.com>"

<http://github.com/yuki-kimoto/Validator-Custom>

Copyright 2009-2014 Yuki Kimoto, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

2015-12-08 perl v5.32.1

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.