Skip to content

Releases: bradleygb/whmcs-cwp-module

v2.5.1 — the dashboard panels filter and page too

Choose a tag to compare

@bradleygb bradleygb released this 02 Sep 21:49

Drop-in as always — extract over modules/servers/cwp7/ and run Test Connection. No
configuration changes and nothing to reconfigure on existing services.

Added

The Domains, Subdomains and Databases panels filter and page, five to a page.

The filter matches on every column, not just the first — a database is as likely to be
looked up by its user as by its name.

Neither the filter nor the pager appears until a panel holds more than five rows, so an
account with three databases looks exactly as it did before.

This follows the same treatment the mailbox list got in 2.5.0, which pages at ten. CWP's
email/list and accountdetail/list both return everything in one response with no
pagination of their own, so the paging is done in the browser.


Full history in CHANGELOG.md.

v2.5.0 — a mailbox list that scales, and terminations that report honestly

Choose a tag to compare

@bradleygb bradleygb released this 02 Sep 21:10

Drop-in as always — extract over modules/servers/cwp7/ and run Test Connection. No
configuration changes, no database changes, nothing to reconfigure on existing services.

Includes everything from 2.3.0 and 2.4.0, which were never tagged.

Added

The mailbox list filters and pages. Ten to a page, with a filter box once there are more
than ten. An account with hundreds of addresses used to render every one of them, and every
row carried a hidden inline editor with three inputs behind it — five hundred mailboxes
meant a thousand table rows and no way to find anything among them.

email/list can't help here: its documented request takes key, action, user and
debug and nothing else, so the whole account arrives in one response and the paging has to
happen in the browser.

Account dashboard in the client area — disk, bandwidth, email accounts, FTP accounts,
databases and subdomains, from accountdetail/list.

Mailbox management from the client area — add, change password, change size, delete,
without sending customers into CWP. Off by default (mailbox_management in config.php);
needs ADD, UPD and DEL on Emails in addition to LIST.

Fixed

A termination that succeeded was reported as a failure. account/del answers
{"status":"OK"} and then appends its panel's HTML confirmation, which json_decode
rejects outright. WHMCS recorded a failed termination and left the service Suspended while
the account had already been deleted from the server.

The parser now takes the first complete JSON object off the front of a reply. It isn't
special-cased to delaccount/susp and account/unsp go through the same CWP
controller.

Suspend, unsuspend and terminate check the server before reporting a failure. If the
account is already gone, already suspended or already active, the request has done what it
was asked to do, whatever CWP said on the way. Absence counts as success for a termination
and as a fault for a suspension, so the two aren't treated alike.

Mailbox passwords and password hashes kept out of the WHMCS module log. email/list
returns every mailbox's {SHA512-CRYPT} hash with no way to suppress it, and email/add
calls the password pass while email/udp calls it password — masking by field name
caught only the first. It's masked by shape now.

The module log no longer stores an entire response body on every call. The client area
fetches the mailbox list on every page view, so a large account wrote hundreds of rows into
tblmodulelog each time somebody opened their service page. Bodies cap at 4000 bytes and
payload rows at 20, each saying how much was left out.

CWP API notes

Worked out the hard way against a live server, in case they save someone else the time:

  • email/add takes the local part only in its email field, not the whole address —
    CWP appends the domain itself. Send test@domain.co.za and you get
    testdomain.co.za@domain.co.za.
  • email/udp and email/del use mailbox (the full address) and password — not
    email and pass. The wrong names produce an HTTP 500 with Undefined offset: 1.
  • quota is ignored on email/add but applied on email/udp, in bytes.
  • changepack/udp takes a package ID only. A name comes back as a bare Error with no
    message.

v2.1.1 — turn off a resource-limits call the server refuses

Choose a tag to compare

@bradleygb bradleygb released this 23 Aug 08:06

Added

apply_resource_limits in config.php (default on).

The product's inode, open-file and process limits are applied through account/udp after a package change, and a refusal there has always been non-fatal — the package still moves. But some servers refuse that call with Account/UPD granted in API Manager, which put a failed call and a warning into the WHMCS Module Log on every package change, for a grant that could not be obtained.

Set it to false on such a server and the call is not made:

'apply_resource_limits' => false,

The three limits then come from the CWP package alone, and must be set in the panel if they matter.

CWP checks that call internally as accout_upd — its own typo, and the same string the API Manager checkbox saves, so the two do agree. The check itself lives in encoded code, so there is no way to see from outside which condition is failing. If your server refuses it, this is the switch.

Upgrading

Replace the directory contents. No configuration changes are required; the default behaviour is unchanged.

v2.1.0 — package creation from products, and packages by name

Choose a tag to compare

@bradleygb bradleygb released this 23 Aug 07:46

Products can now create their CWP packages, and a package set by name works.

Added

