{"record":{"id":"1bf55b9bde4f5859","repo":"tonhowtf/omniget","slug":"esse-pdf-n-o-tem-senha","errorCode":null,"errorMessage":"esse PDF não tem senha","messagePattern":"esse PDF não tem senha","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src-tauri/omniget-core/src/core/tools/pdf_write.rs","lineNumber":125,"sourceCode":"}\n\nfn load(input: &str, password: &str) -> anyhow::Result<Document> {\n    let doc = if password.is_empty() {\n        Document::load(input)\n    } else {\n        let bytes = std::fs::read(input)?;\n        Document::load_mem_with_options(&bytes, lopdf::LoadOptions::with_password(password))\n    };\n    doc.map_err(|e| anyhow!(\"não abri o PDF: {}\", e))\n}\n\nfn password_one(opts: &PasswordOptions, input: &str) -> anyhow::Result<WriteItem> {\n    let mut doc = load(input, &opts.current_password)?;\n    let pages = doc.get_pages().len();\n    let note;\n    if opts.mode == \"remove\" {\n        if !doc.is_encrypted() && opts.current_password.is_empty() {\n            return Err(anyhow!(\"esse PDF não tem senha\"));\n        }\n        // `load_mem_with_password` já devolve o documento decifrado; basta\n        // apagar o dicionário de cifra para o arquivo sair aberto.\n        doc.encryption_state = None;\n        doc.trailer.remove(b\"Encrypt\");\n        note = \"senha removida\".to_string();\n    } else {\n        if opts.user_password.is_empty() && opts.owner_password.is_empty() {\n            return Err(anyhow!(\"defina pelo menos uma senha\"));\n        }\n        let owner = if opts.owner_password.is_empty() {\n            opts.user_password.as_str()\n        } else {\n            opts.owner_password.as_str()\n        };\n        // A derivação da chave usa o /ID do arquivo. PDF gerado por\n        // ferramenta simples costuma não ter: sem isso a cifra falha com um\n        // \"decryption error\" que não diz nada.","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf_write.rs#L107-L143","documentation":"password_one in 'remove' mode requires an actually-encrypted document. If doc.is_encrypted() is false AND no current_password was supplied, there is nothing to strip, so the function returns 'esse PDF não tem senha' instead of pointlessly rewriting the file.","triggerScenarios":"Calling password with mode=\"remove\" on a PDF that has no encryption dictionary and no current_password set in PasswordOptions.","commonSituations":"User drags an unprotected PDF into a 'remove password' flow; a previous run already removed the password; caller misinterprets 'remove' mode as generic re-save.","solutions":["Check the PDF is actually encrypted before invoking (qpdf --show-encryption file.pdf, or doc.is_encrypted())","Only call password(mode=\"remove\") for documents reported as password-protected","If the intent was to add a password, use the add/set mode instead of \"remove\""],"exampleFix":"// before\npassword_one(&PasswordOptions { mode: \"remove\", ..Default::default() }, input)?;\n// after\nif is_pdf_encrypted(input) {\n    password_one(&PasswordOptions { mode: \"remove\", ..Default::default() }, input)?;\n}","handlingStrategy":"validation","validationCode":"if mode == \"remove\" && !is_pdf_encrypted(input) && current_password.is_empty() {\n    anyhow::bail!(\"nada a remover: o PDF já está aberto\");\n}","typeGuard":null,"tryCatchPattern":"match password_one(&opts, input) {\n    Ok(item) => item,\n    Err(e) if e.to_string().contains(\"não tem senha\") => Ok(WriteItem::noop(input)),\n    Err(e) => return Err(e),\n}","preventionTips":["Detect encryption (is_encrypted / qpdf --show-encryption) before remove mode","Treat 'already unprotected' as a no-op success in UI flows","Skip queueing unprotected files for password removal"],"tags":["pdf","encryption","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}