All right, just for other people who would be interested, I hacked this little PHP snippet together - really copy and pasty, but it seems to work (I bypassed the machine ID stuff):
<?php /** PHP script that creates an unlock file for the Tracktion Marketplace Status. */ /** Variables */ $PRODUCT_ID = "YOUR PRODUCT"; $EMAIL = "YOUR EMAIL"; $USER = "YOUR NAME"; $DATE = date("j M Y g:i:sa"); $MACHINE = "BYPASS"; $TIME = dec2hex(round(microtime(true)*1000)); $PRIVATE_KEY_PART_1 = "742ccf57e16f84bb"; // These are stupid 64bit keys for developing, but it should run with big keys too... $PRIVATE_KEY_PART_2 = "ae4337057c0e3f6f"; header('Content-Description: File Transfer'); header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename='.$PRODUCT_ID.'.licence'); header('Content-Transfer-Encoding: UTF-8'); header('Expires: 0'); /** Helper Functions */ function dec2hex($number) { $hexvalues = array('0','1','2','3','4','5','6','7', '8','9','a','b','c','d','e','f'); $hexval = ''; while($number != '0') { $hexval = $hexvalues[bcmod($number,'16')].$hexval; $number = bcdiv($number,'16',0); } return $hexval; } include ('Math/BigInteger.php'); // get this from: phpseclib.sourceforge.net function applyToValue ($message, $key_part1, $key_part2) { $result = new Math_BigInteger(); $zero = new Math_BigInteger(); $value = new Math_BigInteger (strrev ($message), 256); $part1 = new Math_BigInteger ($key_part1, 16); $part2 = new Math_BigInteger ($key_part2, 16); while (! $value->equals ($zero)) { $result = $result->multiply ($part2); list ($value, $remainder) = $value->divide ($part2); $result = $result->add ($remainder->modPow ($part1, $part2)); } return $result->toHex(); } // Create the comment section echo "Keyfile for ", $PRODUCT_ID, "\n"; echo "User: ", $USER, "\n"; echo "Email: ", $EMAIL, "\n"; echo "Machine numbers: ", "\n"; echo "Created: ", $DATE, "\n"; echo "\n"; // Create the XML $dom = new DOMDocument("1.0", "utf-8"); $root = $dom->createElement("key"); $dom->appendChild($root); $root->setAttribute("user", $USER); $root->setAttribute("email", $EMAIL); $root->setAttribute("mach", $MACHINE); $root->setAttribute("app", $PRODUCT_ID); $root->setAttribute("date", $TIME); $XML_STRING = $dom->saveXML(); $ENCRYPTED_XML = "#" . applyToValue($XML_STRING, $PRIVATE_KEY_PART_1, $PRIVATE_KEY_PART_2); $XML_DATA = chunk_split($ENCRYPTED_XML, 70); echo $XML_DATA; ?>
This is the TracktionMarketplaceStatus subclass:
class Unlocker: public TracktionMarketplaceStatus { public: Unlocker(): state(String::empty) {} String getMarketplaceProductID() { return PRODUCT_ID; } RSAKey getPublicKey() override { return RSAKey(PUBLIC_KEY); } String getState() override { return state; }; StringArray getLocalMachineIDs() override { StringArray sa; sa.add("BYPASS"); return sa; }; void saveState(const String &s) override { state = s; } private: String state; };
This is all far from being finished, but it may be a good starting point for other people who want to use the module on their web host.