{"record":{"id":"76542712ac4bc470","repo":"tonhowtf/omniget","slug":"defina-pelo-menos-uma-senha","errorCode":null,"errorMessage":"defina pelo menos uma senha","messagePattern":"defina pelo menos uma senha","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pdf_write.rs","lineNumber":134,"sourceCode":"    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.\n        if doc.trailer.get(b\"ID\").is_err() {\n            use rand::RngExt;\n            let mut id = [0u8; 16];\n            rand::rng().fill(&mut id);\n            let id = hex::encode(id).into_bytes();\n            doc.trailer.set(\n                \"ID\",\n                Object::Array(vec![\n                    Object::string_literal(id.clone()),","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf_write.rs#L116-L152","documentation":"When adding/setting a password, password_one demands at least one of user_password or owner_password. If both strings are empty there is no secret to build an EncryptionState from, so the function bails with 'defina pelo menos uma senha'.","triggerScenarios":"Calling password with mode != \"remove\" and both opts.user_password and opts.owner_password empty strings.","commonSituations":"UI form submitted with blank password fields; caller defaults all PasswordOptions fields to empty strings; config file with unset password keys.","solutions":["Set opts.user_password to require a password to open, or opts.owner_password to lock permissions only","Validate in the caller/UI that at least one password field is non-empty before invoking","If the goal was only to remove a password, switch mode to \"remove\""],"exampleFix":"// before\nlet opts = PasswordOptions { mode: \"add\".into(), ..Default::default() };\npassword_one(&opts, input)?;\n// after\nlet opts = PasswordOptions { mode: \"add\".into(), user_password: \"s3cret\".into(), ..Default::default() };\nassert!(!opts.user_password.is_empty() || !opts.owner_password.is_empty());\npassword_one(&opts, input)?;","handlingStrategy":"validation","validationCode":"if opts.user_password.trim().is_empty() && opts.owner_password.trim().is_empty() {\n    anyhow::bail!(\"informe a senha do usuário ou do proprietário\");\n}","typeGuard":null,"tryCatchPattern":"match password_one(&opts, input) {\n    Ok(item) => item,\n    Err(e) if e.to_string().contains(\"defina pelo menos uma senha\") => {\n        eprintln!(\"informe user_password ou owner_password\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Require non-empty password fields in UI forms before submit","Never construct PasswordOptions with all-empty passwords for add/set modes","Trim passwords and reject whitespace-only values"],"tags":["pdf","validation","encryption","missing-argument"],"backgroundTag":"empty-required-field","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"}