50 | 51 |
About Us
52 | 53 |54 | 55 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/Acknowledgements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Metaforge
26 |

27 | 28 |
"A metadata analyzer that creates dynamic reports with a unique filter"
29 |50 | 51 |
Acknowledgements
52 | 53 |Thanks to...
54 |
62 | 63 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/CustomTags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Metaforge
26 |

27 | 28 |
"A metadata analyzer that creates dynamic reports with a unique filter"
29 |50 | 51 |
Adding your own Tags!
52 |With each file type comes countless different tags. If you are looking for some specific tag, this page is dedicated to showing you how to add tags into the filter so you can get what you want.
53 |This section will include a step-by-step guide in retreiving tags manually, picking out the tags you want, and where to find them in the HTML report that Metaforge produces.
54 |55 | 56 |
Exiftool and Retreiving Metadata Manually
57 |-
58 |
- Choose the file type you want to work with and download a good number of files of that type for metadata gathering purposes. 59 |
- Google searches can be helpful here. Random files can be found using "inurl: .(extension type here)" 60 |
- After gathering your sample files, place them in one local place and run the command: 61 |
- This command prints them in JSON format (very important to use the -j param) and prints the output to a text file 63 |
- Open up a notepad as you will now be collecting the tags you want to collect from your chosen file type. It is recommended that you name the file after your file type that you are collecting the tags from. 64 |
- Sort through the newly created file "alltags.txt" for the file type that you selected, as this will contain all the raw metadata for each file. 65 |
- Record each tag you would like to have added to the CustomTags section of the HTML report generated by Metaforge in your open notepad for easy transfer. 66 |
- Examples of tags are "Composite:ImageSize", "System:FileModifyDate", "IFDO:Copyright". 67 |
exiftool -j -G * > alltags.txt
62 |
68 | 69 |
Adding Tags to the Custom Tags
70 |-
71 |
- Open up "markup.py" with your editor of choice and proceed to line 34 in the code.
- Do not remove the PLACEHOLDER or DELETE_ME 74 |
- Following the same "", format, continue adding tags after the DELETE_ME with a coma and opening the new tag with quotations. 75 |
- The last tag added should not include a coma but should include a closing parenthesis. 76 |
72 |

73 |
79 | 80 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/FAQs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Metaforge
26 |

27 | 28 |
"A metadata analyzer that creates dynamic reports with a unique filter"
29 |51 | 52 |
FAQ's
53 | 54 |57 |
60 |
63 | 64 |
65 | 66 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /docs/Metaforge-1.3.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriswmorris/Metaforge/7b326932d21abdce93de696bf629c17e83cbe350/docs/Metaforge-1.3.tar.gz -------------------------------------------------------------------------------- /docs/Metaforge-1.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriswmorris/Metaforge/7b326932d21abdce93de696bf629c17e83cbe350/docs/Metaforge-1.3.zip -------------------------------------------------------------------------------- /docs/images/AddCustomTag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriswmorris/Metaforge/7b326932d21abdce93de696bf629c17e83cbe350/docs/images/AddCustomTag.png -------------------------------------------------------------------------------- /docs/images/blacktocat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 48 | -------------------------------------------------------------------------------- /docs/images/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriswmorris/Metaforge/7b326932d21abdce93de696bf629c17e83cbe350/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriswmorris/Metaforge/7b326932d21abdce93de696bf629c17e83cbe350/docs/images/screenshot.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Metaforge
27 |

