File manager - Edit - /var/www/html/portal/storage/framework/views/834fad7bdc27e1eabba132e9645ab076.php
Back
<?php $__env->startSection('title', env('APP_NAME') . ' :: Gerador de Senha'); ?> <?php $__env->startSection('content'); ?> <style> :root { --gp-primary: #0d6efd; --gp-primary-soft: #e7f0ff; } .gp-mode-tabs { display: flex; gap: 4px; background: #f1f3f5; padding: 4px; border-radius: 99px; } .gp-mode-tab { flex: 1; padding: .55rem 1rem; border: none; background: transparent; border-radius: 99px; font-size: .9rem; font-weight: 600; cursor: pointer; color: #6c757d; transition: all .2s; display: flex; align-items: center; justify-content: center; gap: 7px; } .gp-mode-tab.active { background: #fff; color: var(--gp-primary); box-shadow: 0 1px 3px rgba(0, 0, 0, .08); } .gp-mode-tab small { font-weight: 400; opacity: .7; font-size: .72rem; } #senhaGerada { font-family: 'Courier New', monospace; font-size: 1.05rem; font-weight: 600; letter-spacing: .5px; } .gp-bar-track { flex: 1; height: 6px; background: #e9ecef; border-radius: 99px; overflow: hidden; } #strengthFill { height: 100%; border-radius: 99px; width: 0%; transition: width .3s ease, background .3s ease; } .gp-toggle { display: inline-flex; align-items: center; gap: 6px; padding: .38rem .85rem; border-radius: 99px; border: 1.5px solid #dee2e6; background: #f8f9fa; font-size: .85rem; cursor: pointer; user-select: none; transition: all .15s; font-weight: 500; } .gp-toggle.active { border-color: var(--gp-primary); background: var(--gp-primary-soft); color: var(--gp-primary); } .gp-toggle input { display: none; } .gp-pill { padding: .3rem .75rem; border-radius: 99px; border: 1.5px solid #dee2e6; background: #f8f9fa; font-size: .85rem; font-weight: 600; cursor: pointer; transition: all .15s; color: #495057; } .gp-pill.active { border-color: var(--gp-primary); background: var(--gp-primary); color: #fff; } .gp-slider-row input[type=range] { flex: 1; accent-color: var(--gp-primary); height: 6px; cursor: pointer; } .gp-len-badge { min-width: 38px; text-align: center; font-weight: 700; font-size: 1rem; color: var(--gp-primary); } .gp-card-title { font-size: .85rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: #6c757d; } .gp-label-bold { font-size: .82rem; font-weight: 600; color: #6c757d; } .hist-pw { flex: 1; font-family: 'Courier New', monospace; font-size: .88rem; font-weight: 600; word-break: break-all; color: #212529; } .gp-toast { position: fixed; bottom: 1.5rem; right: 1.5rem; background: #212529; color: #fff; padding: .6rem 1.1rem; border-radius: 8px; font-size: .88rem; display: flex; align-items: center; gap: 6px; opacity: 0; transform: translateY(6px); pointer-events: none; transition: opacity .25s, transform .25s; z-index: 9999; } .gp-toast.show { opacity: 1; transform: translateY(0); } @media (max-width: 500px) { .gp-mode-tab { font-size: .82rem; padding: .5rem .6rem; } .gp-mode-tab small { display: none; } } </style> <div class="container my-5"> <div class="text-center mb-4"> <h2 class="text-primary fw-bold mb-1"><i class="fas fa-key"></i> Gerador de Senhas</h2> <p class="text-muted small mb-0">Escolha o estilo que combina com você: aleatória forte ou memorável fácil.</p> </div> <div class="gp-mode-tabs mb-3" role="tablist" aria-label="Estilo da senha"> <button class="gp-mode-tab active" data-mode="random" type="button" role="tab"> <i class="fas fa-dice"></i> Aleatória <small>(mais segura)</small> </button> <button class="gp-mode-tab" data-mode="memorable" type="button" role="tab"> <i class="fas fa-feather-alt"></i> Memorável <small>(mais fácil)</small> </button> </div> <div class="card mb-3"> <div class="card-body"> <div class="gp-card-title mb-3"> <i class="fas fa-lock-open text-primary"></i> Senha Gerada </div> <div class="input-group"> <input id="senhaGerada" type="text" class="form-control" readonly placeholder="Clique em Gerar →" autocomplete="off" spellcheck="false" aria-label="Senha gerada"> <button class="btn btn-primary" id="copiar" type="button" aria-label="Copiar senha"> <i class="fas fa-copy"></i> Copiar </button> </div> <div class="d-flex align-items-center gap-2 mt-3"> <span class="small text-muted text-nowrap">Força:</span> <div class="gp-bar-track"> <div id="strengthFill"></div> </div> <span id="nvlSenha" class="badge bg-secondary" style="font-size:.78rem;">—</span> <span id="entropyVal" class="small text-muted text-nowrap">— bits</span> </div> </div> </div> <div class="card mb-3" id="cardRandom"> <div class="card-body"> <div class="gp-card-title mb-3"> <i class="fas fa-sliders-h text-primary"></i> Configurações — Aleatória </div> <div class="mb-3"> <div class="d-flex justify-content-between align-items-center mb-2"> <label for="tamanho" class="small fw-semibold mb-0">Tamanho</label> <span class="gp-len-badge" id="tamanhoLabel">16</span> </div> <div class="gp-slider-row d-flex align-items-center gap-2"> <span class="small text-muted">8</span> <input id="tamanho" type="range" min="8" max="128" value="16" aria-label="Tamanho da senha"> <span class="small text-muted">128</span> </div> </div> <div class="mb-3"> <div class="gp-label-bold mb-2">Tipos de caracteres</div> <div class="d-flex flex-wrap gap-2" id="charsetToggles"> <label class="gp-toggle active" data-set="upper"> <input type="checkbox" checked> Maiúsculas <code class="small">A–Z</code> </label> <label class="gp-toggle active" data-set="lower"> <input type="checkbox" checked> Minúsculas <code class="small">a–z</code> </label> <label class="gp-toggle active" data-set="digits"> <input type="checkbox" checked> Números <code class="small">0–9</code> </label> <label class="gp-toggle active" data-set="symbols"> <input type="checkbox" checked> Símbolos <code class="small">!@#…</code> </label> </div> </div> <div class="mb-4"> <div class="gp-label-bold mb-2">Opções extras</div> <div class="d-flex flex-wrap gap-3"> <label class="form-check-label small d-flex align-items-center gap-1" style="cursor:pointer;"> <input type="checkbox" id="optAmbig" class="form-check-input m-0"> Excluir ambíguos <code class="small">0Ol1I|</code> </label> <label class="form-check-label small d-flex align-items-center gap-1" style="cursor:pointer;"> <input type="checkbox" id="optSimilar" class="form-check-input m-0"> Excluir similares <code class="small">{}()[]\/"'`,;:.</code> </label> <label class="form-check-label small d-flex align-items-center gap-1" style="cursor:pointer;"> <input type="checkbox" id="optSemRepeat" class="form-check-input m-0"> Sem caracteres repetidos </label> </div> </div> <button id="gerar" type="button" class="btn btn-primary w-100 fw-semibold"> <i class="fas fa-magic"></i> Gerar Senha </button> </div> </div> <div class="card mb-3" id="cardMemorable" style="display:none;"> <div class="card-body"> <div class="gp-card-title mb-3"> <i class="fas fa-feather-alt text-primary"></i> Configurações — Memorável </div> <div class="mb-3"> <div class="gp-label-bold mb-2">Quantidade de palavras</div> <div class="d-flex flex-wrap gap-2" id="memWordsRow"> <button type="button" class="gp-pill active" data-val="1">1</button> <button type="button" class="gp-pill" data-val="2">2</button> <button type="button" class="gp-pill" data-val="3">3</button> </div> </div> <div class="mb-3"> <div class="gp-label-bold mb-2">Estilo das letras</div> <div class="d-flex flex-wrap gap-2" id="memCaseRow"> <button type="button" class="gp-pill active" data-val="title">Palavra</button> <button type="button" class="gp-pill" data-val="upper">PALAVRA</button> <button type="button" class="gp-pill" data-val="lower">palavra</button> </div> </div> <div class="mb-3"> <div class="gp-label-bold mb-2">Símbolo especial</div> <div class="d-flex flex-wrap gap-2" id="memSymRow"> <button type="button" class="gp-pill active" data-val="1">1 símbolo</button> <button type="button" class="gp-pill" data-val="2">2 símbolos</button> <button type="button" class="gp-pill" data-val="0">Sem símbolo</button> </div> </div> <div class="mb-4"> <div class="gp-label-bold mb-2">Quantidade de números</div> <div class="d-flex flex-wrap gap-2" id="memDigitsRow"> <button type="button" class="gp-pill" data-val="2">2</button> <button type="button" class="gp-pill active" data-val="4">4</button> <button type="button" class="gp-pill" data-val="6">6</button> <button type="button" class="gp-pill" data-val="0">Sem números</button> </div> </div> <button id="gerarMem" type="button" class="btn btn-primary w-100 fw-semibold"> <i class="fas fa-magic"></i> Gerar Senha Memorável </button> <div class="small text-muted bg-light border-start border-primary border-3 rounded-end px-3 py-2 mt-3"> <i class="fas fa-info-circle"></i> <strong>Exemplo:</strong> <code>Liberdade@4729</code> — uma palavra positiva + símbolo + números. Mais fácil de lembrar, ainda assim com boa segurança. </div> </div> </div> <div class="card mb-3"> <div class="card-body"> <div class="d-flex justify-content-between align-items-center mb-3"> <div class="gp-card-title"> <i class="fas fa-history text-primary"></i> Histórico da Sessão </div> <button id="clearHist" type="button" class="btn btn-sm btn-link text-danger text-decoration-none p-0"> <i class="fas fa-trash-alt"></i> Limpar </button> </div> <ul id="histList" class="list-unstyled mb-0"> <li class="text-center text-muted small py-3">Nenhuma senha gerada ainda.</li> </ul> </div> </div> <div class="card"> <div class="card-body"> <div class="gp-card-title mb-3"><i class="fas fa-shield-alt text-success"></i> Dicas de Segurança</div> <ul class="list-unstyled mb-0 small"> <li class="d-flex gap-2 py-1 border-bottom"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Senhas únicas:</strong> Use uma diferente para cada conta.</span></li> <li class="d-flex gap-2 py-1 border-bottom"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Tamanho recomendado (10–16+):</strong> Quanto mais longa, mais segura.</span></li> <li class="d-flex gap-2 py-1 border-bottom"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Combine tipos:</strong> Maiúsculas, minúsculas, números e símbolos.</span></li> <li class="d-flex gap-2 py-1 border-bottom"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Evite padrões:</strong> Sem datas, nomes ou sequências óbvias (123456, qwerty…).</span></li> <li class="d-flex gap-2 py-1 border-bottom"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Guarde com segurança:</strong> Use um gerenciador de senhas (Bitwarden, 1Password…).</span></li> <li class="d-flex gap-2 py-1"><i class="fas fa-check-circle text-success mt-1"></i><span><strong>Troque quando necessário:</strong> Não precisa trocar todo mês; troque se houver suspeita ou vazamento.</span></li> </ul> </div> </div> </div> <div class="gp-toast" id="toast"> <i class="fas fa-check-circle" style="color:#28a745;"></i> <span id="toastMsg">Copiado!</span> </div> <script> (function() { const PALAVRAS = [ 'Alegria', 'Felicidade', 'Gentileza', 'Honestidade', 'Liberdade', 'Nobreza', 'Plenitude', 'Sinceridade', 'Forca', 'Verdade', 'Brilho', 'Estrela', 'Harmonia', 'Melodia', 'Montanha', 'Natureza', 'Oceano', 'Parque', 'Piano', 'Planeta', 'Praia', 'Presente', 'Saudade', 'Sonho', 'Sorriso', 'Tempo', 'Terra', 'Bondade', 'Carisma', 'Charme', 'Cuidado', 'Humilde', 'Lealdade', 'Maravilha', 'Respeito', 'Sabedoria' ]; const SETS = { upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', lower: 'abcdefghijklmnopqrstuvwxyz', digits: '0123456789', symbols: '!@#$%^&*-_=+<>?/~', }; const MEM_SYMBOLS = '!@#$%&*'; const AMBIG = /[0Ol1I|]/g; const SIMILAR = /[{}()[\]\\/\"'`,.;:]/g; const $ = id => document.getElementById(id); const senhaGerada = $('senhaGerada'); const nvlSenha = $('nvlSenha'); const strengthFill = $('strengthFill'); const entropyVal = $('entropyVal'); const copiar = $('copiar'); const tamanho = $('tamanho'); const tamanhoLabel = $('tamanhoLabel'); const gerar = $('gerar'); const gerarMem = $('gerarMem'); const histList = $('histList'); const clearHist = $('clearHist'); const toast = $('toast'); const toastMsg = $('toastMsg'); const cardRandom = $('cardRandom'); const cardMem = $('cardMemorable'); let history = []; let mode = 'random'; let toastTimer; document.querySelectorAll('.gp-mode-tab').forEach(tab => { tab.addEventListener('click', () => { document.querySelectorAll('.gp-mode-tab').forEach(t => t.classList.remove( 'active')); tab.classList.add('active'); mode = tab.dataset.mode; if (mode === 'random') { cardRandom.style.display = ''; cardMem.style.display = 'none'; } else { cardRandom.style.display = 'none'; cardMem.style.display = ''; } gerarSenha(); }); }); document.querySelectorAll('#charsetToggles .gp-toggle').forEach(lbl => { lbl.addEventListener('click', () => { const cb = lbl.querySelector('input'); cb.checked = !cb.checked; lbl.classList.toggle('active', cb.checked); enforceAtLeastOne(lbl, cb); }); }); function enforceAtLeastOne(lbl, cb) { const active = document.querySelectorAll('#charsetToggles .gp-toggle.active'); if (active.length === 0) { cb.checked = true; lbl.classList.add('active'); } } function singleSelectRow(rowId) { const row = $(rowId); row.addEventListener('click', e => { const btn = e.target.closest('.gp-pill'); if (!btn) return; row.querySelectorAll('.gp-pill').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); } singleSelectRow('memWordsRow'); singleSelectRow('memCaseRow'); singleSelectRow('memSymRow'); singleSelectRow('memDigitsRow'); function getActiveVal(rowId) { const a = document.querySelector('#' + rowId + ' .gp-pill.active'); return a ? a.dataset.val : null; } tamanho.addEventListener('input', () => { tamanhoLabel.textContent = tamanho.value; if (senhaGerada.value && mode === 'random') gerarSenha(); }); gerar.addEventListener('click', gerarSenha); gerarMem.addEventListener('click', gerarSenha); copiar.addEventListener('click', () => { if (!senhaGerada.value) return; copyText(senhaGerada.value, 'Senha copiada!'); }); clearHist.addEventListener('click', () => { history = []; renderHistory(); }); function getRandomInt(max) { if (max <= 0) return 0; const arr = new Uint32Array(1); const limit = Math.floor(0x100000000 / max) * max; let r; do { crypto.getRandomValues(arr); r = arr[0]; } while (r >= limit); return r % max; } function pick(str) { return str[getRandomInt(str.length)]; } function shuffle(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = getRandomInt(i + 1); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } function buildPool() { const excAmbig = $('optAmbig').checked; const excSimilar = $('optSimilar').checked; let pool = ''; let required = []; document.querySelectorAll('#charsetToggles .gp-toggle.active').forEach(lbl => { const set = lbl.dataset.set; let chars = SETS[set]; if (excAmbig) chars = chars.replace(AMBIG, ''); if (excSimilar) chars = chars.replace(SIMILAR, ''); if (chars.length === 0) return; pool += chars; required.push(pick(chars)); }); return { pool, required }; } function gerarUmaAleatoria(length) { const noRepeat = $('optSemRepeat').checked; const { pool, required } = buildPool(); if (!pool) return null; const effectiveLen = Math.min(length, noRepeat ? pool.length : length); const chars = [...required]; if (noRepeat) { const available = pool.split(''); required.forEach(c => { const idx = available.indexOf(c); if (idx !== -1) available.splice(idx, 1); }); shuffle(available); for (let i = chars.length; i < effectiveLen; i++) { if (available.length === 0) break; chars.push(available.shift()); } } else { for (let i = chars.length; i < effectiveLen; i++) { chars.push(pool[getRandomInt(pool.length)]); } } return shuffle(chars).join(''); } function aplicarCase(word, style) { if (style === 'upper') return word.toUpperCase(); if (style === 'lower') return word.toLowerCase(); return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); } function gerarUmaMemoravel() { const numWords = parseInt(getActiveVal('memWordsRow')); const caseStyle = getActiveVal('memCaseRow'); const numSyms = parseInt(getActiveVal('memSymRow')); const numDigits = parseInt(getActiveVal('memDigitsRow')); const pool = [...PALAVRAS]; const words = []; for (let i = 0; i < numWords; i++) { if (pool.length === 0) break; const idx = getRandomInt(pool.length); words.push(aplicarCase(pool[idx], caseStyle)); pool.splice(idx, 1); } const syms = []; for (let i = 0; i < numSyms; i++) syms.push(pick(MEM_SYMBOLS)); let digits = ''; for (let i = 0; i < numDigits; i++) digits += getRandomInt(10); let result = ''; if (numSyms === 0) { result = words.join(''); result += digits; } else if (numSyms === 1) { result = words.join(''); result += syms[0]; result += digits; } else { if (words.length > 1) { const out = []; words.forEach((w, i) => { out.push(w); if (i < words.length - 1) out.push(syms[0]); }); result = out.join('') + syms[1] + digits; } else { result = words[0] + syms[0] + syms[1] + digits; } } return result || null; } function gerarSenha() { const s = mode === 'random' ? gerarUmaAleatoria(parseInt(tamanho.value, 10)) : gerarUmaMemoravel(); if (!s) { alert(mode === 'random' ? 'Selecione pelo menos um tipo de caractere!' : 'Configure ao menos uma palavra!'); return; } senhaGerada.value = s; avaliarForca(s); pushHistory(s); } function calcularEntropia(senha) { if (mode === 'memorable') { const numWords = parseInt(getActiveVal('memWordsRow')); const numSyms = parseInt(getActiveVal('memSymRow')); const numDigits = parseInt(getActiveVal('memDigitsRow')); let e = 0; e += numWords * Math.log2(PALAVRAS.length); e += numSyms * Math.log2(MEM_SYMBOLS.length); e += numDigits * Math.log2(10); return e; } const { pool } = buildPool(); const poolSize = pool ? pool.length : 1; return senha.length * Math.log2(poolSize); } function avaliarForca(senha) { const entropy = calcularEntropia(senha); let label = 'Muito Fraca', pct = 10, color = '#dc3545'; if (entropy >= 128) { label = 'Excelente'; pct = 100; color = '#28a745'; } else if (entropy >= 90) { label = 'Forte'; pct = 82; color = '#20c997'; } else if (entropy >= 60) { label = 'Boa'; pct = 62; color = '#ffc107'; } else if (entropy >= 40) { label = 'Média'; pct = 42; color = '#fd7e14'; } else if (entropy >= 25) { label = 'Fraca'; pct = 22; color = '#e83e3e'; } nvlSenha.textContent = label; nvlSenha.style.background = color; nvlSenha.style.color = '#fff'; strengthFill.style.width = pct + '%'; strengthFill.style.background = color; entropyVal.textContent = Math.round(entropy) + ' bits'; } function pushHistory(senha) { history.unshift({ senha, len: senha.length, ts: new Date(), mode }); if (history.length > 5) history.pop(); renderHistory(); } function renderHistory() { if (history.length === 0) { histList.innerHTML = '<li class="text-center text-muted small py-3">Nenhuma senha gerada ainda.</li>'; return; } histList.innerHTML = ''; history.forEach(({ senha, len, ts, mode: m }, idx) => { const li = document.createElement('li'); li.className = 'd-flex align-items-center gap-2 px-3 py-2 mb-1 bg-light border rounded'; const time = ts.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); const tag = m === 'memorable' ? '✨' : '🎲'; li.innerHTML = ` <span class="hist-pw">${escapeHtml(senha)}</span> <span class="small text-muted text-nowrap">${tag} ${len} chars · ${time}</span> <button class="btn btn-sm btn-link text-muted p-1" type="button" title="Copiar" aria-label="Copiar do histórico ${idx+1}"> <i class="fas fa-copy"></i> </button>`; li.querySelector('button').addEventListener('click', () => copyText(senha, 'Senha copiada!')); histList.appendChild(li); }); } function copyText(text, msg) { navigator.clipboard.writeText(text).then(() => showToast(msg)); } function showToast(msg) { clearTimeout(toastTimer); toastMsg.textContent = msg; toast.classList.add('show'); toastTimer = setTimeout(() => toast.classList.remove('show'), 2000); } function escapeHtml(s) { return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); } gerarSenha(); })(); </script> <?php $__env->stopSection(); ?> <?php echo $__env->make('layouts.pmar.theme', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/portal/resources/views/paginas/gerador-senha.blade.php ENDPATH**/ ?>
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.07 |
proxy
|
phpinfo
|
Settings