PLUSNative: Manual Activation (Offline Method)

When Internet access is not available and online activation is not possible, manual activation is the recommend method for activating an installation and obtaining a license file from SOLO Server. This involves the end-user copying the activation request or saving it to a file that they would take to another computer with Internet access. They would then paste the request or upload the file to SOLO Server's manual request page, which processes the request and generates a response. The end-user must then copy this response or save it to a file and return to the computer they are attempting to activate. Finally, they must paste in the response or point the application to the file. The application can then parse the response and determine which action to take.

The following example demonstrates manually activating an installation, retrieving a license file from SOLO Server, and saving that license file to disk.

Generating and Encrypting the Request

The PLUSNative library has built-in functions for generating requests for the SOLO Server XML Activation Service and XML License File Service web services. Use of these functions avoids having to manually build the web service XML request document. If one finds it necessary, the XML request document can be modified using any of the XML helper functions. For instance, new elements can be added using the SK_XmlElementAddNew function. Once the request has been generated, it must be encrypted and digitally signed.

The following code snippet demonstrates generating the manual activation request:

//declare variables
SK_ResultCode result = SK_ERROR_NONE;
SK_ApiContext context = NULL;
SK_XmlDoc request = NULL;
SK_XmlDoc encryptedRequest = NULL;
char *encryptedRequestString = NULL;
int requestSize = 0;
char *requestFile = "...\ManualActivationRequest.htm";
SK_XmlDoc encryptedResponse = NULL;
SK_XmlDoc response = NULL;
int resultCode = 0;
char *originalSessionCode = NULL;
char *responseSessionCode = NULL;
SK_XmlDoc license = NULL;

//initialize API context (usually called during application start-up)
//refer to the Configuring the API Context topic for instructions

//generate the activation request
result = SK_SOLO_ActivateInstallationGetRequest(context, SK_FLAGS_NONE, 123, "password", NULL, 1000, 1000, FALSE, "My Installation", NULL, &request, &originalSessionCode);

//save the originalSessionCode for later validation

//encrypt/sign the request
result = SK_XmlDocumentEncryptRsa(context, SK_FLAGS_NONE, FALSE, &request, &encryptedRequest);

//get our request as a string
result= SK_XmlDocumentGetDocumentString(SK_FLAGS_NONE, encryptedRequest, &encryptedRequestString, &requestSize);

//You may allow the user to copy the request string and/or save the activation request to an HTML file
result = SK_SOLO_ManualRequestFileSave(context, SK_FLAGS_NONE, SK_CONST_WEBSERVICE_MANUALREQUEST_URL, NULL, NULL, requestFile, encryptedRequest);
//free our encrypted request document
SK_XmlDocumentDispose(SK_FLAGS_NONE, &encryptedRequest);

The above request is generated using fictional hard-coded data for demonstration purposes. The code snippet above omits many of the parameters necessary to initialize the API context (the context variable). Refer to the Configuring the API Context topic for instructions and a complete example of calling the SK_ApiContextInitialize function.

Using the SOLO Server Manual Request Page

Once the user generates the manual activation request, they must take it to a computer with Internet access where they can paste it in or upload it to the SOLO Server manual request page. If SOLO Server is able to successfully process the manual request it will generate a response that must be taken back to the computer being activated. Otherwise, it will display an error message and it may be necessary for the end-user to contact support for help and possibly have to start the process over.


The above SOLO Server Manual Request link is for use with SOLO Server Shared URL only. If using SOLO Server Custom URL, Dedicated URL, or Self-Hosted, this will need to be updated to point to your specific domain.

Decrypting and Parsing the Response

After the end-user returns to the computer being activated with the encrypted response, it must be decrypted and verified. Once done, you must manually parse the response to determine what actions to take. Here, the XML helper functions are used here to extract the data out of the response document. A read-only license file is contained as a sub-document in the response's License node. Once you extract the license document from the response you can save it to disk.

