# Technical documentation — public-procon8.co.za

Evidence date: 2026-10-06. Source revision: `f3f3b6d` on `master` (2020-08-27).

## Architecture

The site is a classic PHP page with one shell and included fragments. There is no framework, no router, and no database.

```text
index.php
  common_functions.php
    content.php          static $everything (menu + sidebars)
  js/nav.js              show/hide .pbox
  js/galleryscript.js    fadeshow
  js/jq.min.js           jQuery 1.9.1
  include aboutus.php, contactus.php, Overview.php,
          project_control.php, contract_management.php,
          specialist_services.php, dbr.php, reference_projects.php

contactus.php  --POST-->  thanks.php
                              |-- file_get_contents Google siteverify
                              |-- PHPMailer SMTP --> SES eu-west-1
```

`SLA.php`, `disclaimer.html`, `gdform.php`, `webformmailer.php`, and `cgi/*.cgi` sit beside that path and are not included by `index.php`.

## Application structure

| Path | Role |
|---|---|
| `index.php` | Shell. Gzip handler, error reporting, home HTML, includes |
| `content.php` | Class `content`, static array `$everything` |
| `common_functions.php` | Class `kwassie extends content` |
| `aboutus.php`, `Overview.php`, `project_control.php`, `contract_management.php`, `specialist_services.php`, `dbr.php`, `reference_projects.php`, `contactus.php` | Fragments. Each includes `common_functions.php` again (`include_once`) |
| `thanks.php` | Form handler. Not a fragment |
| `recaptchalib.php` | Widget helper plus unused legacy verify functions |
| `SLA.php` | Full HTML page and iframe |
| `disclaimer.html` | Static disclaimer |
| `css/style.css`, `fonts.css`, `fonts/` | Presentation |
| `images/` | Slides, logos, page images |
| `js/` | jQuery, nav, slideshow |
| `vendor/` | Third-party PHP, committed |
| `php.ini` | PHP settings file in the web root |
| `.htaccess` | Empty |
| `.errordocs/`, `missing.html` | GoDaddy-style error documents |
| `cgi/gdform.cgi`, `cgi/gdformssl.cgi`, `gdform.php`, `webformmailer.php` | Legacy form dumpers |
| `*.bak` | Copies. `index.php.bak` matches `index.php`. The other three differ |
| `.project`, `.buildpath`, `.settings/` | Eclipse PHP project named `www.procon8.co.za` |

`content.php` and `common_functions.php` headers say package "Common Functions", author Jean Thirion, copyright 2014 PROCON8, version id dated 2014-12-10. The license URL in the header is `http://www.procon8.com/licenses/dppr-license.php`. That URL is not a file in this repository. What the license text says is **Unknown**.

## Languages and libraries

| Piece | Version evidence |
|---|---|
| PHP | No pin in the repo. AWS SDK composer.json requires PHP `>= 5.3.3`. PHPMailer requires PHP `>= 5.0.0`. Application code uses PHP 5 style (`var` properties in the reCAPTCHA library, `each()`, and `split()` inside `webformmailer.php`). `split()` was removed in PHP 7, so that unused mailer would not run on PHP 7+. Host version is Unknown |
| jQuery | 1.9.1, file header in `js/jq.min.js` |
| PHPMailer | `public $Version = '5.2.27'` in `vendor/phpmailer/phpmailer/class.phpmailer.php`. Loaded by `vendor/autoload.php` and `PHPMailerAutoload.php` |
| AWS SDK for PHP | `Aws\Common\Aws::VERSION` is `2.8.31`. Not referenced by application pages |
| Guzzle | 3.x, required by that SDK (`guzzle/guzzle ~3.7`) |
| Symfony EventDispatcher | Vendored under `vendor/symfony/event-dispatcher`, a Guzzle-era dependency |

There is no root `composer.json` or `composer.lock`. `vendor/` is the dependency record.

## Request lifecycle

1. The web server maps a `.php` URL to that file. No rewrite rules are in the empty root `.htaccess`.
2. `index.php` starts `ob_gzhandler`, sets `error_reporting` to `E_ERROR`, `display_errors` to 0, and builds the page.
3. For menu index 1 it prints the home panel with `display: block`. For every later menu row it prints a hidden `.pbox` and `include`s the href (`aboutus.php`, and so on).
4. `js/nav.js` binds clicks on `#navigation` and `#footernav`.
5. If `show` is in the query string, an inline script also runs on ready and tries to show that id.

`thanks.php` is requested directly as the form action. It does not go through `index.php`.

## Data

No application database, schema, migration, or seed exists.

Contact data exists only inside the outbound email. Legacy `gdform.php` would write tagged text files to `DOCUMENT_ROOT/../data/gdform_<unix time>` if something posted to it. `webformmailer.php` would write under `/home/content/.../data/` when `SPI` is set. Neither is the contact form's action.

## External interfaces

### Google reCAPTCHA

- Widget: `recaptcha_get_html` returns a script tag for `https://www.google.com/recaptcha/api.js` and `<div class="g-recaptcha" data-sitekey="...">`.
- Verify: `thanks.php` POSTs `secret` and `response` to `https://www.google.com/recaptcha/api/siteverify` using `file_get_contents` and a stream context. It does not send the remote IP.
- The site key and secret are hardcoded. A previous key pair remains in comments and in `thanks.php.bak`. This document does not repeat the key material.
- `recaptcha_check_answer` still posts to the legacy `www.google.com` verify endpoint. `thanks.php` does not call it. `thanks.php.bak` does.

### Amazon SES

`thanks.php` settings that are safe to record:

