A Custom Server for Shottr

I wrote a PHP script to act as custom cloud server for receiving and storing screenshots from shottr

Created: by Pradeep Gowda Updated: Nov 04, 2023 Tagged: php · utility · chatgpt

Shottr is a screenshotter, annotation tool for MacOS. One of the features available for “Friends of the Proejct” (a paid tier) is the ability to upload the screenshot to their cloud. While handy, I want to own my data.

The developer of this application supports that option via setting a custom web server via command line.

I wrote a simple PHP web application to act as the server that will receive the upload and save it to a directory.

I have modified nginx so that the screenshot can be served from under the screenshots directory on this website.

The PHP code is given below as reference. I wrote most of this with the help of GPT.

Notes:

  • The uploaded image filenames are a base58 representation of the timestamp.
  • The screenshot captured by the Shottr app is uploaded to the server by pressing Command-e
<?php
// Define the destination directory
$uploadDirectory = '/var/www/www.yoursite.com/screenshots/';
// Image Directory
$imageUrlBase = "https://www.yoursite.com/screenshots/";
// Log the information to a log file
$logFile = '/tmp/fileuploader.txt';
//timestamp
$timestamp = date('Y-m-d H:i:s');
$now = date("YmdHis");


// https://www.darklaunch.com/base58-encode-and-decode-using-php-with-example-base58-encode-base58-decode.html
function base58_encode($num) {
    $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $base_count = strlen($alphabet);
    $encoded = '';

    while ($num >= $base_count) {
        $div = $num / $base_count;
        $mod = ($num - ($base_count * intval($div)));
        $encoded = $alphabet[$mod] . $encoded;
        $num = intval($div);
    }

    if ($num) {
        $encoded = $alphabet[$num] . $encoded;
    }

    return $encoded;
}


// Function to log data to the file
function logData($data) {
    global $logFile;
    global $timestamp;

    // Get the current timestamp
    $timestamp = date('Y-m-d H:i:s');

    // Format the data
    $logData = "[$timestamp] " . $data . PHP_EOL;

    // Append the data to the log file
    file_put_contents($logFile, $logData, FILE_APPEND);
}

// Check if a file was uploaded
if (!isset($_FILES['file'])) {
    echo "ERR: No file uploaded.";
    exit;
}

// Get the uploaded file details
$file = $_FILES['file'];
$fileName = $file['name'];
$tmpFilePath = $file['tmp_name'];
$fileContent = file_get_contents($tmpFilePath);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$newFileName = base58_encode($now) . '.' . $extension;
$target = $uploadDirectory .$newFileName;

try {
    copy( $tmpFilePath, $target);
    unlink($tmpFilePath);
} catch (Exception $e) {
    $msg = "ERR: Failed to move the uploaded file - " . $e->getMessage() . PHP_EOL;
    echo $msg;
    unlink($tmpFilePath);
    exit;
}


$logData = "Client IP=" . $_SERVER['REMOTE_ADDR'] . " Filename=" . $newFileName . PHP_EOL;
logData($logData);
$imageURL =  $imageUrlBase . $newFileName;
echo "SUCCESS: " . $imageURL;
?>

The corresponding nginx config is:

    location /screenshots {
        alias /var/www/www.yoursite.com/screenshots;
    }