char *responseString = NULL;
char *responseFile = "...";
//allow the user to paste the response string or load it from a file
if (isLoadFromFile)
//load the response string from a file. The API function will also decrypt the data
result = SK_SOLO_ManualRequestFileLoad(context, SK_FLAGS_NONE, responseFile, &response);
//load the response string into an XML document from a string the user pasted
result = SK_XmlDocumentCreateFromString(SK_FLAGS_NONE, responseString, &encryptedResponse);

//decrypt/verify the response
result = SK_XmlDocumentDecryptRsa(context, SK_FLAGS_NONE, FALSE, encryptedResponse, &response);

//free our encrypted response document
SK_XmlDocumentDispose(SK_FLAGS_NONE, &encryptedResponse);
//get the SessionCode from the response
result = SK_XmlNodeGetValueString(SK_FLAGS_NONE, response, "//SessionCode", FALSE, &responseSessionCode);

//load our originalSessionCode that was previously saved

//verify the session codes match
if ((NULL != responseSessionCode) || (NULL == strstr(originalSessionCode, responseSessionCode)))
//handle error condition

//clear our originalSessionCode that was previously saved

//free our session code strings
SK_StringDispose(SK_FLAGS_NONE, &originalSessionCode);
SK_StringDispose(SK_FLAGS_NONE, &responseSessionCode);

//get the license sub-document
result = SK_XmlNodeGetDocument(SK_FLAGS_NONE, response, "/ActivateInstallationLicenseFile/PrivateData/License", &license);

//free our response document
SK_XmlDocumentDispose(SK_FLAGS_NONE, &response);

if (NULL != license)
//save the license file to disk
result = SK_PLUS_LicenseFileSave(context, SK_FLAGS_NONE, filename, license);

//free our license document
SK_XmlDocumentDispose(SK_FLAGS_NONE, &license);

Although the above example saves the license file to disk, it can actually be saved anywhere, such as in a database. In such a scenario, your application would only need to save the license string. If you don't save the license file using SK_PLUS_LicenseFileSave, it is necessary to call SK_PLUS_LicenseLoad to load the newly obtained license into memory.


If the user is pasting in a response instead of loading a response file, there are a few potential issues to be aware of:

These issues do not occur when the encryption response is loaded from a file.

Session Code Validation

This example uses session code validation to prevent the end-user from processing the same response multiple times, which is known as a replay attack. A random session code is generated and included in each web service request. This session code must be saved somewhere on the system so it can later be retrieved and compared to the session code found in the web service response. If the session codes match then you know the response was the response associated with the original web service request. Otherwise, the response should be consider invalid.


These basic source code examples omit important and necessary error checking for the sake of clarity. Many of the functions used could fail for one reason or another, and it is important that you make sure each function call succeeds before passing the result from one function to another. Otherwise, you may not be able to tell exactly where a problem originated if and when one occurs.

Manual Activation with Serial Number and Product ID

PLUSNative allows activating an application using the Product ID and a serial number pre-loaded into SOLO Server. This method can be used instead of activating with a License ID and Activation Password, and it allows the use of your own activation serial numbers. This can be useful if your customers are already familiar with a certain license key format or if you need to import a list of serials from another system.

Adding Serial Numbers to Licenses in SOLO Server

The SOLO Server manual topic Importing and Exporting Product Serial Numbers explains how to load a list of serial numbers in SOLO Server. Each time a new license is created for that Product, the next unused serial number in the list will be associated with the license. To issue a serial number to an existing license after uploading the serials, you can simply view the license in SOLO Server and choose the Issue Serial Number option in the Licenses menu.

You must use the mechanism described above to import serial numbers into SOLO Server. Attempting to manually enter a serial number into the serial number field by editing a License in SOLO Server will result in the activation failing with a Response Code of 100.

Activating with a Serial Number

To activate using the Serial Number, when calling the SK_SOLO_ActivateInstallationGetRequest API function to get the request data, set the License ID parameter to 0 and the Activation Password parameter to an empty string. Be sure to set the Serial Number parameter and the Product ID was set when creating the API context. The rest of the manual activation steps remain the same.