| Setting | Value |
|---|---|
| Host | `email-smtp.eu-west-1.amazonaws.com` |
| Port | 587 |
| Encryption | `tls` |
| Auth | SMTP auth on |
| To / `setFrom` address | `support@procon8.com` |
| Configuration-set header | `X-SES-CONFIGURATION-SET: ConfigSet_www_procon8_co_za` |
| Library | PHPMailer 5.2.27, `isSMTP()`, `isHTML(true)` |

The SMTP username and password are hardcoded in `thanks.php`. They are live secrets in Git. They are not copied here. Human review should rotate them and remove them from the tree and from history.

The AWS SDK in `vendor/` is not used for this send.

### LinkedIn

`index.php` loads `//platform.linkedin.com/in.js` and an `IN/FollowCompany` tag with `data-id="2761141"`.

### Quantivia and the dashboard

- `http://www.quantivia.com` from `dbr.php`.
- `SLA.php` iframe: `http://www.procon8.co.za:9090/publishPage.do?method=getPublishedDashboard&pagekey=0656059555200eb796972296434984a9` (plain HTTP, port 9090). Product behind `publishPage.do` is Unknown.

### Reference links

Ordinary `<a target="_blank">` URLs in `reference_projects.php`. No tracking parameters were added by the application.

## Authentication and sessions

None. No `session_start`, cookies set by application PHP, or password checks.

The contact form's reCAPTCHA is the only gate in front of mail.

## Background work, queues, storage, monitoring

None in the repository. No cron, worker, queue client, object storage, health check, or analytics snippet.

`php.ini` sets `SMTP = 127.0.0.1`. The live mailer does not use PHP `mail()`, so that directive does not affect `thanks.php`. The backup mailer would.

`php.ini` also enables `extension=imap.so`. No application file calls IMAP functions.

## Security observations

These are facts about the tree, for human review. This document does not include secret values or exploit steps.

1. SES SMTP credentials are committed in `thanks.php`. An older reCAPTCHA secret is committed in `thanks.php.bak`. The live reCAPTCHA secret is committed in `thanks.php`. The site key is also in `contactus.php` (site keys are exposed to browsers by design).
2. `index.php` and `SLA.php` place `$_GET['show']` inside a `<script>` string with no encoding.
3. The contact form's client check does not match the field names, and the server does not require the fields.
4. `thanks.php` shows PHPMailer's `ErrorInfo` to the browser on failure.
5. `gdform.php` and the CGI scripts write request bodies to disk if invoked. `webformmailer.php` refuses to run unless `$_SERVER['SPI']` is set, then writes fields to disk.
6. Root `.htaccess` is empty. `php.ini` turns `expose_php` off and leaves `disable_functions` commented out, so it does not disable `exec` or `shell_exec`. `webformmailer.php` calls `escapeshellcmd` on field names and values while building a CSV line that is written to a file, not passed to a shell.
7. The LinkedIn script and several outbound links are `http://` or protocol-relative. The SLA iframe is `http://` on port 9090.
8. `allow_url_fopen` is Off in the committed `php.ini`, while `thanks.php` needs it for `siteverify`. If that ini is active, the contact handler cannot complete verification.

## Hosting clues

Nothing declares the current host.

Clues that the tree was once on GoDaddy shared hosting:

- `missing.html` loads CSS from `p3nlhclust404.shr.prod.phx3.secureserver.net`.
- `gdform.php`, `webformmailer.php`, and `cgi/gdform*.cgi` match GoDaddy's form-mail layout, including the `SPI` check and `/home/content/.../data/` paths.
- A `php.ini` in the web root and `.errordocs/` match that style of account.
- `.hcc.thumbs/` is a host thumbnail cache.

Clues from 2020:

- The import commit was authored on `ip-10-20-1-5.eu-west-1.compute.internal`.
- Mail is aimed at SES in `eu-west-1`.

Which of those is production now is **Unknown / Requires Confirmation**.

## Configuration

| File | Effect if the host actually loads it |
|---|---|
| `php.ini` | `register_globals` off, `allow_url_fopen` off, `expose_php` off, `max_input_time` 60, `variables_order` EGPCS, `upload_tmp_dir` `/tmp`, `precision` 12, SMTP `127.0.0.1`, `extension=imap.so`. Zend Optimizer block is commented. `disable_functions` is commented |
| `.htaccess` | No directives |
| `.errordocs/.htaccess` | `AddType text/html .html`, `AddHandler default-handler .html`, `AddOutputFilter INCLUDES .html` |
| Eclipse `.settings/org.eclipse.php.core.prefs` | Include path `0;/www.procon8.co.za`, timestamp Wed Dec 10 22:13:56 CAT 2014 |

No `.env`. Secrets are PHP string literals.

## Development and testing

- IDE metadata is Eclipse PHP (`.project` nature `org.eclipse.php.core.PHPNature`).
- No PHPUnit (or other) tests for the site. Vendor packages contain their own tests; those are library tests.
- No Bitbucket Pipelines file, Dockerfile, or README.
- Local run expectation, **inferred**: PHP with short files served from the repository root as the document root. `thanks.php` then needs outbound HTTPS and valid SES credentials. That has not been executed as part of this documentation pass.

## Git

| Item | Value |
|---|---|
| Remote | `git@bitbucket.org:overdrive/public-procon8.co.za.git` |
| Default branch | `master` |
| Only commit | `f3f3b6d83db19fcc57ec28ce685752147c316296` |
| Date | 2020-08-27 08:45:06 +0000 |
| Subject | initial commit of full repository |
| Author | `root <root@ip-10-20-1-5.eu-west-1.compute.internal>` |

No `.gitignore`. `vendor/` and `.bak` files are part of the commit.

## Related products

This repository links to Quantivia and describes it. Quantivia's own codebase is not here. Silicon Ark documents other Quantivia repositories separately. Those documents were not used as evidence for this site's behaviour.