Products can create their CWP packages. Ten new product options describe the package — disk quota, bandwidth, and the FTP, email, email-list, database, subdomain, parked-domain, addon-domain and hourly-email limits. Saving the product creates the package on every CWP server in that product's server group, or updates it if one of that name already exists. No more building the same package by hand on each server.

Off by default — push_packages_on_product_save in config.php. Enabling it decides ownership: WHMCS becomes the source of truth, and a package edited in CWP is overwritten the next time its product is saved. Needs ADD and UPD on Packages.

A limit left blank keeps CWP's own default; set it to 0 to mean none allowed.

The CWP Package field may be left blank, in which case the product's own name is used — both when pushing the package and when provisioning against it.

Fixed

A package change failed whenever the package was set by name. CWP's changepack takes a package id and nothing else — given a name it answers a bare Error with no explanation. Whatever the product holds, name or id, is now resolved against the server's own package list before anything is sent, so a name works and each server in a group can assign that package its own local id.

This replaces the existence check added in 2.0.3, which confirmed the package was real and then sent the unusable form of it anyway. Resolution still fails open on a key without list on Packages, and an unknown package is still refused with the available ones named.

tblservers.accesshash is not encrypted on every install. Where it holds the API key verbatim, running it through DecryptPassword does not fail — it reports success and returns binary noise, which CWP rejects as "No special characters are allowed!". A stored value that already looks like a key is now used as-is.

Upgrading

Replace the directory contents. Nothing else changes — the module type, config option order and stored usernames are all unchanged.

The ten new product options are appended after the existing five, so current settings carry over untouched. Fill them in only if you want package pushing.

Full detail in CHANGELOG.md.

v2.0.3

Choose a tag to compare

@bradleygb bradleygb released this 18 Aug 06:25

Fixed

  • An unknown package ID no longer leaves an account with no package. CWP's
    changepack answers status OK for an ID that does not exist, silently detaching the
    account from any package. The requested ID is now checked against the server's package
    list before anything changes, and a mismatch is refused with the valid IDs listed.
    Applies to account creation as well.

    The check needs Packages/list and fails open without it, so it never blocks a
    package change that would otherwise succeed.

Changed

  • The Change Package button is hidden while apply_package_on_service_save is on,
    since the Product/Service dropdown then does the same job. Hidden, not removed: WHMCS
    draws the button because cwp7_ChangePackage exists, and that function must stay —
    a paid upgrade or downgrade order calls it, and dropping it would bill a customer for a
    package the server never applies. Turning the setting off brings the button back.

v2.0.2

Choose a tag to compare

@bradleygb bradleygb released this 17 Aug 20:34

Security

  • The module log no longer records the client's personal data. WHMCS passes a model
    parameter carrying the service, its product and the full client record; a failed module
    command wrote the stored service password, the customer's name, postal address, phone
    number and last-login IP into the WHMCS Module Log. Logging now uses an allow-list of
    diagnostic fields, so nothing unanticipated is ever written.

Fixed

  • Resource limits were never applied to new accounts. CWP's add endpoint expects
    limit_nofile and limit_nproc; udp calls the same two limits openfiles and
    processes; the module sent nofile and nproc, which neither accepts. Every account
    created by earlier versions therefore carries its CWP package defaults rather than the
    product's open-file and process limits. Run Change Package on existing services to
    apply them.
  • Package changes used the wrong endpoint entirely. CWP has a dedicated
    /v1/changepack for this, gated by the narrow "Account pack change" permission. The
    module posted to /v1/account with action=udp — a full account update, checked as a
    broader grant — and with the package suffixed 12@ where that endpoint documents a
    @12 prefix. Package changes now go to changepack, which takes the bare ID.
  • Account/upd is no longer required. The product's inode, open-file and process
    limits are applied through it after the package moves, but a refusal is non-fatal, so a
    key holding only "Account pack change" changes packages successfully.
  • A package change is now verified. status OK is not evidence, so the account is
    re-read afterwards and the operation fails loudly if CWP did not move it.
  • Account creation no longer times out at 20 seconds. Reads keep the short budget;
    anything that changes the server gets provision_timeout, 180 seconds by default.
    Creating an account builds a user, home directory, vhost, DNS zone and mail
    configuration, and takes far longer than a read.
  • A creation that times out is reconciled. CWP keeps working after the module gives
    up, which previously left an account on the server and a failed service in WHMCS. The
    account is now re-checked, and a creation that finished late is reported as the success
    it was.
  • Error messages carry only advice that applies: the API Manager guidance appears solely
    for Unauthorized action, a missing account is stated plainly, and the private-address
    note no longer appears on a timeout, where the connection had in fact succeeded.

Added

  • hooks.php — optionally apply a package change to CWP when an admin changes a
    service's Product/Service and saves, instead of pressing Change Package afterwards.
    Off by default; enable apply_package_on_service_save in config.php.

v2.0.1

Choose a tag to compare

@bradleygb bradleygb released this 17 Aug 19:02

