Secure DjVu on Viewer Application
To support Secure DjVu on your viewer application, you should do the following four tasks:
Authentication support
When you're implementing a viewer application, which also support Secure DjVu files, the first thing you have to do is to implement authentication mechanism, which typicaly shows some dialog to prompt user to input his user-ID and password. It's mandatory process and without the authentication support, SDK could not open any Secure DjVu files.
The easiest way to implement authentication is to use CredentialProvider::createFromStrings :
- Note
- If the file is Secure DjVu and Document::create is missing a valid CredentialProvider instance, decoding process throws errAuthRequired.
The code above is anyway not complete; if the userId/password pair is not correct, SDK will throw certain exception on actual decoding process; it's not always in Document::create but sometimes in Page methods.
try
{
AutoPtr<Page> page = doc->getPages()[0];
size_t width = page->getWidth();
size_t height = page->getHeight();
page->render(...);
}
catch(std::exception& ex)
{
showError(ex.what());
...
}
- Note
- By implementing CredentialProvider and CredentialInfo, you can realize more flexible and complex authentication process.
Restriction on file operations
Your application should enforce appropriate permissions. Secure DjVu file may disallow certain kind of operations on the file. The following operations should be under control of Secure DjVu:
- Printing of Secure DjVu content
- Exporting (Saving) of Secure DjVu content
- Copying of Secure DjVu content (text, image)
- Editing of user list/user access
So your viewer application should at least enable/disable menu items, shortcuts and/or buttons which enables users to execute the operations above.
{
const SecurityProvider* sp = doc->getSecurityProvider();
if(!sp)
{
return true;
}
if(sp->isExpired())
{
return false;
}
return sp->isPermitted(inPriPro);
}
...
menu.copy.enabled = isPermitted(
p3Copy);
menu.print.enabled = isPermitted(
p3Print);
menu.save.enabled = isPermitted(
p3Export);
And, you had better add more security fences on functions executing Secure DjVu operations:
{
return;
static const char* privs[] = {
NULL, "owner", "edit", "print", "export", "copy", "editprop"};
};
if(!isPermitted(inPriPro))
"Operation not permitted: %s", privs[inPriPro]));
}
...
void your_djvu_save_function(...)
{
...
}
Expiry support
Your application also support expiry of the Secure DjVu document. It's also implemented on the Secure DjVu decoder (the decoder sometimes throws exception for such security and expiry checks) but you should explicitly show the expiry information to the users.
The following code explains the flow:
...
const SecurityProvider* sp = doc->getSecurityProvider();
if(sp && sp->isExpired())
{
showError("The document is expired on %s!", t.getRFC822timeString(true).c_str());
exit(0);
}
License script for Secure DjVu decode
After implementing them correctly, you should obtain appropriate license script (which contains SecureDjVuDecode) from Cuminas and embed the obtained license script on your code:
lm.setLicenseScript(".....");
Without any license script, the program runs under development license and stops working after 2 weeks from its built time. For more information about license system, see License System.
DjVu Encoder application
If your application encodes Secure DjVu files, your application should set appropriate SecurityProvider instance when calling Document::save or IFF::serialize method. The following sub-sections explains about two typical Secure DjVu encoding(saveing) processes.
Securing DjVu file
AutoPtr<Document> doc = ...
PropertySet* ps = secProv->getEditableUserPropSet(utf8s("admin"));
ps->set(utf8s("Password"), utf8s("admin"));
ps->set(utf8s("AllPriv"), utf8s("Yes"));
ps = secProv->getEditableUserPropSet(utf8s("ito"));
ps->set(utf8s("Password"), utf8s("ito"));
ps->set(utf8s("Print"), utf8s("Yes"));
ps = secProv->getEditableUserPropSet(utf8s("kawasaki"));
ps->set(utf8s("Password"), utf8s("kawasaki"));
ps->set(utf8s("Save"), utf8s("Yes"));
doc->save(storageW, secProv);
storageW->commit();
Re-saving modified Secure DjVu
If your application simply load and save the Secure DjVu file without modifying Secure DjVu users/permissions, use the SecurityProvider instance obtained by the Document instance:
...
doc->save(storageW, doc->getSecurityProvider());
storageW->commit();
- Warning
- If you don't pass any SecurityProvider instance on saving the document, the saved file will not be scrambled; it will be in plain DjVu file (descrambled DjVu file). And if the user does not have p3Export privilege, Document::save throws errNotPermitted.
Updating user access control
You can also add/remove/edit users/permissions by updating SecurityProvider instance. Please note that the SecurityProvider instance obtained from Document::getSecurityProvider is not be modified.
const SecurityProvider* secProvOriginal = doc->getSecurityProvider();
AutoPtr<SecurityProvider> secProv = secProvOriginal->duplicate();
PropertySet* ps = secProv->getEditableUserPropSet();
ps->set(utf8s("Password"), utf8s("current-user's-new-password"));
ps = secProv->getEditableUserPropSet(utf8s("ito"));
ps->set(utf8s("Password"), utf8s("ito"));
ps->set(utf8s("Print"), utf8s("Yes"));
doc->save(storageW, secProv);
storageW->commit();
License script for Secure DjVu encode
After implementing them correctly, you should obtain appropriate license script (which contains SecureDjVuEncode) from Cuminas and embed the obtained license script on your code. For more information about license system, see License System.