1/** 2 * Inicialització mÃnima de Klaro. 3 * 4 * Klaro v0.7.11 nativament gestiona: 5 * - Banner + modal de consentiment. 6 * - Bloqueig de <script type="text/plain" data-name="X">. 7 * - Bloqueig de <iframe data-name="X" data-src="...">. 8 * - Esborrat de galetes declarades a services[].cookies[] (config server-side). 9 * - Persistència del consentiment a la galeta `klaro`. 10 * 11 * Aquest fitxer NOMÃS afegeix l'auditoria a BD: cada vegada que l'usuari 12 * canvia preferències, enviem un snapshot a /requestconsentsnapshot. 13 * 14 * No hi ha cap altra capa pròpia al front. 15 */ 16(function () { 17 'use strict'; 18 19 // Klaro accepta cookies[] com [name|RegExp, path, domain]. El PHP envia regex com 20 // string "/^_ga_.*$/". Cal convertir-los a objectes RegExp perquè Klaro pugui 21 // esborrar wildcards (com _ga_ABC123) al rebutjar el servei. 22 (function convertCookieRegexes() { 23 try { 24 var cfg = window.klaroConfig; 25 if (!cfg || !Array.isArray(cfg.services)) return; 26 cfg.services.forEach(function (svc) { 27 if (!Array.isArray(svc.cookies)) return; 28 svc.cookies = svc.cookies.map(function (c) { 29 if (Array.isArray(c) && typeof c[0] === 'string' && /^\/.+\/[gimsuy]*$/.test(c[0])) { 30 var m = c[0].match(/^\/(.+)\/([gimsuy]*)$/); 31 if (m) { 32 try { c[0] = new RegExp(m[1], m[2]); } catch (e) {} 33 } 34 } 35 return c; 36 }); 37 }); 38 } catch (e) {} 39 })(); 40 41 function getCookie(name) { 42 var parts = document.cookie.split(';'); 43 for (var i = 0; i < parts.length; i++) { 44 var c = parts[i].trim(); 45 if (c.indexOf(name + '=') === 0) { 46 return decodeURIComponent(c.substring(name.length + 1)); 47 } 48 } 49 return ''; 50 } 51 52 function getOrCreateConsentUserHash() { 53 var key = 'cookie_consent_user_hash'; 54 try { 55 // sessionStorage: no persisteix entre sessions, no requereix consentiment previ 56 var existing = sessionStorage.getItem(key); 57 if (existing) return existing; 58 var rnd = Math.random().toString(16).slice(2) + Date.now().toString(16); 59 sessionStorage.setItem(key, rnd); 60 return rnd; 61 } catch (e) { 62 return 'anon_' + Date.now().toString(16); 63 } 64 } 65 66 // El dedupe es persisteix a sessionStorage: sense això, cada cà rrega de pà gina 67 // enviava un snapshot idèntic i es disparava el rate-limit del servidor (429). 68 var __snapshotKey = 'cookie_consent_last_snapshot'; 69 var __timer = null; 70 71 function getLastSerialized() { 72 try { return sessionStorage.getItem(__snapshotKey); } catch (e) { return null; } 73 } 74 75 function setLastSerialized(value) { 76 try { sessionStorage.setItem(__snapshotKey, value); } catch (e) {} 77 } 78 79 function sendConsentSnapshot(preferences) { 80 clearTimeout(__timer); 81 __timer = setTimeout(function () { 82 var audit = window.__cookieAudit || {}; 83 var endpoint = audit.endpoint || '/requestconsentsnapshot'; 84 var versionTag = audit.versionTag || (window.klaroConfig && window.klaroConfig.version) || 'v1'; 85 86 var payload = { 87 user_hash: getOrCreateConsentUserHash(), 88 version_tag: versionTag, 89 preferences: preferences || {} 90 }; 91 var serialized = JSON.stringify(payload); 92 if (serialized === getLastSerialized()) return; 93 setLastSerialized(serialized); 94 95 // fetch nativa: 0 dependències jQuery 96 try { 97 fetch(endpoint, { 98 method: 'POST', 99 headers: { 'Content-Type': 'application/json; charset=utf-8' }, 100 body: serialized, 101 credentials: 'same-origin' 102 }).then(function (r) { 103 // Si ha fallat per una causa transitòria, oblidem el dedupe per reintentar. 104 // En 429 NO reintentem: agreujaria el rate-limit. 105 if (!r.ok && r.status !== 429) setLastSerialized(''); 106 }).catch(function () { setLastSerialized(''); }); 107 } catch (e) {} 108 }, 300); 109 } 110 111 function hook() { 112 if (!window.klaro || typeof window.klaro.getManager !== 'function') return false;
113 var manager = window.klaro.getManager(); 114 if (!manager || manager.__snapshotHooked) return true; 115 // Verificar que el manager esté completamente inicializado 116 if (!manager.consents || !manager.watch) return false; 117 manager.__snapshotHooked = true; 118 119 // Si l'usuari ja té la galeta klaro (visita de retorn), activem confirmed=true 120 // perquè el context notice mostri els dos botons: "Acceptar" i "Acceptar Sempre". 121 // Per a visites noves (sense galeta), s'activa en el primer saveConsents/applyConsents 122 // (just after banner interaction), evitant amagar el banner principal. 123 if (getCookie('klaro-v2') && !manager.confirmed) { 124 manager.confirmed = true; 125 } 126 127 // Snapshot inicial (estat actual de la galeta `klaro`) 128 try { sendConsentSnapshot(manager.consents || {}); } catch (e) {} 129 130 // Subscripció a l'API pública de Klaro (sense parxejar saveConsents) 131 if (typeof manager.watch === 'function') { 132 manager.watch({ 133 update: function (obj, name) { 134 // Després de la primera interacció amb el banner principal, 135 // activem confirmed perquè el context notice mostri tots dos botons. 136 if ((name === 'saveConsents' || name === 'applyConsents') && !manager.confirmed) { 137 manager.confirmed = true; 138 } 139 if (name !== 'consents' && name !== 'saveConsents' && name !== 'applyConsents') return; 140 try { sendConsentSnapshot(manager.consents || {}); } catch (e) {} 141 } 142 }); 143 } 144 return true; 145 } 146 147 // Re-aplica consents quan el DOM és complet. 148 // Klaro es carrega al <head> i crida applyConsents() abans que el <body> 149 // existeixi: els iframes/scripts amb data-name no es troben i queden bloquejats. 150 // Només s'executa si ja existeix la galeta klaro (usuari de retorn amb consentiment 151 // previ). Per a primeres visites (sense galeta) no s'interfereix per no amagar el banner. 152 document.addEventListener('DOMContentLoaded', function () { 153 try { 154 if (!getCookie('klaro-v2')) return; 155 if (window.klaro && typeof window.klaro.getManager === 'function') { 156 var m = window.klaro.getManager(); 157 if (m && typeof m.applyConsents === 'function') { 158 m.applyConsents(); 159 } 160 } 161 } catch (e) {} 162 }); 163 164 // Klaro s'inicialitza per si sol llegint window.klaroConfig. Només cal 165 // esperar que el manager existeixi per a enganxar l'auditoria. 166 var tries = 0; 167 var t = setInterval(function () { 168 try { 169 if (hook() || tries++ > 80) clearInterval(t); 170 } catch (e) { 171 // silenci: potser klaro no està totalment inicialitzat encara 172 if (tries++ > 80) clearInterval(t); 173 } 174 }, 250); 175})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.