28 | 29 |
"A metadata analyzer that creates dynamic reports with a unique filter"
30 |50 | 51 |
Introduction
52 |This GitHub Page is dedicated to our Senior Design Project that will be presented at the IT expo. We created this site to provide more information about metadata, provide a download link for Metaforge, provide requirements for the installation, as well as a step-by-step guide on how to use Metaforge.
53 |54 | 55 | 56 |
What is "metadata"?
57 | 58 |To put it simply, metadata is just information about data. The information comes from the tags that capture valuable information about each specific file. Each file has can have many different tags of data that can be retreived for multiple purposes.
59 |The uses for metadata are endless and can prove valuable to those in the information security fields for pentesting and gathering information, like who created the file and what software was used to edit it.
60 |61 | 62 | 63 | 64 |
Metaforge Checklist
65 |-
66 |
- Must have a Unix-based Operating System (Arch, Debian, and RHEL Linux distros have been tested and also Mac OSX) 67 |
- Must have at least Python3.5 or higher 68 |
- Must place all data you wish to analyze in the /media directory. Cannot place folders within the /media directory. 69 |
71 | 72 | 73 |
Install Requirements
74 |1.1 Install Exiftool
75 |In order for Metaforge to work, you must install exiftool first. Also, if you install the requirements.txt first, it won’t work because pyexifinfo requires exiftool to install.
76 |So to install exiftool, run the following based on your OS.
77 |Note: you might need to run these commands as root! So run…
78 |sudo apt/yum/pacman...
79 | 80 | 81 | 82 |
Debian-based
83 |apt install libimage-exiftool-perl
84 |
85 | RHEL-based
86 |yum install perl-Image-ExifTool
87 |
88 | Arch Linux
89 |pacman -S perl-image-exiftool
90 |
91 | Mac OSX
92 |brew install exiftool
93 | 94 | 95 |
1.2 Install Dependencies
96 | 97 |Install the libraries that we used to create Metaforge. Make sure that you’re using pip3! If you don’t know how, here is some help.
98 |-
99 |
- https://www.tecmint.com/install-pip-in-linux/ 100 |
pip3 install -r requirements.txt
102 |
103 | If this doesn’t work, try to install each individual package and report the error message you got and we can help!
104 |105 | 106 |
Running Metaforge
107 |-
108 |
- Place the files you wish to analyze in the /media directory 109 |
- Run metaforge.py 110 |
python3 metaforge.py
112 |
113 | Note: If you want to make it easier to run multiple times, run these commands…
114 |chmod +x metaforge.py
115 |
./metaforge.py
116 | 117 | 118 | 119 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /docs/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.3 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /** 8 | * Correct `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | main, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | 26 | /** 27 | * Correct `inline-block` display not defined in IE 8/9. 28 | */ 29 | 30 | audio, 31 | canvas, 32 | video { 33 | display: inline-block; 34 | } 35 | 36 | /** 37 | * Prevent modern browsers from displaying `audio` without controls. 38 | * Remove excess height in iOS 5 devices. 39 | */ 40 | 41 | audio:not([controls]) { 42 | display: none; 43 | height: 0; 44 | } 45 | 46 | /** 47 | * Address `[hidden]` styling not present in IE 8/9. 48 | * Hide the `template` element in IE, Safari, and Firefox < 22. 49 | */ 50 | 51 | [hidden], 52 | template { 53 | display: none; 54 | } 55 | 56 | /* ========================================================================== 57 | Base 58 | ========================================================================== */ 59 | 60 | /** 61 | * 1. Set default font family to sans-serif. 62 | * 2. Prevent iOS text size adjust after orientation change, without disabling 63 | * user zoom. 64 | */ 65 | 66 | html { 67 | font-family: sans-serif; /* 1 */ 68 | -ms-text-size-adjust: 100%; /* 2 */ 69 | -webkit-text-size-adjust: 100%; /* 2 */ 70 | } 71 | 72 | /** 73 | * Remove default margin. 74 | */ 75 | 76 | body { 77 | margin: 0; 78 | } 79 | 80 | /* ========================================================================== 81 | Links 82 | ========================================================================== */ 83 | 84 | /** 85 | * Remove the gray background color from active links in IE 10. 86 | */ 87 | 88 | a { 89 | background: transparent; 90 | } 91 | 92 | /** 93 | * Address `outline` inconsistency between Chrome and other browsers. 94 | */ 95 | 96 | a:focus { 97 | outline: thin dotted; 98 | } 99 | 100 | /** 101 | * Improve readability when focused and also mouse hovered in all browsers. 102 | */ 103 | 104 | a:active, 105 | a:hover { 106 | outline: 0; 107 | } 108 | 109 | /* ========================================================================== 110 | Typography 111 | ========================================================================== */ 112 | 113 | /** 114 | * Address variable `h1` font-size and margin within `section` and `article` 115 | * contexts in Firefox 4+, Safari 5, and Chrome. 116 | */ 117 | 118 | h1 { 119 | font-size: 2em; 120 | margin: 0.67em 0; 121 | } 122 | 123 | /** 124 | * Address styling not present in IE 8/9, Safari 5, and Chrome. 125 | */ 126 | 127 | abbr[title] { 128 | border-bottom: 1px dotted; 129 | } 130 | 131 | /** 132 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 133 | */ 134 | 135 | b, 136 | strong { 137 | font-weight: bold; 138 | } 139 | 140 | /** 141 | * Address styling not present in Safari 5 and Chrome. 142 | */ 143 | 144 | dfn { 145 | font-style: italic; 146 | } 147 | 148 | /** 149 | * Address differences between Firefox and other browsers. 150 | */ 151 | 152 | hr { 153 | -moz-box-sizing: content-box; 154 | box-sizing: content-box; 155 | height: 0; 156 | } 157 | 158 | /** 159 | * Address styling not present in IE 8/9. 160 | */ 161 | 162 | mark { 163 | background: #ff0; 164 | color: #000; 165 | } 166 | 167 | /** 168 | * Correct font family set oddly in Safari 5 and Chrome. 169 | */ 170 | 171 | code, 172 | kbd, 173 | pre, 174 | samp { 175 | font-family: monospace, serif; 176 | font-size: 1em; 177 | } 178 | 179 | /** 180 | * Improve readability of pre-formatted text in all browsers. 181 | */ 182 | 183 | pre { 184 | white-space: pre-wrap; 185 | } 186 | 187 | /** 188 | * Set consistent quote types. 189 | */ 190 | 191 | q { 192 | quotes: "\201C" "\201D" "\2018" "\2019"; 193 | } 194 | 195 | /** 196 | * Address inconsistent and variable font size in all browsers. 197 | */ 198 | 199 | small { 200 | font-size: 80%; 201 | } 202 | 203 | /** 204 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 205 | */ 206 | 207 | sub, 208 | sup { 209 | font-size: 75%; 210 | line-height: 0; 211 | position: relative; 212 | vertical-align: baseline; 213 | } 214 | 215 | sup { 216 | top: -0.5em; 217 | } 218 | 219 | sub { 220 | bottom: -0.25em; 221 | } 222 | 223 | /* ========================================================================== 224 | Embedded content 225 | ========================================================================== */ 226 | 227 | /** 228 | * Remove border when inside `a` element in IE 8/9. 229 | */ 230 | 231 | img { 232 | border: 0; 233 | } 234 | 235 | /** 236 | * Correct overflow displayed oddly in IE 9. 237 | */ 238 | 239 | svg:not(:root) { 240 | overflow: hidden; 241 | } 242 | 243 | /* ========================================================================== 244 | Figures 245 | ========================================================================== */ 246 | 247 | /** 248 | * Address margin not present in IE 8/9 and Safari 5. 249 | */ 250 | 251 | figure { 252 | margin: 0; 253 | } 254 | 255 | /* ========================================================================== 256 | Forms 257 | ========================================================================== */ 258 | 259 | /** 260 | * Define consistent border, margin, and padding. 261 | */ 262 | 263 | fieldset { 264 | border: 1px solid #c0c0c0; 265 | margin: 0 2px; 266 | padding: 0.35em 0.625em 0.75em; 267 | } 268 | 269 | /** 270 | * 1. Correct `color` not being inherited in IE 8/9. 271 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 272 | */ 273 | 274 | legend { 275 | border: 0; /* 1 */ 276 | padding: 0; /* 2 */ 277 | } 278 | 279 | /** 280 | * 1. Correct font family not being inherited in all browsers. 281 | * 2. Correct font size not being inherited in all browsers. 282 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. 283 | */ 284 | 285 | button, 286 | input, 287 | select, 288 | textarea { 289 | font-family: inherit; /* 1 */ 290 | font-size: 100%; /* 2 */ 291 | margin: 0; /* 3 */ 292 | } 293 | 294 | /** 295 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 296 | * the UA stylesheet. 297 | */ 298 | 299 | button, 300 | input { 301 | line-height: normal; 302 | } 303 | 304 | /** 305 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 306 | * All other form control elements do not inherit `text-transform` values. 307 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. 308 | * Correct `select` style inheritance in Firefox 4+ and Opera. 309 | */ 310 | 311 | button, 312 | select { 313 | text-transform: none; 314 | } 315 | 316 | /** 317 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 318 | * and `video` controls. 319 | * 2. Correct inability to style clickable `input` types in iOS. 320 | * 3. Improve usability and consistency of cursor style between image-type 321 | * `input` and others. 322 | */ 323 | 324 | button, 325 | html input[type="button"], /* 1 */ 326 | input[type="reset"], 327 | input[type="submit"] { 328 | -webkit-appearance: button; /* 2 */ 329 | cursor: pointer; /* 3 */ 330 | } 331 | 332 | /** 333 | * Re-set default cursor for disabled elements. 334 | */ 335 | 336 | button[disabled], 337 | html input[disabled] { 338 | cursor: default; 339 | } 340 | 341 | /** 342 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 343 | * 2. Remove excess padding in IE 8/9/10. 344 | */ 345 | 346 | input[type="checkbox"], 347 | input[type="radio"] { 348 | box-sizing: border-box; /* 1 */ 349 | padding: 0; /* 2 */ 350 | } 351 | 352 | /** 353 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 354 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 355 | * (include `-moz` to future-proof). 356 | */ 357 | 358 | input[type="search"] { 359 | -webkit-appearance: textfield; /* 1 */ 360 | -moz-box-sizing: content-box; 361 | -webkit-box-sizing: content-box; /* 2 */ 362 | box-sizing: content-box; 363 | } 364 | 365 | /** 366 | * Remove inner padding and search cancel button in Safari 5 and Chrome 367 | * on OS X. 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Remove inner padding and border in Firefox 4+. 377 | */ 378 | 379 | button::-moz-focus-inner, 380 | input::-moz-focus-inner { 381 | border: 0; 382 | padding: 0; 383 | } 384 | 385 | /** 386 | * 1. Remove default vertical scrollbar in IE 8/9. 387 | * 2. Improve readability and alignment in all browsers. 388 | */ 389 | 390 | textarea { 391 | overflow: auto; /* 1 */ 392 | vertical-align: top; /* 2 */ 393 | } 394 | 395 | /* ========================================================================== 396 | Tables 397 | ========================================================================== */ 398 | 399 | /** 400 | * Remove most spacing between table cells. 401 | */ 402 | 403 | table { 404 | border-collapse: collapse; 405 | border-spacing: 0; 406 | } 407 | -------------------------------------------------------------------------------- /docs/stylesheets/pygment_trac.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #f0f3f3; } 3 | .highlight .c { color: #0099FF; font-style: italic } /* Comment */ 4 | .highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ 5 | .highlight .k { color: #006699; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #555555 } /* Operator */ 7 | .highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ 8 | .highlight .cp { color: #009999 } /* Comment.Preproc */ 9 | .highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ 10 | .highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ 11 | .highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 14 | .highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ 15 | .highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ 16 | .highlight .go { color: #AAAAAA } /* Generic.Output */ 17 | .highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ 18 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 19 | .highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ 20 | .highlight .gt { color: #99CC66 } /* Generic.Traceback */ 21 | .highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ 22 | .highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ 23 | .highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ 24 | .highlight .kp { color: #006699 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ 27 | .highlight .m { color: #FF6600 } /* Literal.Number */ 28 | .highlight .s { color: #CC3300 } /* Literal.String */ 29 | .highlight .na { color: #330099 } /* Name.Attribute */ 30 | .highlight .nb { color: #336666 } /* Name.Builtin */ 31 | .highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #336600 } /* Name.Constant */ 33 | .highlight .nd { color: #9999FF } /* Name.Decorator */ 34 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ 35 | .highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ 36 | .highlight .nf { color: #CC00FF } /* Name.Function */ 37 | .highlight .nl { color: #9999FF } /* Name.Label */ 38 | .highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ 39 | .highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ 40 | .highlight .nv { color: #003333 } /* Name.Variable */ 41 | .highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ 42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .highlight .mf { color: #FF6600 } /* Literal.Number.Float */ 44 | .highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ 45 | .highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ 46 | .highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ 47 | .highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ 48 | .highlight .sc { color: #CC3300 } /* Literal.String.Char */ 49 | .highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ 50 | .highlight .s2 { color: #CC3300 } /* Literal.String.Double */ 51 | .highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ 52 | .highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ 53 | .highlight .si { color: #AA0000 } /* Literal.String.Interpol */ 54 | .highlight .sx { color: #CC3300 } /* Literal.String.Other */ 55 | .highlight .sr { color: #33AAAA } /* Literal.String.Regex */ 56 | .highlight .s1 { color: #CC3300 } /* Literal.String.Single */ 57 | .highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ 58 | .highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ 59 | .highlight .vc { color: #003333 } /* Name.Variable.Class */ 60 | .highlight .vg { color: #003333 } /* Name.Variable.Global */ 61 | .highlight .vi { color: #003333 } /* Name.Variable.Instance */ 62 | .highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ 63 | 64 | .type-csharp .highlight .k { color: #0000FF } 65 | .type-csharp .highlight .kt { color: #0000FF } 66 | .type-csharp .highlight .nf { color: #000000; font-weight: normal } 67 | .type-csharp .highlight .nc { color: #2B91AF } 68 | .type-csharp .highlight .nn { color: #000000 } 69 | .type-csharp .highlight .s { color: #A31515 } 70 | .type-csharp .highlight .sc { color: #A31515 } 71 | -------------------------------------------------------------------------------- /docs/stylesheets/stylesheet.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Slate Theme for GitHub Pages 3 | by Jason Costello, @jsncostello 4 | *******************************************************************************/ 5 | 6 | @import url(normalize.css); 7 | @import url(pygment_trac.css); 8 | 9 | /******************************************************************************* 10 | Theme Styles 11 | *******************************************************************************/ 12 | 13 | *, *:before, *:after { 14 | -moz-box-sizing: border-box; 15 | -webkit-box-sizing: border-box; 16 | box-sizing: border-box; 17 | } 18 | 19 | body { 20 | color:#373737; 21 | background: #212121; 22 | font-size: 18px; 23 | font-family: "Roboto", Helvetica, Arial, sans-serif; 24 | line-height: 1.5; 25 | -webkit-font-smoothing: antialiased; 26 | } 27 | 28 | h1, h2, h3, h4, h5, h6 { 29 | font-family: "Roboto Condensed", Helvetica, Arial, sans-serif; 30 | margin: 10px 0; 31 | font-weight: 700; 32 | color:#222222; 33 | } 34 | 35 | h1 { 36 | margin-bottom: 20px; 37 | font-size: 36px; 38 | line-height: 1.1; 39 | font-weight: 700; 40 | } 41 | 42 | h1#project_title { 43 | text-transform: uppercase; 44 | } 45 | 46 | h2 { 47 | font-size: 32px; 48 | line-height: 1.2; 49 | } 50 | 51 | h3 { 52 | margin-bottom: 0; 53 | padding-bottom: 0; 54 | font-size: 24px; 55 | line-height: 1.3; 56 | } 57 | 58 | h4 { 59 | margin-bottom: 0; 60 | padding-bottom: 0; 61 | font-size: 21px; 62 | } 63 | 64 | h5 { 65 | margin-bottom: 0; 66 | padding-bottom: 0; 67 | font-size: 18px; 68 | } 69 | 70 | h6 { 71 | margin-bottom: 0; 72 | padding-bottom: 0; 73 | font-size: 16px; 74 | } 75 | 76 | p { 77 | font-family: "Roboto Slab", 78 | font-size: 18px; 79 | margin: 0px 0 15px 0; 80 | } 81 | 82 | footer p { 83 | color: #f2f2f2; 84 | } 85 | 86 | a { 87 | display: inline-block; 88 | text-decoration: none; 89 | border-bottom: 1px dotted #666; 90 | color: inherit; 91 | text-shadow: none; 92 | } 93 | 94 | a:hover, a:focus {border-bottom: 1px solid #0090ff;} 95 | 96 | 97 | em { 98 | font-style: italic; 99 | } 100 | 101 | strong { 102 | font-weight: bold; 103 | } 104 | 105 | img { 106 | position: relative; 107 | margin: 0 auto; 108 | max-width: 739px; 109 | padding: 5px; 110 | margin: 10px 0 10px 0; 111 | 112 | 113 | -webkit-box-shadow: 0 0 5px #ebebeb; 114 | -moz-box-shadow: 0 0 5px #ebebeb; 115 | -o-box-shadow: 0 0 5px #ebebeb; 116 | -ms-box-shadow: 0 0 5px #ebebeb; 117 | } 118 | 119 | p img { 120 | display: inline; 121 | margin: 0; 122 | padding: 0; 123 | vertical-align: middle; 124 | text-align: center; 125 | border: none; 126 | } 127 | 128 | pre, code { 129 | width: 100%; 130 | color: #fff; 131 | background-color: #222; 132 | 133 | font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; 134 | font-size: 14px; 135 | 136 | 137 | box-shadow: 0 0 10px rgba(0,0,0,.1); 138 | } 139 | 140 | pre { 141 | padding: 10px 20px; 142 | overflow: auto; 143 | } 144 | 145 | code { 146 | padding: 3px; 147 | margin: 0 3px; 148 | } 149 | 150 | pre code { 151 | display: block; 152 | box-shadow: none; 153 | } 154 | 155 | blockquote { 156 | color: #666; 157 | margin: 0 0 20px 2px; 158 | padding-left: 20px; 159 | border-left: 3px solid #bbb; 160 | font-style: italic; 161 | } 162 | 163 | ul, ol, dl { 164 | margin: 0 0 15px 0; 165 | padding-left: 20px; 166 | } 167 | 168 | dl dt { 169 | font-weight: bold; 170 | } 171 | 172 | dl dd { 173 | margin-left: 0; 174 | padding-left: 0; 175 | font-style: italic; 176 | } 177 | 178 | dl p { 179 | padding-left: 20px; 180 | font-style: italic; 181 | } 182 | 183 | hr { 184 | height: 1px; 185 | margin-bottom: 5px; 186 | border: none; 187 | background: url('../images/bg_hr.png') repeat-x center; 188 | } 189 | 190 | table { 191 | border: 1px solid #373737; 192 | margin-bottom: 20px; 193 | text-align: left; 194 | } 195 | 196 | th { 197 | padding: 10px; 198 | background: #222; 199 | color: #fff; 200 | } 201 | 202 | td { 203 | padding: 10px; 204 | border: 1px solid #222; 205 | } 206 | 207 | form { 208 | background: #f2f2f2; 209 | padding: 20px; 210 | } 211 | 212 | /******************************************************************************* 213 | Full-Width Styles 214 | *******************************************************************************/ 215 | 216 | .outer { 217 | width: 100%; 218 | padding: 0 10px; 219 | } 220 | 221 | .inner { 222 | position: relative; 223 | max-width: 960px; 224 | padding: 20px 10px; 225 | margin: 0 auto; 226 | } 227 | 228 | #forkme_banner { 229 | display: block; 230 | position: absolute; 231 | top:0; 232 | right: 10px; 233 | z-index: 10; 234 | padding: 10px 20px 10px 50px; 235 | color: #fff; 236 | background: url('../images/blacktocat.svg') #0090ff no-repeat 8% 50%; 237 | background-size: 25px; 238 | font-weight: 700; 239 | border: none; 240 | } 241 | 242 | #forkme_banner:hover { 243 | background-color: #1883ed; 244 | } 245 | 246 | header { 247 | color: #f2f2f2; 248 | } 249 | 250 | #header_wrap { 251 | background: #212121; 252 | } 253 | 254 | #header_wrap .inner { 255 | padding: 60px 10px 0px 0px; 256 | } 257 | 258 | #project_title { 259 | margin: 0; 260 | color: #fff; 261 | font-size: 54px; 262 | font-weight: 700; 263 | } 264 | 265 | #project_tagline { 266 | color: #fff; 267 | font-size: 36px; 268 | font-weight: 300; 269 | background: none; 270 | } 271 | 272 | .downloads { 273 | display: block; 274 | padding-left: 50px; 275 | color: #f2f2f2; 276 | position: relative; 277 | height: 70px; 278 | background: url(../images/download.svg) no-repeat center left; 279 | background-size: 25px 20px; 280 | } 281 | 282 | .downloads a { 283 | margin-right: 20px; 284 | } 285 | .downloads a:hover { 286 | text-decoration: underline solid #fff; 287 | } 288 | 289 | #main_content { 290 | padding-top: 40px; 291 | } 292 | 293 | #main_content.inner { 294 | background-color: #fff; 295 | padding: 70px 100px; 296 | box-shadow: 0 0 5px #ebebeb; 297 | -webkit-box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); 298 | -moz-box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); 299 | -o-box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); 300 | -ms-box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); 301 | } 302 | 303 | #footer_wrap { 304 | background: #212121; 305 | } 306 | 307 | /******************************************************************************* 308 | Small Device Styles 309 | *******************************************************************************/ 310 | 311 | @media screen and (max-width: 992px) { 312 | img { 313 | max-width: 100%; 314 | } 315 | } 316 | 317 | @media screen and (max-width: 480px) { 318 | body { 319 | font-size: 13px; 320 | } 321 | 322 | .downloads { 323 | display: none; 324 | } 325 | 326 | .outer { 327 | padding: 0; 328 | } 329 | 330 | .inner { 331 | min-width: 320px; 332 | max-width: 480px; 333 | } 334 | 335 | #header_wrap .inner { 336 | padding: 60px 10px; 337 | } 338 | 339 | #main_content.inner { 340 | padding: 10px; 341 | } 342 | 343 | #project_title { 344 | font-size: 32px; 345 | } 346 | 347 | h1 { 348 | font-size: 28px; 349 | } 350 | 351 | h2 { 352 | font-size: 24px; 353 | } 354 | 355 | h3 { 356 | font-size: 21px; 357 | } 358 | 359 | h4 { 360 | font-size: 18px; 361 | } 362 | 363 | h5 { 364 | font-size: 14px; 365 | } 366 | 367 | h6 { 368 | font-size: 12px; 369 | } 370 | 371 | code, pre { 372 | min-width: 320px; 373 | max-width: 480px; 374 | font-size: 11px; 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /exifdata/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /exiftool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import pyexifinfo as exif 4 | import os, sys 5 | import subprocess 6 | import json 7 | from os.path import basename 8 | from definitions import ROOT_DIR 9 | import shutil 10 | from progress.bar import Bar 11 | 12 | #This is the exiftool processor, it runs exiftool and puts the outputs in either 13 | #html, json or XML depending on which function is called. Exiftool needs to be installed for this 14 | #to work. 15 | 16 | 17 | #exiftool in JSON 18 | def exifJSON(): 19 | print("Running exiftool to JSON") 20 | os.chdir(ROOT_DIR + "/media/") 21 | mediadir = os.listdir() 22 | mediafiles = len(mediadir) 23 | jsonbar = Bar('Processing', max=mediafiles) 24 | for i in range(mediafiles): 25 | for filename in os.listdir("."): 26 | exifoutputjson = exif.get_json(filename) 27 | #basejson = os.path.basename(filename) 28 | os.chdir(ROOT_DIR + "/exifdata/json") 29 | #Prints output to json file 30 | print(json.dumps(exifoutputjson, sort_keys=True, indent=0, separators=(',', ': ')), 31 | file= open(filename + ".json","w")) 32 | #print(json.dumps(exifoutputjson, sort_keys=True, indent=0, separators=(',', ': ')), 33 | # file= open(os.path.splitext(basejson)[0]+".json","w")) 34 | 35 | jsonbar.next() 36 | os.chdir(ROOT_DIR + "/media") 37 | break 38 | jsonbar.finish() 39 | 40 | #exiftool in HTML 41 | def exifHTML(): 42 | print("Running exiftool to HTML") 43 | os.chdir(ROOT_DIR + "/media/") 44 | mediadir = os.listdir() 45 | mediafiles = len(mediadir) 46 | htmlbar = Bar('Processing', max=mediafiles) 47 | for i in range(mediafiles): 48 | for filename in os.listdir("."): 49 | #Prints output to HTML 50 | #basehtml = os.path.basename(filename) 51 | exifoutputhtml = exif.command_line(['exiftool', '-h', filename]) 52 | os.chdir(ROOT_DIR + "/exifdata/html") 53 | #print(exifoutputhtml,file = open(os.path.splitext(basehtml)[0]+ ".html", "w")) 54 | print(exifoutputhtml,file = open(filename + ".html","w")) 55 | htmlbar.next() 56 | os.chdir(ROOT_DIR + "/media") 57 | break 58 | htmlbar.finish() 59 | 60 | #exiftool hex dump to html 61 | def exifHTMLDump(): 62 | print("Running exiftool to HTML Dump") 63 | os.chdir(ROOT_DIR + "/media/") 64 | mediadir = os.listdir() 65 | mediafiles = len(mediadir) 66 | os.chdir(ROOT_DIR + "/media/") 67 | htmldumpbar = Bar('Processing', max=mediafiles) 68 | for i in range(mediafiles): 69 | for filename in os.listdir("."): 70 | #basehtmldump = os.path.basename(filename) 71 | exifoutputhtmldump = exif.command_line(['exiftool', '-htmlDump', filename]) 72 | os.chdir(ROOT_DIR + "/exifdata/hex_html") 73 | #htmldumpfile = open(os.path.splitext(basehtmldump)[0] + ".html", 'wb') 74 | htmldumpfile = open(filename + ".html", 'wb') 75 | htmldumpfile.write(exifoutputhtmldump) 76 | htmldumpfile.close() 77 | htmldumpbar.next() 78 | os.chdir(ROOT_DIR + "/media") 79 | break 80 | htmldumpbar.finish() 81 | -------------------------------------------------------------------------------- /fileinteractions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os, sys 3 | from definitions import ROOT_DIR 4 | import json 5 | import shutil 6 | import colorama 7 | from colorama import Fore, Back, Style 8 | 9 | 10 | def stageset(): 11 | 12 | #This fuction checks to make sure that the exifdata directory is set correctly 13 | #It creates folders that need to be there 14 | 15 | exifdatadir = ROOT_DIR + "/exifdata/" 16 | filtereddir = ROOT_DIR + "/exifdata/filtered/" 17 | hexhtmldir = ROOT_DIR + "/exifdata/hex_html/" 18 | htmldir = ROOT_DIR + "/exifdata/html/" 19 | jsondir = ROOT_DIR + "/exifdata/json/" 20 | statsdir = ROOT_DIR + "/exifdata/stats/" 21 | geolocationdir = ROOT_DIR + "/exifdata/stats/geolocations" 22 | softwaredir = ROOT_DIR + "/exifdata/stats/software" 23 | devicesdir = ROOT_DIR + "/exifdata/stats/devices" 24 | authorsdir = ROOT_DIR + "/exifdata/stats/authors" 25 | customdir = ROOT_DIR + "/exifdata/stats/custom" 26 | 27 | filetypedir = ['odp', 'odt','png', 'mp3', 'dll', 'torrent', 'pptx', 'ods', 'zip', 'exe', 28 | 'xlsx', 'svg', 'pdf', 'mp4', 'html', 'docx', 'gif', 'wav', 'jpeg', 'mkv', 'all'] 29 | 30 | if not os.path.exists(exifdatadir): 31 | os.mkdir(exifdatadir) 32 | 33 | if not os.path.exists(filtereddir): 34 | os.mkdir(filtereddir) 35 | 36 | if not os.path.exists(hexhtmldir): 37 | os.mkdir(hexhtmldir) 38 | 39 | if not os.path.exists(htmldir): 40 | os.mkdir(htmldir) 41 | 42 | if not os.path.exists(jsondir): 43 | os.mkdir(jsondir) 44 | 45 | if not os.path.exists(statsdir): 46 | os.mkdir(statsdir) 47 | 48 | if not os.path.exists(geolocationdir): 49 | os.mkdir(geolocationdir) 50 | 51 | if not os.path.exists(softwaredir): 52 | os.mkdir(softwaredir) 53 | 54 | if not os.path.exists(devicesdir): 55 | os.mkdir(devicesdir) 56 | 57 | if not os.path.exists(authorsdir): 58 | os.mkdir(authorsdir) 59 | 60 | if not os.path.exists(customdir): 61 | os.mkdir(customdir) 62 | 63 | for filetype in filetypedir: 64 | if not os.path.exists(jsondir + filetype): 65 | os.mkdir(jsondir + filetype) 66 | 67 | 68 | #This function will check to see if the exifdata/ directory and the exifdata/json/ are empty 69 | #if it isn't it will prompt the user to delete them or not 70 | def checkdelete(): 71 | jsonpath = ROOT_DIR + "/exifdata/json/" 72 | filteredjsonpath = ROOT_DIR + "/exifdata/filtered/" 73 | jsonsubdirs = ['odp', 'odt', 'png', 'mp3', 'dll', 'torrent', 'pptx', 'ods', 'zip', 'exe', 74 | 'xlsx', 'svg', 'pdf', 'mp4', 'html', 'docx', 'gif', 'wav', 'jpeg', 'mkv', 'all'] 75 | 76 | #FILTER DIRECTORY 77 | if not os.listdir(filteredjsonpath): 78 | pass 79 | else: 80 | print(Fore.RED + filteredjsonpath + " has files inside") 81 | print(Style.RESET_ALL) 82 | print(Style.BRIGHT + "Would you like to delete these files?") 83 | print("It is recommended, just save the files elsewhere") 84 | print(Style.RESET_ALL) 85 | filteredjsonanswer = input("y/n: ") 86 | if filteredjsonanswer == "y": 87 | for filename in os.listdir(filteredjsonpath): 88 | os.remove(filteredjsonpath + filename) 89 | 90 | else: 91 | print("Not going to delete anything in: " + jsonpath) 92 | print(Fore.RED +"This could cause errors!") 93 | print(Style.RESET_ALL) 94 | pass 95 | 96 | #JSON FOLDERS 97 | os.chdir(jsonpath) 98 | files = [filename for filename in os.listdir('.') if os.path.isfile(filename)] 99 | if not os.listdir(jsonpath): 100 | pass 101 | if files == []: 102 | pass 103 | 104 | else: 105 | print() 106 | print(Fore.RED + " exifdata/json has files inside") 107 | print(Style.RESET_ALL) 108 | print(Style.BRIGHT + "Would you like to delete these files?") 109 | print("It is recommended, just save the files elsewhere") 110 | print(Style.RESET_ALL) 111 | jsonanswer = input("y/n: ") 112 | if jsonanswer == "y": 113 | for filename in files: 114 | os.remove(filename) 115 | else: 116 | print("Not going to delete anything in: " + jsonpath) 117 | print(Fore.RED +"This could cause errors!") 118 | print(Style.RESET_ALL) 119 | pass 120 | 121 | #DIRECTORIES IN EXIFDATA/JSON/ 122 | os.chdir(jsonpath) 123 | for subdir in jsonsubdirs: 124 | if not os.listdir(subdir): 125 | pass 126 | else: 127 | print() 128 | print(Fore.RED + "exifdata/json/" + subdir + " has files inside") 129 | filesinsubdir = os.listdir(subdir) 130 | print(Style.RESET_ALL) 131 | print(Style.BRIGHT + "Would you like to delete these files?") 132 | print("It is recommended, just save the files elsewhere") 133 | print(Style.RESET_ALL) 134 | subdirsanswer = input("y/n: ") 135 | if subdirsanswer == "y": 136 | for f in filesinsubdir: 137 | fstring = ''.join(f) 138 | os.remove(jsonpath +"/"+ subdir +"/"+ fstring) 139 | 140 | else: 141 | print("Not going to delete anything in: " + subdir) 142 | print(Fore.RED +"This could cause errors!") 143 | print(Style.RESET_ALL) 144 | pass 145 | 146 | 147 | #This function sorts the json files into their respective folder based on file extension 148 | def jsonsort(): 149 | 150 | docs = ["docx", "doc", "DOC", "DOCX"] 151 | excel = ["xlsx", "xls", "XLSX", "XLS"] 152 | powerpoint = ["pptx","ppt","PPTX","PPT"] 153 | 154 | 155 | os.chdir(ROOT_DIR + "/exifdata/json/") 156 | jfiles = [filename for filename in os.listdir(".") if os.path.isfile(filename)] 157 | for filename in jfiles: 158 | os.chdir(ROOT_DIR + "/exifdata/json/") 159 | shutil.copy(filename, ROOT_DIR + "/exifdata/json/all") 160 | 161 | try: 162 | with open(filename) as jsonfile: 163 | pjsonfile = json.load(jsonfile) 164 | for p in pjsonfile: 165 | if p['File:FileTypeExtension'] == "jpg": 166 | dest = ROOT_DIR + "/exifdata/json/jpeg" 167 | shutil.move(filename, dest) 168 | pass 169 | 170 | elif p['File:FileTypeExtension'] == "png": 171 | dest = ROOT_DIR + "/exifdata/json/png" 172 | shutil.move(filename, dest) 173 | pass 174 | 175 | elif p['File:FileTypeExtension'] == "gif": 176 | dest = ROOT_DIR + "/exifdata/json/gif" 177 | shutil.move(filename, dest) 178 | pass 179 | 180 | elif p['File:FileTypeExtension'] == "dll": 181 | dest = ROOT_DIR + "/exifdata/json/dll" 182 | shutil.move(filename, dest) 183 | pass 184 | 185 | elif p['File:FileTypeExtension'] == "exe": 186 | dest = ROOT_DIR + "/exifdata/json/exe" 187 | shutil.move(filename, dest) 188 | pass 189 | 190 | elif p['File:FileTypeExtension'] == "html": 191 | dest = ROOT_DIR + "/exifdata/json/html" 192 | shutil.move(filename, dest) 193 | pass 194 | 195 | elif p['File:FileTypeExtension'] == "mkv": 196 | dest = ROOT_DIR + "/exifdata/json/mkv" 197 | shutil.move(filename, dest) 198 | pass 199 | 200 | elif p['File:FileTypeExtension'] == "mp3": 201 | dest = ROOT_DIR + "/exifdata/json/mp3" 202 | shutil.move(filename, dest) 203 | pass 204 | 205 | elif p['File:FileTypeExtension'] == "mp4": 206 | dest = ROOT_DIR + "/exifdata/json/mp4" 207 | shutil.move(filename, dest) 208 | pass 209 | 210 | elif p['File:FileTypeExtension'] == "odp": 211 | dest = ROOT_DIR + "/exifdata/json/odp" 212 | shutil.move(filename, dest) 213 | pass 214 | 215 | elif p['File:FileTypeExtension'] == "ods": 216 | dest = ROOT_DIR + "/exifdata/json/ods" 217 | shutil.move(filename, dest) 218 | pass 219 | 220 | elif p['File:FileTypeExtension'] == "odt": 221 | dest = ROOT_DIR + "/exifdata/json/odt" 222 | shutil.move(filename, dest) 223 | pass 224 | 225 | elif p['File:FileTypeExtension'] == "pdf": 226 | dest = ROOT_DIR + "/exifdata/json/pdf" 227 | shutil.move(filename, dest) 228 | pass 229 | 230 | elif p['File:FileTypeExtension'] == "svg": 231 | dest = ROOT_DIR + "/exifdata/json/svg" 232 | shutil.move(filename, dest) 233 | pass 234 | 235 | elif p['File:FileTypeExtension'] == "torrent": 236 | dest = ROOT_DIR + "/exifdata/json/torrent" 237 | shutil.move(filename, dest) 238 | pass 239 | 240 | elif p['File:FileTypeExtension'] == "wav": 241 | dest = ROOT_DIR + "/exifdata/json/wav" 242 | shutil.move(filename, dest) 243 | pass 244 | 245 | 246 | elif p['File:FileTypeExtension'] == "zip": 247 | dest = ROOT_DIR + "/exifdata/json/zip" 248 | shutil.move(filename, dest) 249 | pass 250 | 251 | # Legacy MS Office Filetypes go into their newer-type's folder 252 | 253 | elif p['File:FileTypeExtension'] in docs: 254 | dest = ROOT_DIR + "/exifdata/json/docx" 255 | shutil.move(filename, dest) 256 | pass 257 | 258 | 259 | elif p['File:FileTypeExtension'] in excel: 260 | dest = ROOT_DIR + "exifdata/json/xlsx" 261 | shutil.move(filename, dest) 262 | pass 263 | 264 | elif p['File:FileTypeExtension'] in powerpoint: 265 | dest = ROOT_DIR + "exifdata/json/pptx" 266 | shutil.move(filename, dest) 267 | pass 268 | 269 | except: 270 | print("Filetype is not supported:" + filename) 271 | 272 | -------------------------------------------------------------------------------- /filter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from definitions import ROOT_DIR 4 | from os.path import basename 5 | import os, sys 6 | import shutil 7 | 8 | ''' 9 | These will filter the JSON files and sort them into useful categories. 10 | Each function is a file extension. 11 | 12 | 1) Load Filter 13 | 2) Load Metadata 14 | 3) Compare each line of Metadata to Filter (tuple) 15 | 4) Print Similarities 16 | 17 | IMPORTANT: Always include the name of the file in the filtered tags as a tuple 18 | https://www.miniwebtool.com/remove-line-breaks/ 19 | ''' 20 | 21 | dest = ROOT_DIR + "/exifdata/filtered/" 22 | 23 | def JPEGfilter(): 24 | #Load list of tags as a tuple 25 | jpegtags = ('Adobe:APP14Flags0', 'Adobe:DCTEncodeVersion', 'Composite:CircleOfConfusion', 'Composite:FocalLength35efl', 26 | 'Composite:FOV', 'Composite:GPSDateTime', 'Composite:GPSLatitude', 'Composite:GPSLongitude', 'Composite:GPSPosition', 27 | 'Composite:HyperfocalDistance', 'Composite:ImageSize', 'Composite:LensID', 'Composite:ShutterSpeed', 'Composite:SubSecCreateDate', 28 | 'Composite:SubSecDateTimeOriginal', 'Composite:SubSecModifyDate', 'Ducky:Quality', 'EXIF:ApertureValue', 'EXIF:Copyright', 29 | 'EXIF:CreateDate', 'EXIF:CustomRendered', 'EXIF:DateTimeOriginal', 'EXIF:ExposureProgram', 'EXIF:FileSource', 'EXIF:Flash', 30 | 'EXIF:FlashpixVersion', 'EXIF:FocalLength', 'EXIF:FocalLengthIn35mmFormat', 'EXIF:Gamma', 'ExifIFD:CreateDate', 'ExifIFD:DateTimeOriginal', 31 | 'ExifIFD:ExposureProgram', 'ExifIFD:FileSource', 'ExifIFD:Flash', 'ExifIFD:FlashpixVersion', 'ExifIFD:FocalLength', 32 | 'ExifIFD:FocalLengthIn35mmFormat', 'ExifIFD:Gamma', 'ExifIFD:ISO', 'ExifIFD:LensInfo', 'ExifIFD:LensMake', 'ExifIFD:LensModel', 33 | 'ExifIFD:LightSource', 'ExifIFD:MaxApertureValue', 'ExifIFD:Saturation', 'ExifIFD:SceneCaptureType', 'ExifIFD:SceneType', 34 | 'ExifIFD:SensingMethod', 'ExifIFD:Sharpness', 'ExifIFD:ShutterSpeedValue', 'ExifIFD:SubjectDistance', 'ExifIFD:SubjectDistanceRange', 35 | 'EXIF:ISO', 'EXIF:LensInfo', 'EXIF:LensMake', 'EXIF:LensModel', 'EXIF:LightSource', 'EXIF:Make', 'EXIF:MaxApertureValue', 36 | 'EXIF:Model', 'EXIF:ModifyDate', 'EXIF:Saturation', 'EXIF:SceneCaptureType', 'EXIF:SceneType', 'EXIF:SensingMethod', 'EXIF:Sharpness', 37 | 'EXIF:ShutterSpeedValue', 'EXIF:Software', 'EXIF:SubjectDistance', 'EXIF:SubjectDistanceRange', 'ExifTool:Warning', 'File:Comment', 38 | 'FOV', 'GPS:GPSAltitude', 'GPS:GPSDateStamp', 'GPS:GPSDOP', 'GPS:GPSLatitude', 'GPS:GPSLatitudeRef', 'GPS:GPSLongitude', 39 | 'GPS:GPSLongitudeRef', 'GPS:GPSTimeStamp', 'ICC-header:DeviceAttributes' 'ICC-header:PrimaryPlatform', 'ICC-header:ProfileCreator', 40 | 'ICC-header:ProfileDateTime', 'ICC-header:RenderingIntent', 'ICC-meas:MeasurementObserver', 'ICC_Profile:ProfileCopyright', 41 | 'ICC_Profile:ProfileDescription', 'ICC_Profile:Technology', 'IFD0:Copyright', 'IFD0:ImageDescription', 'IFD0:Orientation', 42 | 'InternalSerialNumber', 'IPTC:By-line', 'IPTC:Caption-Abstract', 'IPTC:CodedCharacterSet', 'IPTC:CopyrightNotice', 'IPTC:Credit', 43 | 'IPTC:ObjectName', 'IPTC:Source', 'IPTC:SpecialInstructions', 'JFIF:JFIFVersion', 'Macro', 'MakerNotes:AFMode', 'MakerNotes:FacesDetected', 44 | 'MakerNotes:FocusMode', 'MakerNotes:FujiFlashMode', 'MakerNotes:InternalSerialNumber', 'MakerNotes:PictureMode', 'MakerNotes:Quality', 45 | 'MakerNotes:Sharpness', 'Photoshop:PhotoshopFormat', 'Photoshop:ProgressiveScans', 'Photoshop:ReaderName', 'Photoshop:URL_List', 46 | 'Photoshop:WriterName', 'Quality', 'System:FileInodeChangeDate', 'System:FileModifyDate', 'XMP:About', 'XMP:CreatorTool', 47 | 'XMP:DateAcquired', 'XMP-dc:Creator', 'XMP-dc:Rights', 'XMP:DocumentID', 'XMP-exif:UserComment', 'XMP:InstanceID', 48 | 'XMP-photoshop:DateCreated', 'XMP-xmp:CreatorTool', 'XMP-xmpMM:DerivedFromDocumentID', 'XMP:XMPToolkit', 'XMP-x:XMPToolkit') 49 | 50 | #Load files then compare to list of tags 51 | jpegsrc = ROOT_DIR + "/exifdata/json/jpeg/" 52 | 53 | os.chdir(jpegsrc) 54 | for jpegfile in os.listdir("."): 55 | with open(jpegfile) as ofilejson: 56 | basejpeg = os.path.basename(jpegfile) 57 | with open(os.path.splitext(basejpeg)[0]+".txt","w") as jpeg_filename: 58 | for line in ofilejson: 59 | for tag in jpegtags: 60 | if tag in line: 61 | jpeg_filename.write(line) 62 | 63 | #Move the outputs to filtered directory 64 | os.chdir(ROOT_DIR + "/exifdata/json/jpeg") 65 | for jpegfile in os.listdir("."): 66 | if ".txt" in jpegfile: 67 | shutil.move(jpegsrc + jpegfile, dest) 68 | 69 | 70 | 71 | def PNGfilter(): 72 | 73 | pngtags = ('File:FileModifyDate','Composite:CircleOfConfusion', 'Composite:FocalLength35efl', 'Composite:FOV', 'Composite:GPSDateTime', 'Composite:GPSLatitude', 74 | 'Composite:GPSLongitude', 'Composite:GPSPosition', 'Composite:HyperfocalDistance', 'Composite:ImageSize', 'Composite:LensID', 75 | 'Composite:ShutterSpeed', 'Composite:SubSecCreateDate', 'Composite:SubSecDateTimeOriginal', 'Composite:SubSecModifyDate', 'Ducky:Quality', 76 | 'File:Comment', 'File:FileAccessDate', 'File:FileInodeChangeDate', 'GPSAltitude', 'GPSDateStamp', 'GPSDOP', 'GPSLatitude', 77 | 'GPSLatitudeRef', 'GPSLongitude', 'GPSLongitudeRef', 'GPSTimeStamp', 'ICC-header:DeviceAttributes' 'ICC-header:PrimaryPlatform', 78 | 'ICC-header:ProfileCreator', 'ICC-header:ProfileDateTime', 'ICC-header:RenderingIntent', 'ICC-meas:MeasurementObserver', 79 | 'ICC_Profile:DeviceMfgDesc', 'ICC_Profile:DeviceModel', 'ICC_Profile:DeviceModelDesc', 'ICC_Profile:MakeAndModel', 80 | 'ICC_Profile:MeasurementIlluminant', 'ICC_Profile:MeasurementObserver', 'ICC_Profile:PrimaryPlatform', 'ICC_Profile:ProfileCMMType', 81 | 'ICC_Profile:ProfileCopyright', 'ICC_Profile:ProfileCreator' 'ICC_Profile:ProfileDateTime', 'ICC_Profile:ProfileDescription', 82 | 'ICC_Profile:ProfileFileSignature', 'ICC_Profile:ProfileID', 'ICC_Profile:RenderingIntent', 'ICC_Profile:Technology', 'ICC_Profile:ViewingCondDesc', 83 | 'PNG:Copyright', 'PNG:CreationTime', 'PNG:datecreate', 'PNG:datemodify', 'PNG:Filter', 'PNG:ModifyDate', 'PNG:Palette', 'PNG:ProfileName', 84 | 'PNG:Software', 'PNG:SRGBRendering', 'PNG:VirtualPageUnits', 'XMP:About', 'XMP:Compression', 'XMP:CreateDate', 'XMP:CreatorTool', 85 | 'XMP:DateAcquired', 'XMP:DateCreated', 'XMP-dc:Creator', 'XMP-dc:Rights', 'XMP:DerivedFromDocumentID', 'XMP:DerivedFromInstanceID', 86 | 'XMP:DerivedFromOriginalDocumentID', 'XMP:DocumentID', 'XMP-exif:UserComment', 'XMP:HistoryAction', 'XMP:HistoryChanged', 87 | 'XMP:HistoryInstanceID', 'XMP:HistoryParameters', 'XMP:HistorySoftwareAgent', 'XMP:HistoryWhen', 'XMP:ICCProfileName', 'XMP:InstanceID', 88 | 'XMP:Marked', 'XMP:MetadataDate', 'XMP:ModifyDate', 'XMP:Orientation', 'XMP-photoshop:DateCreated', 'XMP:Title', 'XMP:TransmissionReference', 89 | 'XMP:UserComment', 'XMP-xmp:CreatorTool', 'XMP-xmpMM:DerivedFromDocumentID', 'XMP:XMPToolkit', 'XMP:XMPToolkit', 'XMP-x:XMPToolkit') 90 | 91 | pngsrc = ROOT_DIR + "/exifdata/json/png/" 92 | 93 | os.chdir(pngsrc) 94 | for pngfile in os.listdir("."): 95 | with open(pngfile) as opngfile: 96 | basepng = os.path.basename(pngfile) 97 | with open(os.path.splitext(basepng)[0]+".txt","w") as png_filename: 98 | for line in opngfile: 99 | for tag in pngtags: 100 | if tag in line: 101 | png_filename.write(line) 102 | 103 | os.chdir(pngsrc) 104 | for pngfile in os.listdir("."): 105 | if ".txt" in pngfile: 106 | shutil.move(pngsrc + pngfile, dest) 107 | 108 | 109 | def GIFfilter(): 110 | 111 | giftags =("File:FileModifyDate","File:Comment" ,"HTML:HTTPEquivXUaCompatible","HTML:viewport","HTML:twitterAccount_id","HTML:twitterCard", 112 | "HTML:twitterTitle","HTML:twitterCreator","HTML:twitterSite","HTML:twitterDescription","HTML:twitterImageSrc","HTML:twitterDomain", 113 | "HTML:twitterPlayer","HTML:Rating","HTML:Description","HTML:Author","HTML:Keywords","HTML:pinterest","HTML:Title","GIF:GIFVersion", 114 | "GIF:AnimationIterations","GIF:FrameCount","GIF:Duration","HTML:Copyright","HTML:msapplicationTileColor","HTML:msapplicationTileImage", 115 | "HTML:pDomain_verify") 116 | 117 | gifsrc = ROOT_DIR + "/exifdata/json/gif/" 118 | 119 | os.chdir(gifsrc) 120 | for giffile in os.listdir("."): 121 | with open(giffile) as ogiffile: 122 | basegif = os.path.basename(giffile) 123 | with open(os.path.splitext(basegif)[0]+".txt","w") as gif_filename: 124 | for line in ogiffile: 125 | for tag in giftags: 126 | if tag in line: 127 | gif_filename.write(line) 128 | 129 | os.chdir(gifsrc) 130 | for giffile in os.listdir("."): 131 | if ".txt" in giffile: 132 | shutil.move(gifsrc + giffile, dest) 133 | 134 | 135 | 136 | def DOCXfilter(): 137 | 138 | docxtags=("File:FileModifyDate","File:MIMEType","ZIP:ZipModifyDate","XML:Template","XML:TotalEditTime","XML:Application", 139 | "XML:Paragraphs","XML:LastPrinted","XML:CreateDate","XML:RevisionNumber","XMP:Creator","XML:ModifyDate","XMP:Creator", 140 | "XMP:Language","XML:Words","XML:Pages","XML:CharactersWithSpaces","XMP:Description","XMP:Subject","XMP:Title","XML:Characters", 141 | "XML:DocSecurity","XML:Keywords","XML:Lines","XML:Company","XML:SharedDoc","XML:AppVersion","XML:LastModifiedBy","FlashPix:Title", 142 | "FlashPix:Subject","FlashPix:Author","FlashPix:LastModifiedBy","FlashPix:RevisionNumber","FlashPix:Software", 143 | "FlashPix:TotalEditTime","FlashPix:LastPrinted","FlashPix:CreateDate","FlashPix:Pages","FlashPix:Words","FlashPix:Characters", 144 | "FlashPix:Security","FlashPix:CodePage","FlashPix:Company","FlashPix:Lines","FlashPix:Paragraphs","FlashPix:CharCountWithSpaces", 145 | "FlashPix:SharedDoc","FlashPix:CompObjUserType","FlashPix:Comments","FlashPix:Bytes","FlashPix:Slides","FlashPix:Notes", 146 | "FlashPix:HiddenSlides","FlashPix:AppVersion") 147 | 148 | docxsrc = ROOT_DIR + "/exifdata/json/docx/" 149 | 150 | os.chdir(docxsrc) 151 | for docxfile in os.listdir("."): 152 | with open(docxfile) as odocxfile: 153 | basedocx = os.path.basename(docxfile) 154 | with open(os.path.splitext(basedocx)[0]+".txt","w") as docx_filename: 155 | for line in odocxfile: 156 | for tag in docxtags: 157 | if tag in line: 158 | docx_filename.write(line) 159 | 160 | os.chdir(docxsrc) 161 | for docxfile in os.listdir("."): 162 | if ".txt" in docxfile: 163 | shutil.move(docxsrc + docxfile, dest) 164 | 165 | 166 | def EXEfilter(): 167 | 168 | exetags=("File:FileType","File:FileModifyDate","EXE:MachineType","EXE:TimeStamp","EXE:PEType","EXE:LinkerVersion", 169 | "EXE:OSVersion","EXE:Subsystem","EXE:ProductName","EXE:OriginalFileName","EXE:LegalCopyright","EXE:InternalName", 170 | "EXE:FileVersion","EXE:FileDescription","EXE:CompanyName","EXE:CharacterSet","EXE:LanguageCode","EXE:FileOS", 171 | "EXE:ProductVersionNumber","EXE:EntryPoint","EXE:SquirrelAwareVersion","EXE:ProductVersion","EXE:CharacterSet", 172 | "EXE:Comments","EXE:ObjectFileType","EXE:FileVersionNumber","EXE:FileFlags","EXE:InitializedDataSize") 173 | 174 | exesrc = ROOT_DIR + "/exifdata/json/exe/" 175 | 176 | os.chdir(exesrc) 177 | for exefile in os.listdir("."): 178 | with open(exefile) as oexefile: 179 | baseexe = os.path.basename(exefile) 180 | with open(os.path.splitext(baseexe)[0]+".txt","w") as exe_filename: 181 | for line in oexefile: 182 | for tag in exetags: 183 | if tag in line: 184 | exe_filename.write(line) 185 | 186 | os.chdir(exesrc) 187 | for exefile in os.listdir("."): 188 | if ".txt" in exefile: 189 | shutil.move(exesrc + exefile, dest) 190 | 191 | 192 | def MKVfilter(): 193 | mkvtags=("File:FileModifyDate","Matroska:MuxingApp","Matroska:WritingApp","Matroska:Duration","Matroska:TrackType","Matroska:Title","Matroska:AudioSampleRate", 194 | "Matroska:VideoFrameRate","Matroska:VideoCodecID","Matroska:ImageWidth","Matroska:ImageHeight","Composite:ImageSize","Composite:Megapixels") 195 | 196 | mkvsrc = ROOT_DIR + "/exifdata/json/mkv/" 197 | 198 | os.chdir(mp3src) 199 | for mkvfile in os.listdir("."): 200 | with open(mkvfile) as omkvfile: 201 | basemkv = os.path.basename(mkvfile) 202 | with open(os.path.splitext(basemkv)[0]+".txt","w") as mkv_filename: 203 | for line in omkvfile: 204 | for tag in mkvtags: 205 | if tag in line: 206 | mkv_filename.write(line) 207 | 208 | os.chdir(mkvsrc) 209 | for mkvfile in os.listdir("."): 210 | if ".txt" in mkvfile: 211 | shutil.move(mkvsrc + mkvfile, dest) 212 | 213 | 214 | 215 | 216 | def MP3filter(): 217 | 218 | mp3tags=('File:ID3Size','MPEG:MPEGAudioVersion','MPEG:AudioLayer','MPEG:AudioBitrate','MPEG:SampleRate', 219 | 'MPEG:ChannelMode','MPEG:MSStereo','MPEG:IntensityStereo','MPEG:CopyrightFlag','MPEG:OriginalMedia','MPEG:Emphasis', 220 | 'ID3:Title','ID3:Artist','ID3:Album','ID3:Year','ID3:Comment','ID3:Genre','Composite:DateTimeOriginal','Composite:Duration') 221 | 222 | 223 | mp3src = ROOT_DIR + "/exifdata/json/mp3/" 224 | 225 | os.chdir(mp3src) 226 | for mp3file in os.listdir("."): 227 | with open(mp3file) as omp3file: 228 | basemp3 = os.path.basename(mp3file) 229 | with open(os.path.splitext(basemp3)[0]+".txt","w") as mp3_filename: 230 | for line in omp3file: 231 | for tag in mp3tags: 232 | if tag in line: 233 | mp3_filename.write(line) 234 | 235 | os.chdir(mp3src) 236 | for mp3file in os.listdir("."): 237 | if ".txt" in mp3file: 238 | shutil.move(mp3src + mp3file, dest) 239 | 240 | 241 | def MP4filter(): 242 | mp4tags=("QuickTime:CreateDate","QuickTime:Duration","QuickTime:GraphicsMode","QuickTime:CompressorName","QuickTime:MajorBrand","QuickTime:MediaLanguageCode", 243 | "QuickTime:HandlerDescription","QuickTime:HandlerVendorID","XMP:CreateDate","XMP:VideoFieldOrder","XMP:HistorySoftwareAgent","XMP:XMPToolkit", 244 | "XMP:PantryHistorySoftwareAgent","XMP:WindowsAtomUncProjectPath","XMP:CreatorTool","XMP:MacAtomPosixProjectPath") 245 | 246 | mp4src = ROOT_DIR + "/exifdata/json/mp4/" 247 | 248 | os.chdir(mp4src) 249 | for mp4file in os.listdir("."): 250 | with open(mp4file) as omp4file: 251 | basemp4 = os.path.basename(mp4file) 252 | with open(os.path.splitext(basemp4)[0]+".txt","w") as mp4_filename: 253 | for line in omp4file: 254 | for tag in mp4tags: 255 | if tag in line: 256 | mp4_filename.write(line) 257 | 258 | os.chdir(mp4src) 259 | for mp4file in os.listdir("."): 260 | if ".txt" in mp4file: 261 | shutil.move(mp4src + mp4file, dest) 262 | 263 | 264 | def HTMLfilter(): 265 | 266 | htmltags=("HTML:Title","HTML:Description","HTML:twitterCard","HTML:Robots","HTML:twitterTitle","HTML:twitterDescription","HTML:twitterUrl","HTML:twitterImage", 267 | "HTML:googleSiteVerification","HTML:swiftPageName","HTML:msapplicationTileImage","HTML:hostname","HTML:googleAnalytics","HTML:requestId","HTML:userLogin", 268 | "HTML:expectedHostname","HTML:jsProxySiteDetectionPayload","HTML:enabledFeatures","HTML:browserStatsUrl","HTML:browserErrorsUrl","HTML:themeColor","HTML:mobileWebAppCapable", 269 | "HTML:Keywords","HTML:csrfToken","HTML:themeColor") 270 | 271 | 272 | htmlsrc = ROOT_DIR + "/exifdata/json/html/" 273 | 274 | os.chdir(htmlsrc) 275 | for htmlfile in os.listdir("."): 276 | with open(htmlfile) as ohtmlfile: 277 | basehtml = os.path.basename(htmlfile) 278 | with open(os.path.splitext(basehtml)[0]+".txt","w") as html_filename: 279 | for line in ohtmlfile: 280 | for tag in htmltags: 281 | if tag in line: 282 | html_filename.write(line) 283 | 284 | os.chdir(htmlsrc) 285 | for htmlfile in os.listdir("."): 286 | if ".txt" in htmlfile: 287 | shutil.move(htmlsrc + htmlfile, dest) 288 | 289 | def ODPfilter(): 290 | 291 | odptags=("XMP:Creation-date","XMP:Date","XMP:Editing-duration","XMP:Editing-cycles","XMP:Generator", 292 | "XMP:Document-statisticObject-count","XMP:Language","XMP:Print-date","XMP:Creator","XMP:User-definedName", 293 | "XMP:XMPToolkit","XMP:Description","XMP:Title","XMP:CreationDate--Text","XMP:Producer","XMP:CreatorTool", 294 | "XMP:ModifyDate","XMP:About","XMP:CreatorTool","XMP:DateAcquired","XMP-dc:Creator","XMP-dc:Rights","XMP:DocumentID", 295 | "XMP-exif:UserComment","XMP:InstanceID","XMP-photoshop:DateCreated","XMP-xmp:CreatorTool","XMP-xmpMM:DerivedFromDocumentID", 296 | "XMP:XMPToolkit","XMP-x:XMPToolkit") 297 | 298 | odpsrc = ROOT_DIR + "/exifdata/json/odp/" 299 | 300 | os.chdir(odpsrc) 301 | for odpfile in os.listdir("."): 302 | with open(odpfile) as oodpfile: 303 | baseodp = os.path.basename(odpfile) 304 | with open(os.path.splitext(baseodp)[0]+".txt","w") as odp_filename: 305 | for line in oodpfile: 306 | for tag in odptags: 307 | if tag in line: 308 | odp_filename.write(line) 309 | 310 | os.chdir(odpsrc) 311 | for odpfile in os.listdir("."): 312 | if ".txt" in odpfile: 313 | shutil.move(odpsrc + odpfile, dest) 314 | 315 | 316 | 317 | def PPTXfilter(): 318 | pptxtags = ('File:FileModifyDate', 'File:FileAccessDate', 'File:FileInodeChangeDate', 'FlashPix:CurrentUser', 319 | 'FlashPix:Title', 'FlashPix:Author', 'FlashPix:Template', 'FlashPix:LastModifiedBy', 'FlashPix:RevisionNumber', 'FlashPix:Software', 320 | 'FlashPix:TotalEditTime', 'FlashPix:CreateDate', 'FlashPix:ModifyDate', 'FlashPix:Words', 'FlashPix:PresentationTarget', 321 | 'FlashPix:Company', 'FlashPix:Bytes', 'FlashPix:Paragraphs', 'FlashPix:Slides', 'FlashPix:Notes', 'FlashPix:HiddenSlides', 322 | 'FlashPix:MMClips', 'FlashPix:AppVersion', 'FlashPix:ScaleCrop', 'FlashPix:LinksUpToDate', 'FlashPix:SharedDoc', 323 | 'FlashPix:HyperlinksChanged', 'FlashPix:TitleOfParts', 'FlashPix:HeadingPairs', 'FlashPix:CodePage', 'FlashPix:Hyperlinks', 324 | 'FlashPix:ContentType', 'FlashPix:HyperlinkBase', 'XML:TitlesOfParts', 'ZIP:ZipRequiredVersion', 'ZIP:ZipFileName', 325 | 'ZIP:ZipModifyDate', 'XML:Template', 'XML:TotalEditTime', 'XML:Words', 'XML:Application', 'XML:PresentationFormat', 326 | 'XML:Paragraphs', 'XML:Slides', 'XML:Notes', 'XML:HiddenSlides', 'XML:MMClips', 'XML:ScaleCrop', 'XML:HeadingPairs', 327 | 'XML:LinksUpToDate', 'XML:SharedDoc', 'XML:HyperlinksChanged', 'XML:AppVersion', 'XML:LastModifiedBy', 'XML:RevisionNumber', 328 | 'XML:CreateDate', 'XML:ModifyDate', 'XML:KSOProductBuildVer', 'XMP:Title', 'XMP:Creator', 'XML:Company', 'XML:LastPrinted') 329 | 330 | pptxsrc = ROOT_DIR + "/exifdata/json/pptx/" 331 | 332 | os.chdir(pptxsrc) 333 | for pptxfile in os.listdir("."): 334 | with open(pptxfile) as opptxfile: 335 | basepptx = os.path.basename(pptxfile) 336 | with open(os.path.splitext(basepptx)[0]+".txt","w") as pptx_filename: 337 | for line in opptxfile: 338 | for tag in pptxtags: 339 | if tag in line: 340 | pptx_filename.write(line) 341 | 342 | os.chdir(pptxsrc) 343 | for pptxfile in os.listdir("."): 344 | if ".txt" in pptxfile: 345 | shutil.move(pptxsrc + pptxfile, dest) 346 | 347 | 348 | def ODSfilter(): 349 | odstags=("XMP:About","XMP:CreatorTool","XMP:DateAcquired","XMP-dc:Creator","XMP-dc:Rights","XMP:DocumentID","XMP-exif:UserComment","XMP:InstanceID", 350 | "XMP-photoshop:DateCreated","XMP-xmp:CreatorTool","XMP-xmpMM:DerivedFromDocumentID","XMP:XMPToolkit","XMP-x:XMPToolkit","XMP:Creator","XMP:Compression", 351 | "XMP:CreateDate","XMP:CreatorTool","XMP:DateAcquired","XMP:DateCreated","XMP-dc:Creator","XMP-dc:Rights","XMP:DerivedFromDocumentID","XMP:DerivedFromInstanceID", 352 | "XMP:DerivedFromOriginalDocumentID","XMP:DocumentID","XMP-exif:UserComment","XMP:HistoryAction","XMP:HistoryChanged","XMP:HistoryInstanceID","XMP:HistoryParameters", 353 | "XMP:HistorySoftwareAgent","XMP:HistoryWhen","XMP:ICCProfileName","XMP:InstanceID","XMP:Marked","XMP:MetadataDate","XMP:ModifyDate","XMP:Orientation","XMP-photoshop:DateCreated","XMP:Title", 354 | "XMP:TransmissionReference","XMP:UserComment","XMP-xmp:CreatorTool","XMP-xmpMM:DerivedFromDocumentID","XMP:XMPToolkit","XMP:XMPToolkit","XMP-x:XMPToolkit", 355 | "XMP:Date","XMP:Editing-duration","XMP:Editing-cycles","XMP:Document-statisticTable-count","XMP:Document-statisticCell-count","XMP:Document-statisticObject-count", 356 | "XMP:Generator") 357 | 358 | odssrc = ROOT_DIR + "/exifdata/json/ods/" 359 | 360 | os.chdir(odssrc) 361 | for odsfile in os.listdir("."): 362 | with open(odsfile) as oodsfile: 363 | baseods = os.path.basename(odsfile) 364 | with open(os.path.splitext(baseods)[0]+".txt","w") as ods_filename: 365 | for line in oodsfile: 366 | for tag in odstags: 367 | if tag in line: 368 | ods_filename.write(line) 369 | 370 | os.chdir(odssrc) 371 | for odsfile in os.listdir("."): 372 | if ".txt" in odsfile: 373 | shutil.move(odssrc + odsfile, dest) 374 | 375 | def PDFfilter(): 376 | 377 | pdftags=("PDF:PageCount","PDF:PDFVersion","PDF:Author","PDF:CreationDate--Text","PDF:CreateDate","PDF:Creator","PDF:ModifyDate","PDF:Producer", 378 | "PDF:Subject","PDF:Title","XMP:XMPToolkit","XMP:Creator","XMP:Description","XMP:Title","XMP:CreationDate--Text","XMP:Producer","XMP:CreatorTool", 379 | "XMP:ModifyDate","XMP:About","XMP:CreatorTool","XMP:DateAcquired","XMP-dc:Creator","XMP-dc:Rights","XMP:DocumentID","XMP-exif:UserComment", 380 | "XMP:InstanceID","XMP-photoshop:DateCreated","XMP-xmp:CreatorTool","XMP-xmpMM:DerivedFromDocumentID","XMP:XMPToolkit","XMP-x:XMPToolkit", 381 | "PDF:PageCount","PDF:Language","PDF:PTEX_Fullbanner","PDF:PXCViewerInfo") 382 | 383 | pdftsrc = ROOT_DIR + "/exifdata/json/pdf/" 384 | 385 | os.chdir(pdfsrc) 386 | for pdffile in os.listdir("."): 387 | with open(pdffile) as opdffile: 388 | basepdf = os.path.basename(pdffile) 389 | with open(os.path.splitext(basepdf)[0]+".txt","w") as pdf_filename: 390 | for line in opdffile: 391 | for tag in pdftags: 392 | if tag in line: 393 | pdf_filename.write(line) 394 | 395 | os.chdir(pdfsrc) 396 | for pdffile in os.listdir("."): 397 | if ".txt" in pdffile: 398 | shutil.move(pdfsrc + pdffile, dest) 399 | 400 | 401 | 402 | def SVGfilter(): 403 | svgtags=("SVG:Xmlns","SVG:ID","SVG:ImageHeight","SVG:ImageWidth","SVG:Version","SVG:Docname","SVG:Output_extension","SVG:Export-filename","SVG:MetadataID", 404 | "XMP:WorkFormat","XMP:WorkType","XMP:WorkDescription","XMP:WorkTitle","XMP:WorkPublisherAgentTitle","XMP:WorkCreatorAgentTitle","XMP:WorkRightsAgentTitle", 405 | "XMP:WorkLicense","XMP:WorkLanguage","XMP:About","XMP:LicensePermits") 406 | 407 | svgsrc = ROOT_DIR + "/exifdata/json/svg/" 408 | 409 | os.chdir(svgsrc) 410 | for svgfile in os.listdir("."): 411 | with open(svgfile) as osvgfile: 412 | basesvg = os.path.basename(svgfile) 413 | with open(os.path.splitext(basesvg)[0]+".txt","w") as svg_filename: 414 | for line in osvgfile: 415 | for tag in svgtags: 416 | if tag in line: 417 | svg_filename.write(line) 418 | 419 | os.chdir(svgsrc) 420 | for svgfile in os.listdir("."): 421 | if ".txt" in svgfile: 422 | shutil.move(svgsrc + svgfile, dest) 423 | 424 | 425 | def TORRENTfilter(): 426 | 427 | torrenttags = ('Torrent:Announce','Torrent:CreateDate','Torrent:Length','Torrent:Name','Torrent:PieceLength','Torrent:Comment','Torrent:Creator','Torrent:URLList', 428 | 'Torrent:Private','Torrent:AnnounceList','Torrent:File','Torrent:FileLength') 429 | 430 | torrentsrc = ROOT_DIR + "/exifdata/json/torrent/" 431 | 432 | os.chdir(torrentsrc) 433 | for torrentfile in os.listdir("."): 434 | with open(torrentfile) as otorrentfile: 435 | basetorrent = os.path.basename(torrentfile) 436 | with open(os.path.splitext(basetorrent)[0]+".txt","w") as torrent_filename: 437 | for line in otorrentfile: 438 | for tag in torrenttags: 439 | if tag in line: 440 | torrent_filename.write(line) 441 | 442 | os.chdir(torrentsrc) 443 | for torrentfile in os.listdir("."): 444 | if ".txt" in torrentfile: 445 | shutil.move(torrentsrc + torrentfile, dest) 446 | 447 | def WAVfilter(): 448 | wavtags=("File:FileModifyDate","RIFF:Encoding","RIFF:SampleRate","RIFF:AvgBytesPerSec","RIFF:Description","RIFF:Originator","RIFF:DateTimeOriginal", 449 | "RIFF:OriginatorReference","Composite:Duration","RIFF:Software","RIFF:Title","RIFF:Artist","RIFF:Comment","RIFF:DateCreated") 450 | 451 | wavsrc = ROOT_DIR + "/exifdata/json/wav/" 452 | 453 | os.chdir(wavsrc) 454 | for wavfile in os.listdir("."): 455 | with open(wavfile) as owavfile: 456 | basewav = os.path.basename(wavfile) 457 | with open(os.path.splitext(basewav)[0]+".txt","w") as wav_filename: 458 | for line in owavfile: 459 | for tag in wavtags: 460 | if tag in line: 461 | wav_filename.write(line) 462 | 463 | os.chdir(wavsrc) 464 | for wavfile in os.listdir("."): 465 | if ".txt" in wavfile: 466 | shutil.move(wavsrc + wavfile, dest) 467 | 468 | 469 | def ZIPfilter(): 470 | 471 | ziptags=("File:FileModifyDate","ZIP:ZipRequiredVersion","ZIP:ZipModifyDate","ZIP:ZipFileName","ZIP:ZipUncompressedSize","ZIP:ZipCompressedSize","ZIP:ZipCRC") 472 | 473 | zipsrc = ROOT_DIR + "/exifdata/json/zip/" 474 | 475 | os.chdir(zipsrc) 476 | for zipfile in os.listdir("."): 477 | with open(zipfile) as ozipfile: 478 | basezip = os.path.basename(zipfile) 479 | with open(os.path.splitext(basezip)[0]+".txt","w") as zip_filename: 480 | for line in ozipfile: 481 | for tag in ziptags: 482 | if tag in line: 483 | zip_filename.write(line) 484 | 485 | os.chdir(zipsrc) 486 | for zipfile in os.listdir("."): 487 | if ".txt" in zipfile: 488 | shutil.move(zipsrc + zipfile, dest) 489 | 490 | def DLLfilter(): 491 | 492 | dlltags=("File:FileType","File:FileModifyDate","EXE:MachineType","EXE:TimeStamp","EXE:PEType","EXE:LinkerVersion","EXE:OSVersion", 493 | "EXE:Subsystem","EXE:ProductName","EXE:OriginalFileName","EXE:LegalCopyright","EXE:InternalName","EXE:FileVersion","EXE:FileDescription", 494 | "EXE:CompanyName","EXE:CharacterSet","EXE:LanguageCode","EXE:FileOS","EXE:ProductVersionNumber","EXE:EntryPoint","EXE:SquirrelAwareVersion", 495 | "EXE:ProductVersion","EXE:CharacterSet","EXE:Comments","EXE:ObjectFileType","EXE:FileVersionNumber","EXE:FileFlags","EXE:InitializedDataSize") 496 | 497 | dllsrc = ROOT_DIR + "/exifdata/json/dll/" 498 | 499 | os.chdir(dllsrc) 500 | for dllfile in os.listdir("."): 501 | with open(dllfile) as odllfile: 502 | basedll = os.path.basename(dllfile) 503 | with open(os.path.splitext(basedll)[0]+".txt","w") as dll_filename: 504 | for line in odllfile: 505 | for tag in dlltags: 506 | if tag in line: 507 | dll_filename.write(line) 508 | 509 | os.chdir(dllsrc) 510 | for dllfile in os.listdir("."): 511 | if ".txt" in dllfile: 512 | shutil.move(dllsrc + dllfile, dest) 513 | 514 | 515 | 516 | 517 | def XLSXfilter(): 518 | 519 | xlsxtags=("XML:LastModifiedBy","XML:CreateDate","XML:ModifyDate","XML:Application","XML:DocSecurity","XML:HeadingPairs", 520 | "XML:TitlesOfParts","XML:SharedDoc","XML:AppVersion","XML:Keywords","XML:Company","XMP:Title","XMP:Subject","XMP:Creator", 521 | "XMP:Description","FlashPix:Author","FlashPix:CodePage","FlashPix:LastModifiedBy","FlashPix:Software","FlashPix:CreateDate", 522 | "FlashPix:ModifyDate","FlashPix:Security","FlashPix:Company","FlashPix:TitleOfParts","FlashPix:HeadingPairs","FlashPix:SharedDoc", 523 | "FlashPix:AppVersion","FlashPix:Tag_EmailSubject","FlashPix:Tag_AuthorEmail","FlashPix:Tag_AuthorEmailDisplayName","XML:Application") 524 | 525 | xlsxsrc = ROOT_DIR + "/exifdata/json/xlsx/" 526 | 527 | os.chdir(xlsxsrc) 528 | for xlsxfile in os.listdir("."): 529 | with open(xlsxfile) as oxlsxfile: 530 | basexlsx = os.path.basename(xlsxfile) 531 | with open(os.path.splitext(basexlsx)[0]+".txt","w") as xlsx_filename: 532 | for line in oxlsxfile: 533 | for tag in xlsxtags: 534 | if tag in line: 535 | xlsx_filename.write(line) 536 | 537 | os.chdir(xlsxsrc) 538 | for xlsxfile in os.listdir("."): 539 | if ".txt" in xlsxfile: 540 | shutil.move(xlsxsrc + xlsxfile, dest) 541 | 542 | 543 | def ODTfilter(): 544 | 545 | odttags=("File:FileModifyDate","XMP:Creation-date","XMP:Date","XMP:Editing-duration","XMP:Editing-cycles","XMP:Generator", 546 | "XMP:Document-statisticObject-count","XMP:Language","XMP:Print-date","XMP:User-definedName","XMP:XMPToolkit", 547 | "XMP:Creator","XMP:Description","XMP:Title","XMP:CreationDate--Text","XMP:Producer","XMP:CreatorTool","XMP:ModifyDate", 548 | "XMP:About","XMP:DateAcquired","XMP-dc:Creator","XMP-dc:Rights","XMP:DocumentID","XMP-exif:UserComment","XMP:InstanceID", 549 | "XMP-photoshop:DateCreated","XMP-xmp:CreatorTool","XMP-xmpMM:DerivedFromDocumentID","XMP:XMPToolkit","XMP-x:XMPToolkit") 550 | 551 | odtsrc = ROOT_DIR + "/exifdata/json/odt/" 552 | 553 | os.chdir(odtsrc) 554 | for odtfile in os.listdir("."): 555 | with open(odtfile) as oodtfile: 556 | baseodt = os.path.basename(odtfile) 557 | with open(os.path.splitext(baseodt)[0]+".txt","w") as odt_filename: 558 | for line in oodtfile: 559 | for tag in odttags: 560 | if tag in line: 561 | odt_filename.write(line) 562 | 563 | os.chdir(odtsrc) 564 | for odtfile in os.listdir("."): 565 | if ".txt" in odtfile: 566 | shutil.move(odtsrc + odtfile, dest) 567 | 568 | 569 | 570 | 571 | def filterexec(): 572 | try: 573 | ODPfilter() 574 | except: 575 | pass 576 | 577 | try: 578 | MP3filter() 579 | except: 580 | pass 581 | 582 | try: 583 | DLLfilter() 584 | except: 585 | pass 586 | 587 | try: 588 | TORRENTfilter() 589 | except: 590 | pass 591 | 592 | try: 593 | PPTXfilter() 594 | except: 595 | pass 596 | 597 | try: 598 | ODSfilter() 599 | except: 600 | pass 601 | 602 | try: 603 | ZIPfilter() 604 | except: 605 | pass 606 | 607 | try: 608 | EXEfilter() 609 | except: 610 | pass 611 | 612 | try: 613 | XLSXfilter() 614 | except: 615 | pass 616 | 617 | try: 618 | SVGfilter() 619 | except: 620 | pass 621 | 622 | try: 623 | PDFfilter() 624 | except: 625 | pass 626 | 627 | try: 628 | MP4filter() 629 | except: 630 | pass 631 | 632 | try: 633 | HTMLfilter() 634 | except: 635 | pass 636 | 637 | try: 638 | DOCXfilter() 639 | except: 640 | pass 641 | 642 | try: 643 | GIFfilter() 644 | except: 645 | pass 646 | try: 647 | WAVfilter() 648 | 649 | except: 650 | pass 651 | 652 | try: 653 | JPEGfilter() 654 | except: 655 | pass 656 | 657 | try: 658 | MKVfilter() 659 | except: 660 | pass 661 | 662 | try: 663 | PNGfilter() 664 | except: 665 | pass 666 | 667 | try: 668 | ODTfilter() 669 | except: 670 | pass 671 | 672 | -------------------------------------------------------------------------------- /markups.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os, os.path, sys 4 | import dominate 5 | import shutil 6 | import subprocess 7 | from dominate.tags import * 8 | from dominate.util import raw 9 | from definitions import ROOT_DIR 10 | from os import listdir 11 | from os.path import isfile, join 12 | 13 | def statshtml(): 14 | # This will display stats about the files 15 | # Some stats to include will be... 16 | # 1) Number of file types (graph too) 17 | # 2) Geolocations with map (maybe?) 18 | # 3) Filtered vs. unfiltered meta 19 | # 4) File Size Graph? 20 | # 5) Software 21 | # 6) Device/manufact. model 22 | # 7) Top 5 largest files 23 | # Then Generate the html report 24 | 25 | # ADD CUSTOM TAGS HERE: 26 | # The best way to look for tags is to run exiftool -j -G