Custom UAPI Modules
Overview
You can add custom modules to cPanel & WHM and call them with UAPI.
Make certain that you thoroughly test custom modules before you attempt to add them to production servers.
cPanel & WHM does not support custom modules for the WHM API 1 system.
Steps to create a custom module
To create a custom module and add it to cPanel & WHM's UAPI, perform the following steps:
- Create a Perl module.
Save your custom module as the /usr/local/cpanel/Cpanel/API/Module.pm
file, where Module
is the custom module's name.
UAPI modules reside in the Cpanel::API
namespace.
cPanel & WHM treats all of the modules in the /usr/local/cpanel/Cpanel/API/
directory as UAPI modules.
We recommend that you only save module files (.pm
) to this location. The presence of other files may cause problems, even if the files relate to your custom modules.
- Add functions to your module.
- A single module generally contains many functions.
- You can cause functions to only work with certain feature lists.
- Thoroughly test your module on a non-production server.
Additional resources
For more information about how to write Perl modules, we recommend the following resources:
- The perlmonks.org Simple Module Tutorial.
- Perl.org's perlmodstyle documentation.
- Perl.org's perlnewmod documentation.
Create your module
To create a custom module, you must first create the Module.pm
file.
Make certain that you thoroughly test custom modules before you install them to production servers.
The Module.pm file
Save your custom module as the /usr/local/cpanel/Cpanel/API/Module.pm
file, where Module
represents the module's name.
- We recommend that you use a CamelCase module name.
- UAPI modules cannot use the same name as an existing UAPI module.
-
UAPI module names should
not
begin with an underscore (
_
).
We recommend that you begin with the following file template:
package Cpanel::API::Module;
use strict;
our $VERSION = '1.0';
# Your comments about this custom module.
# Cpanel Dependencies
use Cpanel ();
use Cpanel::API ();
use Cpanel::Locale ();
use Cpanel::Logger ();
# Other dependencies go here.
# Defaults go here.
# Constants go here.
# Globals
my $logger;
my $locale;
# Caches go here.
# Functions go here.
1;
Package the module
package Cpanel::API::Module;
This declaration instructs Perl to treat all of the file's functions as a part of the Cpanel::API::Module
namespace.
For more information, read perldoc.perl.org's package documentation.
Set the strict pragma
use strict;
This declaration instructs Perl to return errors if the file contains potentially unsafe code.
For more information, read perldoc.perl.org's strict documentation.
Declare a module version
our $VERSION = '1.0';
This declaration creates the variable $VERSION
and sets it to 1.0
. This allows you to differentiate between this and future versions of your module.
cPanel dependencies
# Cpanel Dependencies
use Cpanel ();
use Cpanel::API ();
use Cpanel::Locale ();
use Cpanel::Logger ();
While UAPI calls do not require that you include these dependencies, we recommend that you include them.
For more information, read perldoc.perl.org's use documentation.
If you include the use Cpanel::API
statement, your functions can call functions from any other custom or cPanel-provided UAPI module. Remember that those UAPI functions may have additional feature list requirements.
Additional dependencies, defaults, and constants
# Other dependencies go here.
# Defaults go here.
# Constants go here.
# Globals
my $logger;
my $locale;
# Caches go here.
Use the lines below the Cpanel::
dependencies to declare dependencies on additional Perl modules, declare default values for variables, set constant values, and set caches.
UAPI modules that use the Cpanel::Logger
and Cpanel::Locale
objects should also declare the $logger
and $locale
global variables.
Functions
# Functions go here.
Module files must contain at least one function.
For more information, read our Custom Function Basics documentation.
End the module file
End your module file with the following line:
1;
Perl requires that module files return a true
value in order to function. This line fulfills that requirement.
Custom Function Basics
Custom modules contain one or more individual functions.
Make certain that you thoroughly test custom modules before you install them to production servers.
Functions
Write all of the functions for a custom module in the same Module.pm
file.
The examples below use the following variables:
-
Module
— The custom module's name. -
function
— The name of a function in the custom module.
For each function that you wish to include in your module, we recommend the following format and elements:
#-------------------------------------------------------------------------------------------------
# Name:
# function - Choose a function name that describes the function's action.
# Desc:
# A description of the function function's action.
# Arguments:
# $arg1 - string - A description of the $arg1 parameter.
# Returns:
# $result1 - string - A description of the $result1 parameter.
#-------------------------------------------------------------------------------------------------
sub function {
my ( $args, $result ) = @_;
my ( $arg1, $arg2 ) = $args->get( 'arg1', 'arg2' );
# (Optional) Set a feature that the cPanel user must have in order to access the function.
my $feature = 'featurename';
if ( !main::hasfeature($feature) ) {
$result->error( '_ERROR_FEATURE', $feature );
return;
}
# Make the function unusable if the cPanel account is in demo mode.
if ( $Cpanel::CPDATA{'DEMO'} ) {
$result->error( '_ERROR_DEMO_MODE', $feature );
return;
}
# Validate the required parameters.
# Sanitize the arguments.
# Perform the function's action(s).
# Build the results.
if ($success) {
$result->data($successful_data);
return 1;
}
else {
return 0;
}
}
Function information
#-------------------------------------------------------------------------------------------------
# Name:
# function - Choose a function name that describes the function's action.
# Desc:
# A description of the function function's action.
# Arguments:
# $arg1 - string - A description of the $arg1 parameter.
# Returns:
# $result1 - string - A description of the $result1 parameter.
#-------------------------------------------------------------------------------------------------
We strongly encourage you to include a summary of each function in the form of comments. This practice is beneficial both to your future self, and to other developers who may use your code.
The function subroutine
sub function {
Write each function in a UAPI module as a subroutine.
- We recommend that you use lowercase function names.
-
If your function name includes multiple words, separate each word with an underscore (
_
) for readability. -
UAPI considers functions with names that begin with an underscore (
_
) to be private functions.- You cannot call these functions through UAPI.
- These functions will not appear in cPanel's API Shell interface ( cPanel >> Home >> Advanced >> API Shell ).
For more information about subroutines in Perl, read perldoc.perl.org's perlsub documentation.
Get arguments from @_
We strongly recommend that all custom functions begin with this line of code. Functions that do not perform this action will experience errors.
my ( $args, $result ) = @_;
This code declares the $args and $result variables, and assigns values from @_.
-
The
Cpanel::Args
object allows UAPI calls to receive named parameters. -
The
Cpanel::Result
object allows UAPI calls to return function data.
Use the get() method to assign variables
my ( $arg1, $arg2 ) = $args->get( 'arg1', 'arg2' );
This code assumes that the arg1
and arg2
input parameters exist. It uses the Cpanel::Args
object's get()
method to assign these parameters' values to the $arg1
and $arg2
variables.
Require a feature
You can choose to require specific features in order to call the function. Replace featurename
with the name of the feature to require.
# (Optional) Set a feature that the cPanel user must have in order to access the function.
my $feature = 'featurename';
if ( !main::hasfeature($feature) ) {
$result->error( '_ERROR_FEATURE', $feature );
return;
}
This if statement uses built-in cPanel & WHM functionality to check whether the account has access to the specified feature. If the cPanel user does not have the access to the required feature, the function will return an error message and will not perform any other actions.
For example, the following code requires that a cPanel user has the filemanager
feature in order to call the function:
my $feature = 'filemanager';
if ( !main::hasfeature($feature) ) {
$result->error( '_ERROR_FEATURE', $feature );
return;
}
Disallow demo mode
In most cases, you should not allow your custom module to function on cPanel accounts that are in demo mode.
# Make the function unusable if the cPanel account is in demo mode.
if ( $Cpanel::CPDATA{'DEMO'} ) {
$result->error( '_ERROR_DEMO_MODE', $feature );
return;
}
This if statement uses built-in cPanel & WHM functionality to check whether the cPanel account is a demo account. If a demo cPanel account attempts to call your function, the function call with return an error message and will not perform any other actions.
Perform the desired actions
# Validate the required parameters.
# Sanitize the arguments.
# Perform the function's action(s).
This section of the subroutine is where your function performs its own unique actions.
These actions could combine any of Perl's many functions. Often, this includes the following actions:
- Validate the data that you passed into variables in line 13.
- Sanitize this data (for example, use the chomp function to remove trailing newlines).
- Check data in other files .
- Write data to other files .
Result data and returns
At the end of your function, you can use the Cpanel::Result
object's data()
method to assign values to a hash or array of hashes of named output parameters.
- Output in an array of hashes allows you to use UAPI's filter, sort, and pagination options.
-
The only meaningful return values in Perl are
1
(for success) and0
(for failure). -
While Perl allows bare
return
values, we do not recommend that you use them in UAPI functions. In some circumstances, the system may misinterpret barereturn
values as true.
# Build the results.
if ($success) {
$result->data($successful_data);
return 1;
}
else {
return 0;
}
}
This example code assumes that, at some point during the function's actions, the subroutine initialized and assigned values to the $success
and $successful_data
values.
In line 35, this example feeds the $successful_data
value into the data hash, to return output parameters. The API also returns the standard UAPI metadata.
If your return data contains any strings with Unicode characters that are binary encoded, and that display on a cPanel interface, you will receive a Wide Character warning. To resolve this, use the following code to encode your strings:
use Encode qw(encode);
$result->data( encode( 'utf-8', $successful_data ) );
The cPanel Args object
UAPI modules use the Cpanel::Args
object to receive arguments (input parameters). When you write a custom UAPI module, you must use this object for your functions to operate correctly.
For more information about methods in Perl, read perl.org's perlobj documentation.
Required $args declaration
Before you can use Cpanel::Args
methods, you must declare the $args
variable, as in the following example:
sub custom_function {
my ( $args, $result ) = @_;
}
This example declares the $args
and $result
variables, and assigns values from the input parameters that the function received. We strongly recommend that you begin all custom functions with the my ( $args, $result ) = @_;
declaration. Functions that do not perform this action will experience errors.
For more information about the Cpanel::Result
object, read the Cpanel::Result
Object section below.
Methods
The Cpanel::Args
object includes methods that you can use to incorporate input parameter values into your function call.
$args->exists()
This method checks whether a named parameter exists. Use this method, for example, to ensure that a value exists for an input parameter before you attempt to perform the function's action.
# Check whether the param1 input parameter exists.
$args->exists('param1');
In this example, the exists
method checks whether a value exists for the param1
input parameter.
-
If the
param1
parameter exists, the method returns true (1
). -
If the
param1
parameter does not exist, the method returns false (0
).
This method returns true
if the parameter exists with a null or blank value.
$args->get()
This method retrieves one or more named parameters. We recommend that you use this method to assign values from optional input parameters.
# Assign param1's value to $arg1 and param2's value to $arg2.
# The param1 and param2 input parameters are optional.
my($arg1, $arg2) = $args->get('param1', 'param2');
This example assigns the param1
parameter's value to the $arg1
variable, and the param2
parameter's value to the $arg2
variable.
This method does not return runtime errors if the method attempts to assign a value from a nonexistent parameter.
- For this reason, we recommend that you do not use this method with required parameters.
-
To check whether a parameter exists and then return the value or an error message, use the
get_required()
method.
$args->get_required()
This method checks whether a named parameter exists.
- If the parameter exists, the method returns that parameter and its value.
- If it does not exist, the method returns a predetermined error message.
We recommend that you use this method to assign values from required input parameters that could have a blank value.
# Assign param1's value to $variable.
# Returns an error if param1 does not exist.
# No error if param1's value is blank.
my ($variable) = $args->get_required('param1');
This example uses the get_required
method to check whether the param1
parameter exists, and then assigns the parameter and its value to the $variable
variable.
This method does not return an error if the parameter exists with a null or blank value.
$args->getlengthrequired()
This method checks whether a named parameter exists, and ensures that it is not a blank or null value.
- If the parameter exists and has a value, the method returns that parameter and its value.
- If it does not exist, has a blank value, or has a null value, the method returns a predetermined error message.
We recommend that you use this method to assign values from required input parameters that must not be empty.
# Assign param1's value to $variable.
# Returns an error if param1 does not have a value or is empty.
my ($variable) = $args->get_length_required('param1');
This example uses the get_length_required
method to check whether the param1
parameter exists and has a valid value, and then assigns the parameter and its value to the $variable
variable.
$args->add()
This method adds a key=value
pair to the currently available named parameters. Use this method, for example, to introduce additional parameters from another subroutine.
$args->add('parameter_name','value');
In this example, the add
method adds the parameter_name
parameter, and assigns it a value of value
.
$args->keys()
This method retrieves all of the current named parameters. Use this method to assign all of the named input parameters to an array, without the need to explicitly name each parameter.
my $value = $args->keys();
In this example, the keys
method assigns all of the available named parameters and their values to the $value
variable.
The cPanel Result objects
UAPI modules use the Cpanel::Result
object to return messages and data. When you write a custom UAPI module, you must use this object for your functions to operate correctly.
For more information about methods in Perl, read perl.org's perlobj documentation.
Required $result declaration
Before you can use Cpanel::Result
methods, you must declare the $result
variable, as in the following example:
sub custom_function {
my ( $args, $result ) = @_;
}
This example declares the $args
and $result
variables, and assigns values from the input parameters that the function received.
We strongly recommend that you begin all custom functions with the my ( $args, $result ) = @_;
declaration. Functions that do not perform this action will experience errors.
If your return data contains any strings with Unicode characters that are binary encoded, and that display on a cPanel interface, you will receive a Wide Character warning. To resolve this, use the following code to encode your strings:
use Encode qw(encode);
$result->data( encode( 'utf-8', $successful_data ) );
For more information about the Cpanel::Args
object, read the Cpanel::Args Object
documentation above.
Methods
The Cpanel::Result
object includes methods that you can use to return messages and data through UAPI.
$result->data()
This method stores data to include in the function's return data. Use this method to return the data hash for custom functions.
You can use the data()
method to store individual values. However, we recommend that you instead use this method to store hashes of named parameters.
$result->data(@array_of_data);
In this example, the data method stores an array of function data. This data will appear in the data hash in the function's metadata.
Do not use this method more than once in each function. If a function uses the data()
method a second time, it will overwrite all of the data that it previously stored.
$result->error()
This method stores an error message to include in the function's return data. Use this method to return error messages in custom functions.
If you call this method multiple times in the same function, it appends the new error messages to the list that it previously stored.
$result->error('This is an error message about the function.');
In this example, the error
method stores an error message. This message will appear in the errors
hash in the function's metadata.
- This method attempts to localize any message that a function passes to it.
- For this reason, do not attempt to interpolate data into a string that you pass to this method.
- The strings that you use with this method must be exact string literals.
-
To include interpolated data in an error message, use the
raw_error()
method.
$result->raw_error()
This method stores an error message to include in the function's return data. Use this method to return error messages in custom functions.
If you call this method multiple times in the same function, it appends the new error messages to the list that it previously stored.
$result->raw_error('This is an error message about the [_1].', '$function');
In this example, the raw_error
method stores an error message. This message will appear in the errors
hash in the function's metadata.
This method does not attempt to localize strings, and therefore is safe to use with interpolated data.
$result->message()
This method stores a message to include in the function's return data. Use this method to return messages of success, or additional function information.
If you call this method multiple times in the same function, it appends the new messages to the list that it previously stored.
$result->message('This is a message of success about the function.');
In this example, the message
method stores a success message. This message will appear in the messages
hash in the function's metadata.
- This method attempts to localize any message that a function passes to it.
- For this reason, do not attempt to interpolate data into a string that you pass to this method.
- The strings that you use with this method must be exact string literals.
-
To include interpolated data in an error message, use the
raw_message()
method.
$result->raw_message()
This method stores a message to include in the function's return data. Use this method to return messages of success, or the function's metadata
If you call this method multiple times in the same function, it appends the new messages to the list that it previously stored.
$result->raw_message('This is a message of success about the function.');
In this example, the raw_message
method stores a success message. This message will appear in the messages
hash in the function's metadata.
This method does not attempt to localize strings, and therefore is safe to use with interpolated data.
$result->metadata()
This method stores metadata to include in the function's return data.
$result->metadata('metadata_var', '1');
This example adds the metadata_var
parameter to the hash of metadata, with a value of 1
. This message will appear in the metadata
hash in the function's metadata.
In most instances, custom modules will not need to use this method.