From 49b749d90b81db04ac9204452fb9011fc1ac3bc5 Mon Sep 17 00:00:00 2001 From: Braun Patrik Date: Sun, 16 Jul 2017 14:03:16 +0200 Subject: [PATCH] improving utf8 image metadata support --- backend/middlewares/user/AuthenticationMWs.ts | 1 - backend/model/threading/DiskMangerWorker.ts | 24 +++++------------- backend/server.ts | 2 +- package.json | 4 +-- .../unit/assets/test image öüóőúéáű-.,.jpg | Bin 57172 -> 62392 bytes .../model/threading/DiskMangerWorker.spec.ts | 13 +++++----- 6 files changed, 15 insertions(+), 29 deletions(-) diff --git a/backend/middlewares/user/AuthenticationMWs.ts b/backend/middlewares/user/AuthenticationMWs.ts index a2c5aadc..28eaad6e 100644 --- a/backend/middlewares/user/AuthenticationMWs.ts +++ b/backend/middlewares/user/AuthenticationMWs.ts @@ -116,7 +116,6 @@ export class AuthenticationMWs { (typeof req.body.loginCredential.password === 'undefined')) { return next(new ErrorDTO(ErrorCodes.INPUT_ERROR)); } - //TODO: implement remember me try { //lets find the user const user = Utils.clone(await ObjectManagerRepository.getInstance().UserManager.findOne({ diff --git a/backend/model/threading/DiskMangerWorker.ts b/backend/model/threading/DiskMangerWorker.ts index a6627f13..1af8f6d3 100644 --- a/backend/model/threading/DiskMangerWorker.ts +++ b/backend/model/threading/DiskMangerWorker.ts @@ -4,7 +4,7 @@ import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata} from ". import {Logger} from "../../Logger"; import * as fs from "fs"; import * as path from "path"; -import * as iptc from "node-iptc"; +import {IptcParser} from "ts-node-iptc"; import * as exif_parser from "exif-parser"; import {ProjectPath} from "../../ProjectPath"; @@ -53,7 +53,7 @@ export class DiskMangerWorker { const exif = exif_parser.create(data).parse(); metadata.cameraData = { ISO: exif.tags.ISO, - model: exif.tags.Model.toString("utf8"), + model: exif.tags.Model, make: exif.tags.Make, fStop: exif.tags.FNumber, exposure: exif.tags.ExposureTime, @@ -76,18 +76,7 @@ export class DiskMangerWorker { } try { - - const iptcData = iptc(data); - //Decode characters to UTF8 - const decode = (s: any) => { - for (let a, b, i = -1, l = (s = s.split("")).length, o = String.fromCharCode, c = "charCodeAt"; ++i < l; - ((a = s[i][c](0)) & 0x80) && - (s[i] = (a & 0xfc) == 0xc0 && ((b = s[i + 1][c](0)) & 0xc0) == 0x80 ? - o(((a & 0x03) << 6) + (b & 0x3f)) : o(128), s[++i] = "") - ); - return s.join(""); - }; - + const iptcData = IptcParser.parse(data); if (iptcData.country_or_primary_location_name || iptcData.province_or_state || iptcData.city) { metadata.positionData = metadata.positionData || {}; metadata.positionData.country = iptcData.country_or_primary_location_name; @@ -95,11 +84,10 @@ export class DiskMangerWorker { metadata.positionData.city = iptcData.city; } - - metadata.keywords = (iptcData.keywords || []).map((s: string) => decode(s)); - metadata.creationDate = iptcData.date_time ? iptcData.date_time.getTime() : 0; + metadata.keywords = (iptcData.keywords || []); + metadata.creationDate = (iptcData.date_time ? iptcData.date_time.getTime() : 0); } catch (err) { - Logger.info(LOG_TAG, "Error parsing iptc data", fullPath); + Logger.info(LOG_TAG, "Error parsing iptc data", fullPath, err); } return resolve(metadata); diff --git a/backend/server.ts b/backend/server.ts index 1d2a9db8..41ba91c5 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -1,5 +1,4 @@ import * as _express from "express"; -import * as _session from "cookie-session"; import * as _bodyParser from "body-parser"; import * as _http from "http"; import {PublicRouter} from "./routes/PublicRouter"; @@ -17,6 +16,7 @@ import {ThumbnailGeneratorMWs} from "./middlewares/thumbnail/ThumbnailGeneratorM import {DiskManager} from "./model/DiskManger"; import {NotificationRouter} from "./routes/NotificationRouter"; import {ConfigDiagnostics} from "./model/ConfigDiagnostics"; +import _session = require('cookie-session'); const LOG_TAG = "[server]"; export class Server { diff --git a/package.json b/package.json index 8bfe4888..5fedd711 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,13 @@ "body-parser": "1.17.2", "cookie-session": "^2.0.0-beta.2", "ejs": "2.5.6", - "exif-parser": "0.1.9", + "exif-parser": "^0.1.11", "express": "4.15.3", "flat-file-db": "1.0.0", "jimp": "0.2.28", "mysql": "2.13.0", - "node-iptc": "1.0.4", "reflect-metadata": "0.1.10", + "ts-node-iptc": "^1.0.7", "typeconfig": "1.0.4", "typeorm": "0.0.11", "winston": "2.3.1" diff --git a/test/backend/unit/assets/test image öüóőúéáű-.,.jpg b/test/backend/unit/assets/test image öüóőúéáű-.,.jpg index b44dcb5d1864a8634efd043f339208ebd0534483..b6347849e9d7f69bdfd18350e81f3173283db1a1 100644 GIT binary patch delta 5594 zcmd^DeN0=|6~E6IunAuUhp#|vY`y~6@7Wj|9?v#khLD8e@R3E^s>Lx6aKJqG*#wZ9 zQL0s4)qN0dRjF0hq*K(b+oWbfYNIXcmbrATRxR7oRMV7o?H^M+wsln#?T@G%yYIbw zpKSty{xR*3DoT9Lz32YU@0@$iz3=AjS2M1Dkg>G+ht2mu;gP<9K0r|v_$T@UHs80g z{)O-a0E2^|5dfeA`BVnTKoSMA&_4x0gJdM>en}O|vKh&5P(|2=LN*m3Q?>`X4eEd@ ze?m228-zyL!TF`^QQbYtA%hqI(3`0aS+vwqDj<6AH)@Go{Ot?RAtC^902oR( zDgm<9dTnX<{w*2Cn?-i&s&CsRk?gXdIXV2>_0r%l#M;Z zGNZeK;A{_*ufhc9Pzq6!t967oeAie7ZyD<{U}?!@ zuTxAA8hebNjScjAoo#I#ouVsfzc<@wZzM&^(%?x#1n~U z*H;oSaUt<^a)rzlxlzc<wUc(G)yWp{xuRD+1c{b%FE zLCJpqS$;NdAsrfv5A#w7%SS~;0U1V=1_#NoE+-NptqF(fsvj^9^D$vg4Dq;<^l+)p zuT;7ozEL-ZNt)^nSaR1NA5khn24)Y3W2ovDNhL{jr4|zEVWrMY(oZxf#`w|2DC*O# zPW5_tv%W^BR3lRUU4Nz%D{37Oeb0!`H<*)%Z#I~c%BjW*s6XUR4!qJhoKy;$4#J^Y z{ZTpD?EDn3oIBECmfkj>A-Xg!j>d+hw^NPBlgbtz4weL+?pWcWrkSI+*$NnII-Vyl z=aktY_}e-s%xEs(rP`9k91>$n-9WLqOs(ecG+S{g{JgmVOB>BDELp7NI6Pvl#A9J= zBbJ`F61y8#aE}OvD=z6^DBicfacZMm0R)!q!%glawiaChQmYEhTy}}R{A2Y3Z z>|>?`dhJH6ow8S8>71R!|3f>;&hP95^AmeBwySoKwLK0(EaD)u7aR<>yWwC6*{YUO zSkXcpxmyUSXp0kXz7+Q1IUW{z%HYYCyxhQ?7@gsjc7^Y@kb9`W=_Ht8rx8v#NkX4= z61T59+cAMIR~am7C80=Kv^5i+XeIQek(E}m!IC!6QUKp;B}tV=N?c?^yIh?qxEEZ+ z^L1Azq15cIfrs4nN%a5}+@uUIy2+;8a+73f+k6m9Y&R?@P#RIQ&QHSj-*LPHUb>%tkymdP`I=PEa}>aqVCcO#N&$p7x=43ycC|9wWHE38 zeSJVB*GdTO;2~|76!s~w z>6@iY5A)-D%-EOr?o$O#_oxo<8lQD9zEn8)r(SX><@(7TWc8DqG~g$9)j2=0`?24$ zB>7P4e21@X^^t~O1B2m^D8z&b<<*z^aEy?d6v+uLczLBr<`KJY(&*6c!8ooYw$h)kE#-U*(O_tr zkDK_}aZmkxz0bS(kFg5)riCAsT4}T>R0c+0$ULPskSM>N>iRHlx SXX*Fv3jT+GwI*Et3;SQPi@Jya delta 3704 zcmbVPdrVu`8Nc`1gkZ`eKrki*E|1^@QvAReFvbSk7#lDcLuisp$sGHpI04&S8$!EH zQSwjQJ*0&1kD*0vmknvvvb2kss%o9ONS&f~QXW;OD4M1yQ?-Ytb;;Ce+S;}3-0$3b zZQ6uP6_UTl`M%%xINv$v^5&m4zkOSCdgIQ`{14m|--x;okOd8tTt}UxDUc zIQx>ypM#|$zl&Qvr&WNtpRTZsj)HMlS2)%5-4(5>zqL}J>hHiOMNJ%c59)OtrQBbB zSf;K#fWta}EBEg;E2>C_nr&+~478i@t!rJ#7ZctGcPp;L<;vz(&C8^2scYO* zoXd{o`SiSyjq=O$bIFWjx!)L#r;Z5@!b@tCkw=s4$$n#SKKhK{a7bG{ol4E|7ITNq zY;@_IV*I!x;`7T8MCv!f%|q=4WKGAzJ<~3O(Wv9)1cp zn-ZmLcx=v;uz&)U<`S-OG%F@f(prg#hFG|4=`?MIfu+vIMyWWW&MY1~A;hvdbWijd ziVpuhR8t^f@xa=ux^k$p1)}EMAKB{ayz0`kscb4Un@ZD$!!K>6(!P=q@7wlat2S&l zq&;0jNY8dXxmD}(_mPYN!q&-4%nt zWVSgsdYNoQkY@8@cgK#LmLw4h(KNQt&(k3SZBL`#7!fk5MKLB|y}T3M9dS6{V}*22 zu~zCYoas4GOBkmKVaVW$i6tTK7gO`tq<{8Iwn)o#HIT@Vxp+3Wb?RV1s<(Q_7XlLW z)!vqEQW(Piy7xpSvYV!ce}rSw(WE%8I(UV>>X=kmLtkVEMJ9ETmN`z%3Q4$PuY~h` zRbMSonRBm#e$`P6hn(Gt_^4oYVCXNlez_`IqIwp-)I2!SKPk1}2@m=WaHGF(tLexe zxR{v1ovwnfxoYI0JMDTBhwO@LFVed%J5qzYrAdlGd>o#+MIo>#xXeydzDSlK=59mt z6*qOe?rx>2y)vMO@`2qs;eN0XZUwi)p@CXO*#s8`=tXsHfJXm#fWmYP@(4RMNH4JG z25l`$HeNB69utmdm2^~D%IEf=5gj>CGtxGXjYd1|(Zkn0yHI(-(@B*NJO=p4L+`*+ zZx=3>daL1xw}Dr}`Gnc%b879fB!#-@rKR8U(o6L}-g*S6^X*3(@--k`@X?fBlJz%y zX7Vu5&IT6Y+^`;gGgMM0HCZ|u*m0tNf4ByE{Ut@iq9BlGfCNkp(dPVQNUmvPs0Lo2 zD3six++Rqe`{`9a;g^jr`5WL>KW*bpzZs3R!@aZt>3|*%54Yrm3;DwDhvm(b%o+l1 zidj9(2O1SY50?UabHal_Q%(qzJ+}uNG3Mo99lR1Of-^zdj?2Ly>OT#3BJCWZZHte% zQGRuVR{P-yEvS055A`#na_+BP%H11jGerGF{=NuEZ-fYx3xax zpkN^y^!bnp<+nn$NPici^H?}e_trd4uVVAK0lqW72W=$&=J-BZZQ}$F^%HdFq=lms z?W)nGKq;(_SLwowVtNku7$lSOuoga^pv{qFYnZwm3)9VdF-*_K&%<(z&%%26Buo=D zOj6_EBn3!KT4^GsksA2bWV0ePLve({EJUhdEJBafLd1vJ{UTy?DE_R{4yh zq%NhBf_G6|!rZ^`ro+#scFM2rnHfWnxX2$d>is2M8PoX)IN_>Bnfonq#~+8Qplrrg z&(4gM}+uSET>&|-Mj<;51#ZfvgOdoAaMUFdRqB|^{vDQ zBh4g^iP2GPy&hzZOdq?h#f4pP^54>s?A=w~+F9`YSezUWQr{{^mf_Q;P4 z)~`N&TcdZnm($VMNg>M%$#}oI#s-n;qfiPdj)p8f05 OJ*Td(fAHoX9sdKWxXASY diff --git a/test/backend/unit/model/threading/DiskMangerWorker.spec.ts b/test/backend/unit/model/threading/DiskMangerWorker.spec.ts index c0d7ceae..b54721b5 100644 --- a/test/backend/unit/model/threading/DiskMangerWorker.spec.ts +++ b/test/backend/unit/model/threading/DiskMangerWorker.spec.ts @@ -6,15 +6,14 @@ import {ProjectPath} from "../../../../../backend/ProjectPath"; describe('DiskMangerWorker', () => { - it('should call next on authenticated', async () => { + it('should parse metadata', async () => { Config.Server.imagesFolder = path.join(__dirname, "/../../assets"); ProjectPath.ImageFolder = path.join(__dirname, "/../../assets"); const dir = await DiskMangerWorker.scanDirectory("/"); - console.log(dir.photos[0].metadata); expect(dir.photos.length).to.be.equals(1); expect(dir.photos[0].name).to.be.equals("test image öüóőúéáű-.,.jpg"); - expect(dir.photos[0].metadata.keywords).to.deep.equals(['Berkley,USA']); - expect(dir.photos[0].metadata.fileSize).to.deep.equals(57172); + expect(dir.photos[0].metadata.keywords).to.deep.equals(['Berkley', 'USA', 'űáéúőóüö ŰÁÉÚŐÓÜÖ']); + expect(dir.photos[0].metadata.fileSize).to.deep.equals(62392); expect(dir.photos[0].metadata.size).to.deep.equals({width: 140, height: 93}); expect(dir.photos[0].metadata.cameraData).to.deep.equals({ ISO: 3200, @@ -32,9 +31,9 @@ describe('DiskMangerWorker', () => { longitude: -122.25678, altitude: 102.4498997995992 }, - country: 'óüöúőűáé ÓÜÖÚŐŰÁÉ', - state: 'óüöúőűáé ÓÜÖÚŐŰÁÉ', - city: 'óüöúőűáé ÓÜÖÚŐŰÁÉ' + country: 'mmóüöúőűáé ÓÜÖÚŐŰÁÉmm-.,|\\mm\u0000', + state: 'óüöúőűáé ÓÜÖÚŐŰÁ', + city: 'óüöúőűáé ÓÜÖÚŐŰÁ' }); expect(dir.photos[0].metadata.creationDate).to.be.equals(1436610566000);