{"record":{"id":"e94ab579226f7a55","repo":"Dolibarr/dolibarr","slug":"bad-link-missing-identification-to-find-file-original-file","errorCode":null,"errorMessage":"Bad link. Missing identification to find file (original_file or hashp)","messagePattern":"Bad link\\. Missing identification to find file \\(original_file or hashp\\)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"htdocs/document.php","lineNumber":156,"sourceCode":" * @var User $user\n */\nrequire_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';\nrequire_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';\n\n$encoding = '';\n$action = GETPOST('action', 'aZ09');\n$original_file = GETPOST('file', 'alphanohtml');\n$hashp = GETPOST('hashp', 'aZ09');\n$modulepart = GETPOST('modulepart', 'alpha');\n$urlsource = GETPOST('urlsource', 'alpha');\n$entity = ($entity > 0 ? $entity : $conf->entity);\n\n// Security check\nif (empty($modulepart) && empty($hashp)) {\n\thttponly_accessforbidden('Bad link. Bad value for parameter modulepart', 400);\n}\nif (empty($original_file) && empty($hashp)) {\n\thttponly_accessforbidden('Bad link. Missing identification to find file (original_file or hashp)', 400);\n}\nif ($hashp == 'shared') {\n\thttponly_accessforbidden('Bad link. Bad value for parameter hashp', 400);\n}\nif ($modulepart == 'fckeditor') {\n\t$modulepart = 'medias'; // For backward compatibility\n}\n\n$socid = 0;\nif ($user->socid > 0) {\n\t$socid = $user->socid;\n}\n\n// For some module part, dir may be privates\nif (in_array($modulepart, array('facture_paiement', 'unpaid'))) {\n\tif (!$user->hasRight('societe', 'client', 'voir')) {\n\t\t$original_file = 'private/'.$user->id.'/'.$original_file; // If user has no permission to see all, output dir is specific to user\n\t}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/document.php#L138-L174","documentation":"document.php requires a way to identify the file: either original_file (path relative to the module's document dir) or hashp (public shared-hash). If both are empty the security check calls httponly_accessforbidden() with this message and HTTP 400.","triggerScenarios":"document.php called with a modulepart but neither original_file nor hashp, e.g. document.php?modulepart=facture — the check `empty($original_file) && empty($hashp)` triggers.","commonSituations":"Links built without the filename; original_file dropped by URL rewriting or sanitization; copy-pasted URLs missing query params; custom code that forgot original_file when modulepart is present.","solutions":["Add original_file=<relative path> to the document.php URL","Or use hashp=<shared hash> for public share links","Ensure the parameter survives any routing/rewrite layer (check for stripped query strings)","Verify the generating code includes the file path (e.g. from ecmdocs or the object's last_main_doc)"],"exampleFix":"// before\ndocument.php?modulepart=ecm\n// after\ndocument.php?modulepart=ecm&original_file=myfile.pdf","handlingStrategy":"validation","validationCode":"if (empty($_GET['original_file']) && empty($_GET['hashp'])) {\n  http_response_code(400); exit('original_file or hashp required');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include original_file (or hashp) whenever modulepart is present","Test generated links end-to-end after template changes","Beware URL rewriters stripping empty-looking parameters","Source file paths from the object record (last_main_doc) not user input"],"tags":["http-400","download","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"598aa4bdada683d17ca04b1842548821ff0eb6c6","analyzedAt":"2026-09-14T11:12:15.309Z","contentChangedAt":"2026-09-14T11:12:15.309Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}