Ajoute le plugin Acrobat Pro d'imposition (acrobat-plugin/)
Suite d'imposition professionnelle en Folder-Level Scripts JS (7 modules + verification de licence Vision), avec un plugin natif hybride optionnel (WinINet + Registre) pour deplacer la verification de licence en code compile. Installeur install.bat sur le meme modele que celui du projet desktop (git portable, detection automatique des dossiers Acrobat).
This commit is contained in:
342
acrobat-plugin/src/Imposition-00b-Licence.js
Executable file
342
acrobat-plugin/src/Imposition-00b-Licence.js
Executable file
@@ -0,0 +1,342 @@
|
||||
// Imposition-00b-Licence.js
|
||||
// ---------------------------------------------------------------------------
|
||||
// Suite d'imposition professionnelle - Folder-Level Script pour Adobe Acrobat Pro
|
||||
// Module 0b : Verification de licence (serveur Vision)
|
||||
//
|
||||
// Depend de Imposition-00-Core.js (doit etre charge avant). Doit etre charge
|
||||
// AVANT Imposition-01-UI.js (le prefixe "00b" garantit cet ordre).
|
||||
//
|
||||
// Reutilise le serveur de licence Vision deja en place pour le projet
|
||||
// "Copydev Imposing Tool" (impose) : meme API license.php, meme logique de
|
||||
// cache hors-ligne avec duree de tolerance, meme principe de plafond
|
||||
// d'appareils (max_devices) gere cote serveur. Seul le champ "product"
|
||||
// change pour distinguer ce plugin Acrobat des autres produits Copydev.
|
||||
//
|
||||
// AVERTISSEMENTS TECHNIQUES - a tester dans Acrobat Pro reel :
|
||||
// - Net.HTTP.request() est l'API documentee pour les requetes HTTP depuis
|
||||
// un script Acrobat privilegie, mais sa disponibilite depend des
|
||||
// reglages de securite reseau d'Acrobat (Preferences > Securite
|
||||
// (avancee) > Gestionnaire de confiance > acces internet pour les
|
||||
// scripts non-PDF). A activer/whitelister si necessaire.
|
||||
// - La lecture du flux de reponse (Stream.read()) est implementee selon le
|
||||
// schema le plus communement documente, mais n'a pas pu etre executee
|
||||
// dans cet environnement de developpement (pas d'Acrobat installe) :
|
||||
// ajuster _lireFluxReponse() si le parsing JSON echoue en conditions
|
||||
// reelles.
|
||||
// - L'identifiant machine (machine_id) repose sur ActiveXObject (COM),
|
||||
// disponible uniquement sous Windows pour des scripts de dossier
|
||||
// (folder-level) de confiance. En cas d'indisponibilite, on retombe sur
|
||||
// un identifiant genere une fois et persiste localement (moins robuste
|
||||
// contre la copie de licence, mais fonctionnel).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (typeof CDImp === "undefined") {
|
||||
throw new Error("Imposition-00b-Licence.js : CDImp.Core doit etre charge avant ce fichier.");
|
||||
}
|
||||
|
||||
CDImp.Licence = CDImp.Licence || {};
|
||||
|
||||
CDImp.Licence.CONFIG = {
|
||||
serveurUrl: "https://vision.copydev.fr/api/license.php",
|
||||
produit: "imposing-acrobat",
|
||||
dureeCacheHeuresParDefaut: 24 // utilisee si le serveur ne renvoie pas offline_timeout_hours
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Identifiants machine
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Nom de la machine, via WSH (Windows uniquement, scripts de dossier
|
||||
* privilegies). Retombe sur "Inconnu" si indisponible.
|
||||
*/
|
||||
CDImp.Licence._obtenirHostname = function () {
|
||||
try {
|
||||
var reseau = new ActiveXObject("WScript.Network");
|
||||
return String(reseau.ComputerName);
|
||||
} catch (e) {
|
||||
return "Inconnu";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Identifiant machine stable, persiste dans les preferences globales
|
||||
* d'Acrobat (genere une seule fois). Pas un identifiant materiel (UUID
|
||||
* BIOS), mais suffisant pour le comptage d'appareils cote serveur.
|
||||
*/
|
||||
CDImp.Licence._obtenirMachineId = function () {
|
||||
if (typeof global.cdImpMachineId !== "undefined" && global.cdImpMachineId) {
|
||||
return global.cdImpMachineId;
|
||||
}
|
||||
var id = "";
|
||||
for (var i = 0; i < 32; i++) {
|
||||
id += Math.floor(Math.random() * 16).toString(16);
|
||||
}
|
||||
CDImp.Util.avecPrivileges(function () {
|
||||
global.cdImpMachineId = id;
|
||||
global.setPersistent("cdImpMachineId", true);
|
||||
});
|
||||
return id;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Requete HTTP synchrone vers le serveur de licence
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Convertit le flux de reponse Net.HTTP en chaine de caracteres.
|
||||
*/
|
||||
CDImp.Licence._lireFluxReponse = function (msgStream) {
|
||||
try {
|
||||
var nTaille = msgStream.length;
|
||||
var aOctets = msgStream.read(nTaille);
|
||||
var texte = "";
|
||||
for (var i = 0; i < aOctets.length; i++) {
|
||||
texte += String.fromCharCode(aOctets[i]);
|
||||
}
|
||||
return texte;
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Effectue une requete GET synchrone et retourne { erreur, texte }.
|
||||
*/
|
||||
CDImp.Licence._requeteHTTPSync = function (url) {
|
||||
var resultat = { erreur: null, texte: null };
|
||||
try {
|
||||
Net.HTTP.request({
|
||||
cVerb: "GET",
|
||||
cURL: url,
|
||||
oHandler: {
|
||||
response: function (msgStream, status) {
|
||||
if (status && status >= 400) {
|
||||
resultat.erreur = "HTTP " + status;
|
||||
} else {
|
||||
resultat.texte = CDImp.Licence._lireFluxReponse(msgStream);
|
||||
}
|
||||
},
|
||||
error: function (msg, err) {
|
||||
resultat.erreur = (err || msg || "Erreur reseau inconnue").toString();
|
||||
}
|
||||
},
|
||||
bAsync: false
|
||||
});
|
||||
} catch (e) {
|
||||
resultat.erreur = e.toString();
|
||||
}
|
||||
return resultat;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Saisie / stockage de la cle de licence
|
||||
// -----------------------------------------------------------------------
|
||||
CDImp.Licence._demanderCle = function () {
|
||||
var cle = app.response({
|
||||
cQuestion: "Cle de licence Copydev Imposing (Acrobat) :",
|
||||
cTitle: "Activation de la licence",
|
||||
cDefault: ""
|
||||
});
|
||||
return (cle && cle.length > 0) ? cle : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recopie la cle dans le Registre Windows (HKCU\Software\Copydev\
|
||||
* ImposingAcrobat\CleLicence), seul emplacement que le plugin natif
|
||||
* (voir /native/PluginMain.cpp) sait lire : global.setPersistent() stocke
|
||||
* la valeur dans le mecanisme de preferences interne d'Acrobat, pas dans
|
||||
* le Registre, donc cette ecriture explicite est necessaire pour que le
|
||||
* plugin natif et le JS partagent la meme cle. Echec silencieux si
|
||||
* ActiveXObject est indisponible (plugin natif alors simplement inutilisable,
|
||||
* le JS continue de fonctionner seul).
|
||||
*/
|
||||
CDImp.Licence._ecrireCleRegistre = function (cle) {
|
||||
try {
|
||||
var shell = new ActiveXObject("WScript.Shell");
|
||||
shell.RegWrite("HKCU\\Software\\Copydev\\ImposingAcrobat\\CleLicence", cle, "REG_SZ");
|
||||
} catch (e) {
|
||||
// pas grave : le plugin natif (s'il est installe) ne pourra pas
|
||||
// verifier la licence de son cote, le JS reste fonctionnel seul.
|
||||
}
|
||||
};
|
||||
|
||||
CDImp.Licence._obtenirCle = function () {
|
||||
if (typeof global.cdImpLicenceCle !== "undefined" && global.cdImpLicenceCle) {
|
||||
return global.cdImpLicenceCle;
|
||||
}
|
||||
var cle = CDImp.Licence._demanderCle();
|
||||
if (!cle) {
|
||||
return null;
|
||||
}
|
||||
CDImp.Util.avecPrivileges(function () {
|
||||
global.cdImpLicenceCle = cle;
|
||||
global.setPersistent("cdImpLicenceCle", true);
|
||||
});
|
||||
CDImp.Licence._ecrireCleRegistre(cle);
|
||||
return cle;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verdict du plugin natif (voir /native/), lu en priorite s'il est present
|
||||
// et frais. Permet de s'appuyer sur une verification effectuee en code
|
||||
// compile (plus dur a lire/patcher qu'un .js) plutot que sur le seul check
|
||||
// JS ci-dessous. Si le plugin natif n'est pas installe ou n'a pas encore
|
||||
// ecrit de verdict, on retombe naturellement sur la verification JS pure
|
||||
// (aucune regression).
|
||||
// -----------------------------------------------------------------------
|
||||
CDImp.Licence._lireVerdictNatif = function () {
|
||||
try {
|
||||
var shell = new ActiveXObject("WScript.Shell");
|
||||
var ok = shell.RegRead("HKCU\\Software\\Copydev\\ImposingAcrobat\\LicenceOK");
|
||||
var expirationStr = shell.RegRead("HKCU\\Software\\Copydev\\ImposingAcrobat\\LicenceValideJusqua");
|
||||
var expiration = parseInt(expirationStr, 10);
|
||||
var maintenant = Math.floor((new Date()).getTime() / 1000);
|
||||
|
||||
if (String(ok) === "1" && expiration > maintenant) {
|
||||
return { valide: true, source: "plugin_natif" };
|
||||
}
|
||||
return { valide: false, source: "plugin_natif", raison: "Verdict du plugin natif absent ou expire." };
|
||||
} catch (e) {
|
||||
return null; // plugin natif non installe / registre absent : pas d'info
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verification (serveur, avec repli sur cache hors-ligne)
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Verifie la licence auprès du serveur Vision. En cas d'echec reseau,
|
||||
* retombe sur le dernier resultat valide mis en cache, dans la limite de la
|
||||
* duree de tolerance hors-ligne (offline_timeout_hours renvoye par le
|
||||
* serveur, ou valeur par defaut).
|
||||
*
|
||||
* @returns {Object} { valide, source: "serveur"|"cache", donnees, raison }
|
||||
*/
|
||||
CDImp.Licence.verifier = function () {
|
||||
var verdictNatif = CDImp.Licence._lireVerdictNatif();
|
||||
if (verdictNatif && verdictNatif.valide) {
|
||||
return verdictNatif;
|
||||
}
|
||||
// Verdict natif absent, expire ou plugin non installe : on continue
|
||||
// avec la verification JS habituelle (HTTP + cache hors-ligne).
|
||||
|
||||
var cle = CDImp.Licence._obtenirCle();
|
||||
if (!cle) {
|
||||
return { valide: false, raison: "Aucune cle de licence saisie." };
|
||||
}
|
||||
|
||||
var machineId = CDImp.Licence._obtenirMachineId();
|
||||
var hostname = CDImp.Licence._obtenirHostname();
|
||||
var url = CDImp.Licence.CONFIG.serveurUrl
|
||||
+ "?key=" + encodeURIComponent(cle)
|
||||
+ "&machine_id=" + encodeURIComponent(machineId)
|
||||
+ "&hostname=" + encodeURIComponent(hostname)
|
||||
+ "&product=" + encodeURIComponent(CDImp.Licence.CONFIG.produit);
|
||||
|
||||
var reponse = CDImp.Licence._requeteHTTPSync(url);
|
||||
|
||||
if (reponse.erreur || !reponse.texte) {
|
||||
return CDImp.Licence._verifierCache(reponse.erreur);
|
||||
}
|
||||
|
||||
var data;
|
||||
try {
|
||||
data = JSON.parse(reponse.texte);
|
||||
} catch (e) {
|
||||
return CDImp.Licence._verifierCache("Reponse serveur illisible.");
|
||||
}
|
||||
|
||||
var valide = !!(data.active || data.valid);
|
||||
|
||||
CDImp.Util.avecPrivileges(function () {
|
||||
global.cdImpLicenceCache = { valide: valide, donnees: data, dateVerif: (new Date()).getTime() };
|
||||
global.setPersistent("cdImpLicenceCache", true);
|
||||
});
|
||||
|
||||
return { valide: valide, donnees: data, source: "serveur" };
|
||||
};
|
||||
|
||||
CDImp.Licence._verifierCache = function (raisonReseau) {
|
||||
var cache = global.cdImpLicenceCache;
|
||||
if (!cache) {
|
||||
return { valide: false, raison: "Serveur de licence inaccessible (" + (raisonReseau || "?") + ") et aucun cache local." };
|
||||
}
|
||||
var heuresEcoulees = ((new Date()).getTime() - cache.dateVerif) / 3600000;
|
||||
var tolerance = (cache.donnees && cache.donnees.offline_timeout_hours) || CDImp.Licence.CONFIG.dureeCacheHeuresParDefaut;
|
||||
|
||||
if (cache.valide && heuresEcoulees <= tolerance) {
|
||||
return { valide: true, donnees: cache.donnees, source: "cache", heuresEcoulees: heuresEcoulees };
|
||||
}
|
||||
return {
|
||||
valide: false,
|
||||
raison: "Serveur de licence inaccessible (" + (raisonReseau || "?") + ") et cache hors-ligne expire ou invalide\n(hors-ligne depuis ~" + Math.round(heuresEcoulees) + "h, tolerance " + tolerance + "h)."
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifie la licence et affiche une alerte bloquante si elle est invalide.
|
||||
* A appeler avant toute action des modules d'imposition.
|
||||
*
|
||||
* @returns {Boolean} true si l'utilisation peut continuer
|
||||
*/
|
||||
CDImp.Licence.verifierEtBloquerSiInvalide = function () {
|
||||
var resultat;
|
||||
try {
|
||||
resultat = CDImp.Licence.verifier();
|
||||
} catch (e) {
|
||||
CDImp.Util.erreur("Erreur lors de la verification de la licence : " + e.toString());
|
||||
return false;
|
||||
}
|
||||
if (!resultat.valide) {
|
||||
CDImp.Util.erreur("Licence invalide ou expiree :\n" + (resultat.raison || "")
|
||||
+ "\n\nLa suite d'imposition professionnelle est desactivee.\nUtilisez \"Imposition Pro > Gerer la licence...\" pour saisir une cle valide.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Boite de dialogue simple permettant de saisir/remplacer la cle de licence
|
||||
* et de relancer immediatement une verification.
|
||||
*/
|
||||
CDImp.Licence.gererCle = function () {
|
||||
var cleActuelle = global.cdImpLicenceCle || "";
|
||||
var nouvelleCle = app.response({
|
||||
cQuestion: "Cle de licence Copydev Imposing (Acrobat) :",
|
||||
cTitle: "Gerer la licence",
|
||||
cDefault: cleActuelle
|
||||
});
|
||||
if (nouvelleCle === null || nouvelleCle === cleActuelle) {
|
||||
return;
|
||||
}
|
||||
CDImp.Util.avecPrivileges(function () {
|
||||
global.cdImpLicenceCle = nouvelleCle;
|
||||
global.setPersistent("cdImpLicenceCle", true);
|
||||
global.cdImpLicenceCache = null; // force une nouvelle verification serveur
|
||||
global.setPersistent("cdImpLicenceCache", true);
|
||||
});
|
||||
CDImp.Licence._ecrireCleRegistre(nouvelleCle);
|
||||
CDImp.Util.info("Cle enregistree. Redemarrez Acrobat pour que le plugin natif\n(s'il est installe) la prenne en compte au prochain demarrage.");
|
||||
var resultat = CDImp.Licence.verifier();
|
||||
if (resultat.valide) {
|
||||
CDImp.Util.info("Licence valide. Source : " + resultat.source + ".");
|
||||
} else {
|
||||
CDImp.Util.erreur("Licence invalide : " + (resultat.raison || ""));
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Entree de menu "Gerer la licence..."
|
||||
// -----------------------------------------------------------------------
|
||||
CDImp.Util.avecPrivileges(function () {
|
||||
try {
|
||||
app.addMenuItem({
|
||||
cName: "CDImpGererLicence",
|
||||
cParent: "Edit",
|
||||
cExec: "CDImp.Licence.gererCle();",
|
||||
cEnable: "event.rc = (CDImp.Licence != undefined);",
|
||||
nPos: -1
|
||||
});
|
||||
} catch (e) {
|
||||
// menu deja present (rechargement de script) : ignore
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user