diff --git a/src/models/proof.ts b/src/models/proof.ts index eff1465..619ca40 100644 --- a/src/models/proof.ts +++ b/src/models/proof.ts @@ -110,14 +110,21 @@ type FlagValue = { const pathsC2PASource = (): FlagValue[] => { return [ - {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:Make", transform: getExifMakeModel }, - {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:Model", transform: getExifMakeModel }, + {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:Make", transform: getExifMakeModelPrefixed }, + {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:Model", transform: getExifMakeModelPrefixed }, {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=c2pa.actions|c2pa.actions.v2]/data/actions[action=c2pa.created]/softwareAgent/name"}, {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=c2pa.actions|c2pa.actions.v2]/data/actions[action=c2pa.created]/softwareAgent"}, {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=c2pa.actions|c2pa.actions.v2]/data/actions[action=c2pa.created]/../../../claim_generator"} ]; }; +const pathsExifSource = (): FlagValue[] => { + return [ + {path: "integrity/exif/Make", transform: getExifMakeModelNoPrefix }, + {path: "integrity/exif/Model", transform: getExifMakeModelNoPrefix } + ]; +}; + const pathsC2PACreationDate = (): FlagValue[] => { return [ {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=c2pa.actions|c2pa.actions.v2]/data/actions[action=c2pa.created]/when"}, @@ -131,6 +138,20 @@ const pathsC2PACreationDate = (): FlagValue[] => { ]; } +const pathsC2PACamera = (): FlagValue[] => { + return [ + {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensMake"}, + {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensModel"}, + ]; +}; + +const pathsExifCamera = (): FlagValue[] => { + return [ + {path: "integrity/exif/LensMake"}, + {path: "integrity/exif/LensModel"}, + ]; +}; + const getExifValue = (val: string): string => { return val.replace(/^"(.+(?="$))"$/, "$1"); }; @@ -146,19 +167,27 @@ const pathsExifCreationDate = (): FlagValue[] => { ]; } -const getExifMakeModel = (ignoredvalue: any, match: FlagMatchRuleValue): string => { +const getExifMakeModelNoPrefix = (ignoredvalue: any, match: FlagMatchRuleValue): string => { + return getExifMakeModel(match, ""); +} + +const getExifMakeModelPrefixed = (ignoredvalue: any, match: FlagMatchRuleValue): string => { + return getExifMakeModel(match, "exif:"); +} + +const getExifMakeModel = (match: FlagMatchRuleValue, prefix: string): string => { // Make and model let makeAndModel = ""; - const make = extractFlagValues("../exif:Make", match.path)?.at(0)?.value as string; - const model = extractFlagValues("../exif:Model", match.path)?.at(0)?.value as string; + const make = extractFlagValues(`../${prefix}Make`, match.path)?.at(0)?.value as string; + const model = extractFlagValues(`../${prefix}Model`, match.path)?.at(0)?.value as string; if (make) { - makeAndModel += make; + makeAndModel += getExifValue(make); } if (model) { if (makeAndModel.length > 0) { makeAndModel += ", "; } - makeAndModel += model; + makeAndModel += getExifValue(model); } return makeAndModel; } @@ -361,6 +390,10 @@ export const extractProofHintFlags = (proof?: Proof): ProofHintFlags | undefined let dateCreatedSource: ProofHintFlagSource | undefined = undefined; source = getFirstWithData(pathsC2PASource(), rootMatchPath); + if (!source) { + source = getFirstWithData(pathsExifSource(), rootMatchPath); + } + dateCreated = getFirstWithDataAsDate(pathsC2PACreationDate(), rootMatchPath); if (dateCreated) { dateCreatedSource = "c2pa"; @@ -385,6 +418,12 @@ export const extractProofHintFlags = (proof?: Proof): ProofHintFlags | undefined } else if ([C2PASourceTypeTrainedAlgorithmicMedia, C2PASourceTypeCompositeWithTrainedAlgorithmicMedia].includes(digitalSourceType)) { generator = "ai"; generatorSource = "c2pa"; + } else if (getFirstWithData(pathsC2PACamera(), rootMatchPath)) { + generator = "camera"; + generatorSource = "c2pa"; + } else if (getFirstWithData(pathsExifCamera(), rootMatchPath)) { + generator = "camera"; + generatorSource = "exif"; } else if (matchFlag(ruleScreenshotMeta(), rootMatchPath).result) { generator = "screenshot"; generatorSource = "metadata";