Fixed

  • Disk usage was imported as zero for every service. CWP's account/list names the
    field diskused, which was not among the names the module looked for.
  • Disk usage now comes from accountdetail. account/list reports a placeholder
    rather than real consumption — the same account shows diskused => 1 there and
    space_usage => 480715 on accountdetail. Bandwidth and all limits still come from
    the single list call, which reports them accurately.
  • Responses under result are read. Current CWP builds return success payloads under
    result, older ones under msj, and errors under msg. All three are accepted;
    account/list and accountdetail use different keys as the same server.
  • -1 is understood as unlimited and stored as 0, which is how WHMCS reads it. A
    negative limit previously rendered as a negative usage bar.
  • Usage rows are matched to services by primary key rather than by a domain query, so a
    domain shared by two services can no longer have both rewritten.
  • Terminated, cancelled and fraud services no longer trigger API calls. The admin
    service page called CWP on every view for a service whose account no longer exists,
    showing a rejection banner each time; usage import likewise treated dead services as
    candidates, letting one shadow a live service that reused the same domain.
  • A missing account now reads as a plain statement rather than an error banner — that is
    an ordinary state, not a fault.

Added

  • usage_detail_lookup in config.php (default on). The accurate disk figure costs one
    extra API call per account that matches a WHMCS service on that server — accounts
    with no service are skipped before the call is made. Set to false to use the single
    list call and accept the placeholder figure.

v2.0.0

Choose a tag to compare

@bradleygb bradleygb released this 17 Aug 13:07

A full rewrite of the CWP provisioning module. The module name, directory and function
prefix are unchanged, so this drops straight over version 1.7 with no reconfiguration:
server entries and products keep working, and no service needs re-linking.

Requires PHP 7.4–8.3 and WHMCS 8.5–9.0.

Fixed

  • Usage reporting now works. It matched tblhosting.dedicatedip against CWP's
    ip_address, but dedicatedip is empty for every shared-IP account, so the query
    matched no rows. It now scopes by server ID and domain, as WHMCS documents.
  • Invalid lastupdate timestamps. Usage rows were written with
    date('Y-m-d H:i:S') — capital S is PHP's English ordinal suffix, producing values
    like 14:30:th, which MySQL rejects in strict mode. Now written with now().
  • ChangePassword sent a misspelled acction field, so the action never reached
    CWP and the endpoint ran on its default behaviour.
  • Fatal TypeError in the daily cron. count() was called on the API payload
    without checking it was an array; on PHP 8 a missing or renamed key aborted the cron
    run. All cron-facing paths are now exception-safe.
  • curl_errno() was checked before curl_exec(), so transport errors were never
    reported.
  • Module functions could return an array where WHMCS expects a string, producing
    "Array to string conversion" instead of a usable error.
  • cURL handles are closed on every path.

Security

  • TLS verification is enabled. Previously CURLOPT_SSL_VERIFYPEER and
    CURLOPT_SSL_VERIFYHOST were disabled on every call, while the request body carried
    an API key with administrative scope over every account on the server.
  • The API key is no longer written to the WHMCS Module Log in plaintext. It is
    masked in the request, passed to WHMCS's redaction, and stripped from CWP's own error
    text — CWP echoes the submitted key back inside Unauthorized action responses.
  • Autologin tokens are no longer rendered into page HTML. A live session URL was
    minted on every product-details page load and printed into the page, leaving it in
    page source, browser history and referrer headers. Sessions are now minted on click
    through WHMCS single sign-on.
  • Redirects are not followed and the transport is pinned to HTTPS, so a redirect cannot
    replay the API key to another host.
  • Client-facing errors no longer carry raw CWP output, which can name other accounts and
    filesystem paths.

Added

  • MetaData — display name, API version, default port, single sign-on label.
  • TestConnection, with failure messages that distinguish DNS, refused connections,
    timeouts and certificate faults, and name the address actually dialled.
  • ServiceSingleSignOn for panel login from the client area and admin service page.
  • ListAccounts for Server Sync, so existing CWP accounts can be listed and imported.
  • AdminServicesTabFields showing live account detail on the admin service page.
  • Renew as an explicit no-op.
  • Client area overview output that makes no API call during page render.
  • Product options for resource limits and a username length cap.
  • Optional config.php for TLS policy, ports and timeouts.
  • Support for both msg and msj response keys, which CWP has used at different times.

Changed

  • Usernames are corrected to CWP's rules for new accounts only, and the corrected
    value is written back to the service. Existing accounts are addressed exactly as
    stored, so services created by earlier versions are unaffected.
  • AdminLink is a plain link to the CWP admin panel; it previously submitted an empty
    form with no credentials.
  • Config option labels use FriendlyName. Option order is unchanged, so existing
    product settings carry over.

Removed

  • AutoSSL triggering. CWP issues and renews AutoSSL certificates on its own schedule, so
    the module does not call it and the API key needs no AutoSSL permission.