From d4b014847a0746de99093083791d9e2a6bd9c4fc Mon Sep 17 00:00:00 2001 From: Erik Ziegler Date: Tue, 9 Aug 2016 15:53:09 +0200 Subject: [PATCH] Add ServerConfiguration schema to validate Meteor settings, removed defaultSettings, ran JSCS for DIMSEService package --- LesionTracker/defaultSettings.js | 54 - OHIFViewer/.meteor/packages | 1 + OHIFViewer/.meteor/versions | 2 + OHIFViewer/defaultSettings.js | 44 - Packages/dimseservice/package.js | 3 +- Packages/dimseservice/server/CSocket.js | 176 ++- Packages/dimseservice/server/Connection.js | 145 +- Packages/dimseservice/server/DIMSE.js | 27 +- Packages/dimseservice/server/Data.js | 1275 +++++++++-------- Packages/dimseservice/server/Field.js | 157 +- Packages/dimseservice/server/Message.js | 750 +++++----- Packages/dimseservice/server/RWStream.js | 305 ++-- Packages/dimseservice/server/methods.js | 3 - Packages/worklist/both/schema.js | 160 +++ Packages/worklist/package.js | 11 +- .../server/validateServerConfiguration.js | 12 + 16 files changed, 1696 insertions(+), 1429 deletions(-) delete mode 100644 LesionTracker/defaultSettings.js delete mode 100644 OHIFViewer/defaultSettings.js delete mode 100755 Packages/dimseservice/server/methods.js create mode 100644 Packages/worklist/both/schema.js create mode 100644 Packages/worklist/server/validateServerConfiguration.js diff --git a/LesionTracker/defaultSettings.js b/LesionTracker/defaultSettings.js deleted file mode 100644 index e980b8441..000000000 --- a/LesionTracker/defaultSettings.js +++ /dev/null @@ -1,54 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -Meteor.startup(function() { - if (Object.keys(Meteor.settings).length > 1) { - console.log('Using custom LesionTracker settings'); - console.log(Meteor.settings); - return; - } - - Meteor.settings = { - servers: { - dicomWeb: [{ - name: 'Orthanc', - wadoUriRootNOTE: 'either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently', - wadoUriRoot: 'http://localhost:8043/wado', - qidoRoot: 'http://localhost:8042/dicom-web', - wadoRoot: 'http://localhost:8042/dicom-web', - qidoSupportsIncludeField: false, - imageRendering: 'wadouri', - requestOptions: { - auth: 'orthanc:orthanc', - logRequests: true, - logResponses: false, - logTiming: true - } - }], - dimse: [{ - name: "ORTHANC_DIMSE", - peers: [{ - host: 'localhost', - port: 4242, - aeTitle: 'ORTHANC', - default: true - }] - }] - }, - "defaultServiceType": 'dicomWeb', - "public": { - "verifyEmail": false, - "ui": { - "studyListFunctionsEnabled": true - } - } - //defaultServiceType: 'dimse' - }; - - console.log('Using default LesionTracker settings with service: ' + Meteor.settings.defaultServiceType); - - // Bind events if window is closed - $(window).bind('beforeunload', function (e) { - // have to return null, unless you want a chrome popup alert - // return 'If you leave this page then any unsaved changes will be lost.'; - }); -}); diff --git a/OHIFViewer/.meteor/packages b/OHIFViewer/.meteor/packages index deeed9d59..aa93d7180 100644 --- a/OHIFViewer/.meteor/packages +++ b/OHIFViewer/.meteor/packages @@ -39,3 +39,4 @@ clinical:router fastclick@1.0.12 standard-minifier-css@1.1.8 standard-minifier-js@1.1.8 +aldeed:simple-schema diff --git a/OHIFViewer/.meteor/versions b/OHIFViewer/.meteor/versions index c3e533a69..7a8f08e69 100644 --- a/OHIFViewer/.meteor/versions +++ b/OHIFViewer/.meteor/versions @@ -1,3 +1,4 @@ +aldeed:simple-schema@1.5.3 allow-deny@1.0.5 arsnebula:reactive-promise@0.9.1 autoupdate@1.3.11 @@ -49,6 +50,7 @@ jquery@1.11.9 launch-screen@1.0.12 livedata@1.0.18 logging@1.1.14 +mdg:validation-error@0.2.0 meteor@1.2.16 meteor-base@1.0.4 meteor-platform@1.2.6 diff --git a/OHIFViewer/defaultSettings.js b/OHIFViewer/defaultSettings.js deleted file mode 100644 index dd60c7cb8..000000000 --- a/OHIFViewer/defaultSettings.js +++ /dev/null @@ -1,44 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -Meteor.startup(function() { - if (Object.keys(Meteor.settings).length > 1) { - console.log('Using custom LesionTracker settings: '); - console.log(Meteor.settings); - return; - } - - Meteor.settings = { - servers: { - dicomWeb: [{ - name: 'Orthanc', - wadoUriRootNOTE: 'either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently', - wadoUriRoot: 'http://localhost:8043/wado', - qidoRoot: 'http://localhost:8042/dicom-web', - wadoRoot: 'http://localhost:8042/dicom-web', - qidoSupportsIncludeField: false, - imageRendering: 'wadouri', - requestOptions: { - auth: 'orthanc:orthanc', - logRequests: true, - logResponses: false, - logTiming: true - } - }], - dimse: [{ - name: "ORTHANC_DIMSE", - peers: [{ - host: 'localhost', - port: 4242, - hostAE: 'ORTHANC' - }] - }] - }, - defaultServiceType: 'dicomWeb', - //defaultServiceType: 'dimse' - public: { - ui: { - studyListFunctionsEnabled: true - } - } - }; -}); diff --git a/Packages/dimseservice/package.js b/Packages/dimseservice/package.js index 73792bf6e..01bcbf017 100755 --- a/Packages/dimseservice/package.js +++ b/Packages/dimseservice/package.js @@ -5,8 +5,9 @@ Package.describe({ }); Package.onUse(function(api) { - //api.use("weiwei:dicomservices"); + api.versionsFrom('1.4'); + api.use('ecmascript'); api.addFiles('server/require.js', 'server'); api.addFiles('server/constants.js', 'server'); api.addFiles('server/elements_data.js', 'server'); diff --git a/Packages/dimseservice/server/CSocket.js b/Packages/dimseservice/server/CSocket.js index 4c4a19cc7..2baf6e6d0 100755 --- a/Packages/dimseservice/server/CSocket.js +++ b/Packages/dimseservice/server/CSocket.js @@ -5,14 +5,15 @@ function time() { } function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min)) + min; + return Math.floor(Math.random() * (max - min)) + min; } var Envelope = function(command, dataset) { EventEmitter.call(this); this.command = command; this.dataset = dataset; -} +}; + util.inherits(Envelope, EventEmitter); CSocket = function(socket, options) { @@ -39,35 +40,43 @@ CSocket = function(socket, options) { this.options = options; var o = this; - this.socket.on("connect", function(){ + this.socket.on('connect', function() { + console.log('Connect'); o.ready(); }); - this.socket.on("data", function(data) { + this.socket.on('data', function(data) { o.received(data); }); - this.socket.on("error", function(he) { - console.log("Error: ", he); + this.socket.on('error', function(he) { + console.log('Error: ', he); + throw 'Error: ' + he; }); - this.socket.on("close", function() { + this.socket.on('timeout', function(he) { + console.log('Timeout: ', he); + throw 'Timeout: ' + he; + }); + this.socket.on('close', function() { if (o.intervalId) { clearInterval(o.intervalId); } - o.connected = false; - console.log("Connection closed"); - o.emit('close'); - }) - this.on("released", function() { + o.connected = false; + console.log('Connection closed'); + o.emit('close'); + }); + + this.on('released', function() { this.released(); }); this.on('aborted', function(pdu) { - console.log('Assocation aborted with reason ' + pdu.reason); + console.warn('Association aborted with reason ' + pdu.reason); this.released(); - }) + }); this.on('message', function(pdvs) { this.receivedMessage(pdvs); }); }; + util.inherits(CSocket, EventEmitter); CSocket.prototype.setCallingAE = function(ae) { @@ -84,22 +93,23 @@ CSocket.prototype.associate = function() { associateRQ.setCallingAETitle(this.callingAe); associateRQ.setApplicationContextItem(new ApplicationContextItem()); - var contextItems = [] + var contextItems = []; this.presentationContexts.forEach(function(context) { - var contextItem = new PresentationContextItem(), - syntaxes = []; - context.transferSyntaxes.forEach(function(transferSyntax) { - var transfer = new TransferSyntaxItem(); - transfer.setTransferSyntaxName(transferSyntax); - syntaxes.push(transfer); - }); - contextItem.setTransferSyntaxesItems(syntaxes); - contextItem.setPresentationContextID(context.id); + var contextItem = new PresentationContextItem(), + syntaxes = []; - var abstractItem = new AbstractSyntaxItem(); - abstractItem.setAbstractSyntaxName(context.abstractSyntax); - contextItem.setAbstractSyntaxItem(abstractItem); - contextItems.push(contextItem); + context.transferSyntaxes.forEach(function(transferSyntax) { + var transfer = new TransferSyntaxItem(); + transfer.setTransferSyntaxName(transferSyntax); + syntaxes.push(transfer); + }); + contextItem.setTransferSyntaxesItems(syntaxes); + contextItem.setPresentationContextID(context.id); + + var abstractItem = new AbstractSyntaxItem(); + abstractItem.setAbstractSyntaxName(context.abstractSyntax); + contextItem.setAbstractSyntaxItem(abstractItem); + contextItems.push(contextItem); }); associateRQ.setPresentationContextItems(contextItems); @@ -123,39 +133,45 @@ CSocket.prototype.associate = function() { CSocket.prototype.getContext = function(id) { for (var k in this.presentationContexts) { var ctx = this.presentationContexts[k]; - if (id == ctx.id) return ctx; + if (id === ctx.id) { + return ctx; + } } + return null; -} +}; CSocket.prototype.getSyntax = function(contextId) { if (!this.negotiatedContexts[contextId]) return null; return this.negotiatedContexts[contextId].transferSyntax; -} +}; CSocket.prototype.getContextByUID = function(uid) { for (var k in this.negotiatedContexts) { var ctx = this.negotiatedContexts[k]; - if (ctx.abstractSyntax == uid) { + if (ctx.abstractSyntax === uid) { return ctx; } } + return null; -} +}; CSocket.prototype.getContextId = function(contextId) { - if (!this.negotiatedContexts[contextId]) return null; + if (!this.negotiatedContexts[contextId]) { + return null; + } return this.negotiatedContexts[contextId].id; -} +}; CSocket.prototype.setPresentationContexts = function(uids) { var contexts = [], id = 0; uids.forEach(function(uid) { id++; - if (typeof uid == 'string') { + if (typeof uid === 'string') { contexts.push({ id: id, abstractSyntax: uid, @@ -174,7 +190,7 @@ CSocket.prototype.setPresentationContexts = function(uids) { CSocket.prototype.newMessageId = function() { return (++this.messageIdCounter) % 65536; -} +}; CSocket.prototype.resetReceive = function() { this.receiving = this.receiveLength = null; @@ -197,7 +213,7 @@ CSocket.prototype.released = function() { }; CSocket.prototype.ready = function() { - console.log("Connection established"); + console.log('Connection established'); this.connected = true; this.started = time(); @@ -217,8 +233,6 @@ CSocket.prototype.checkIdle = function() { this.idleClose(); } else if (this.lastReceived && (current - this.lastReceived >= idl)) { this.idleClose(); - } else { - //console.log('keep idling') } }; @@ -228,7 +242,6 @@ CSocket.prototype.idleClose = function() { }; CSocket.prototype.received = function(data) { - var i = 0; do { data = this.process(data); } while (data !== null); @@ -236,7 +249,6 @@ CSocket.prototype.received = function(data) { }; CSocket.prototype.process = function(data) { - //console.log("Data received"); if (this.receiving === null) { if (this.minRecv) { data = Buffer.concat([this.minRecv, data], this.minRecv.length + data.length); @@ -263,6 +275,7 @@ CSocket.prototype.process = function(data) { process = data.slice(0, len + 6); remaining = data.slice(len + 6, cmp + 6); } + this.resetReceive(); this.interpret(new ReadStream(process), this); if (remaining) { @@ -270,6 +283,7 @@ CSocket.prototype.process = function(data) { } } } else { + console.log('Data received'); var newData = Buffer.concat([this.receiving, data], this.receiving.length + data.length), pduLength = newData.length - 6; @@ -281,6 +295,7 @@ CSocket.prototype.process = function(data) { remaining = newData.slice(this.receiveLength + 6, pduLength + 6); newData = newData.slice(0, this.receiveLength + 6); } + this.resetReceive(); this.interpret(new ReadStream(newData)); if (remaining) { @@ -288,6 +303,7 @@ CSocket.prototype.process = function(data) { } } } + return null; }; @@ -302,8 +318,9 @@ CSocket.prototype.interpret = function(stream) { pdu.presentationContextItems.forEach(function(ctx) { var requested = o.getContext(ctx.presentationContextID); if (!requested) { - throw "Accepted presentation context not found"; + throw 'Accepted presentation context not found'; } + o.negotiatedContexts[ctx.presentationContextID] = { id: ctx.presentationContextID, transferSyntax: ctx.transferSyntaxesItems[0].transferSyntaxName, @@ -350,11 +367,13 @@ CSocket.prototype.interpret = function(stream) { break; } } + if (pdvs[i].isLast) { this.emit('message', pdvs[i]); } else { this.pendingPDVs = [pdvs[i]]; } + i = j; } else { this.emit('message', pdvs[i++]); @@ -377,9 +396,11 @@ CSocket.prototype.receivedMessage = function(pdv) { if (msg.is(C.COMMAND_C_GET_RSP) || msg.is(C.COMMAND_C_MOVE_RSP)) { //console.log('remaining', msg.getNumOfRemainingSubOperations(), msg.getNumOfCompletedSubOperations()); } + if (msg.failure()) { - console.log("message failed with status ", msg.getStatus().toString(16)); + console.log('message failed with status ', msg.getStatus().toString(16)); } + listener.emit('response', msg); if (msg.isFinal()) { if (listener) { @@ -403,7 +424,7 @@ CSocket.prototype.receivedMessage = function(pdv) { } else { if (!this.lastCommand) { - throw "Only dataset?"; + throw 'Only dataset?'; } else if (!this.lastCommand.haveData()) { throw "Last command didn't indicate presence of data"; } @@ -413,7 +434,7 @@ CSocket.prototype.receivedMessage = function(pdv) { if (this.messages[replyId].listener) { var flag = this.lastCommand.failure() ? true : false; - this.messages[replyId].listener.emit("result", msg, flag); + this.messages[replyId].listener.emit('result', msg, flag); if (this.lastCommand.failure()) { delete this.messages[replyId]; @@ -429,7 +450,7 @@ CSocket.prototype.receivedMessage = function(pdv) { if (this.lastGets.length > 0) { useId = this.lastGets[0]; } else { - throw "Where does this c-store came from?"; + throw 'Where does this c-store came from?'; } } else console.log('move ', moveMessageId); //this.storeResponse(useId, msg); @@ -447,7 +468,7 @@ CSocket.prototype.wrapToPData = function(message, context) { pdv.setMessage(message); pdata.setPresentationDataValueItems([pdv]); return pdata; -} +}; CSocket.prototype.sendMessage = function(context, command, dataset) { var nContext = this.getContextByUID(context), @@ -459,7 +480,7 @@ CSocket.prototype.sendMessage = function(context, command, dataset) { msgData.listener = new Envelope(command); var o = this; - msgData.listener.on('cancel', function(){ + msgData.listener.on('cancel', function() { var cancelMessage = null; if (this.command.is(C.COMMAND_C_FIND_RQ) || this.command.is(C.COMMAND_C_MOVE_RQ)) { cancelMessage = new CCancelRQ(); @@ -474,20 +495,22 @@ CSocket.prototype.sendMessage = function(context, command, dataset) { command.setSyntax(C.IMPLICIT_LITTLE_ENDIAN); command.setContextId(context); command.setMessageId(messageId); - if (dataset) + if (dataset) { command.setDataSetPresent(C.DATA_SET_PRESENT); + } this.lastSent = command; if (command.is(C.COMMAND_C_GET_RQ)) { this.lastGets.push(messageId); } + var pdata = this.wrapToPData(command); msgData.command = command; this.messages[messageId] = msgData; console.log('Sending command ' + command.typeString()); this.send(pdata); - if (dataset && typeof dataset == 'object') { + if (dataset && typeof dataset === 'object') { dataset.setSyntax(syntax); var dsData = new PDataTF(), dPdv = new PresentationDataValueItem(cid); @@ -496,6 +519,7 @@ CSocket.prototype.sendMessage = function(context, command, dataset) { dsData.setPresentationDataValueItems([dPdv]); this.send(dsData); } + return msgData.listener; }; @@ -520,7 +544,9 @@ CSocket.prototype.wrapMessage = function(data) { var datasetMessage = new DataSetMessage(); datasetMessage.setElements(data); return datasetMessage; - } else return data; + } else { + return data; + } }; CSocket.prototype.find = function(params, options) { @@ -540,14 +566,14 @@ CSocket.prototype.storeInstance = function(sopClassUID, sopInstanceUID, options) storeMessage.setAffectedSOPClassUID(sopClassUID); return this.sendMessage(sopClassUID, storeMessage, true); -} +}; CSocket.prototype.moveInstances = function(destination, params, options) { var sendParams = Object.assign({ 0x00080052: C.QUERY_RETRIEVE_LEVEL_IMAGE, }, params); options = Object.assign({ - context : C.SOP_STUDY_ROOT_MOVE + context: C.SOP_STUDY_ROOT_MOVE }, options); return this.move(destination, sendParams, options); @@ -556,13 +582,13 @@ CSocket.prototype.moveInstances = function(destination, params, options) { CSocket.prototype.findPatients = function(params, options) { var sendParams = Object.assign({ 0x00080052: C.QUERY_RETRIEVE_LEVEL_PATIENT, - 0x00100010: "", - 0x00100020: "", - 0x00100030: "", - 0x00100040: "", + 0x00100010: '', + 0x00100020: '', + 0x00100030: '', + 0x00100040: '', }, params); options = Object.assign({ - context : C.SOP_PATIENT_ROOT_FIND + context: C.SOP_PATIENT_ROOT_FIND }, options); return this.find(sendParams, options); @@ -571,13 +597,13 @@ CSocket.prototype.findPatients = function(params, options) { CSocket.prototype.findStudies = function(params, options) { var sendParams = Object.assign({ 0x00080052: C.QUERY_RETRIEVE_LEVEL_STUDY, - 0x00080020: "", - 0x00100010: "", - 0x00080061: "", - 0x0020000D: "" + 0x00080020: '', + 0x00100010: '', + 0x00080061: '', + 0x0020000D: '' }, params); options = Object.assign({ - context : C.SOP_STUDY_ROOT_FIND + context: C.SOP_STUDY_ROOT_FIND }, options); return this.find(sendParams, options); @@ -586,13 +612,13 @@ CSocket.prototype.findStudies = function(params, options) { CSocket.prototype.findSeries = function(params, options) { var sendParams = Object.assign({ 0x00080052: C.QUERY_RETRIEVE_LEVEL_SERIES, - 0x00080020: "", - 0x0020000E: "", - 0x0008103E: "", - 0x0020000D: "" + 0x00080020: '', + 0x0020000E: '', + 0x0008103E: '', + 0x0020000D: '' }, params); options = Object.assign({ - context : C.SOP_STUDY_ROOT_FIND + context: C.SOP_STUDY_ROOT_FIND }, options); return this.find(sendParams, options); @@ -601,14 +627,14 @@ CSocket.prototype.findSeries = function(params, options) { CSocket.prototype.findInstances = function(params, options) { var sendParams = Object.assign({ 0x00080052: C.QUERY_RETRIEVE_LEVEL_IMAGE, - 0x00080020: "", - 0x0020000E: "", - 0x0008103E: "", - 0x0020000D: "" + 0x00080020: '', + 0x0020000E: '', + 0x0008103E: '', + 0x0020000D: '' }, params); options = Object.assign({ - context : C.SOP_STUDY_ROOT_FIND + context: C.SOP_STUDY_ROOT_FIND }, options); return this.find(sendParams, options); -}; \ No newline at end of file +}; diff --git a/Packages/dimseservice/server/Connection.js b/Packages/dimseservice/server/Connection.js index 1133e825b..2e46cd7f9 100755 --- a/Packages/dimseservice/server/Connection.js +++ b/Packages/dimseservice/server/Connection.js @@ -1,9 +1,11 @@ +// Uses NodeJS 'net' +// https://nodejs.org/api/net.html var net = Npm.require('net'), Socket = net.Socket; var DEFAULT_MAX_PACKAGE_SIZE = 32768; -Connection = function (options) { +Connection = function(options) { EventEmitter.call(this); this.options = Object.assign({ maxPackageSize: C.DEFAULT_MAX_PACKAGE_SIZE, @@ -18,21 +20,24 @@ Connection = function (options) { this.peerSockets = {}; this.defaultPeer = null; this.defaultServer = null; -} +}; util.inherits(Connection, EventEmitter); -var StoreHandle = function () { +var StoreHandle = function() { EventEmitter.call(this); -} +}; + util.inherits(StoreHandle, EventEmitter); -Connection.prototype.addPeer = function (options) { +Connection.prototype.addPeer = function(options) { if (!options.aeTitle || !options.host || !options.port) { return false; } + this.peers[options.aeTitle] = { - host: options.host, port: options.port + host: options.host, + port: options.port }; if (options.default) { if (options.server) { @@ -41,90 +46,103 @@ Connection.prototype.addPeer = function (options) { this.defaultPeer = options.aeTitle; } } + if (options.server) { //start listening var server = net.createServer(); - server.listen(options.port, options.host, function () { - console.log("listening on %j", this.address()); + server.listen(options.port, options.host, function() { + console.log('listening on %j', this.address()); }); - server.on('error', function (err) { - console.log("server error %j", err); + server.on('error', function(err) { + console.log('server error %j', err); }); var o = this; - server.on('connection', function (nativeSocket) { + server.on('connection', function(nativeSocket) { //incoming connections var socket = new CSocket(nativeSocket, o.options); o.addSocket(options.aeTitle, socket); //close server on close socket - socket.on('close', function () { + socket.on('close', function() { server.close(); }); }); } }; -Connection.prototype.selectPeer = function (aeTitle) { +Connection.prototype.selectPeer = function(aeTitle) { if (!aeTitle || !this.peers[aeTitle]) { - throw "No such peer"; + throw 'No such peer'; } + return this.peers[aeTitle]; }; -Connection.prototype._sendFile = function (socket, sHandle, file, maxSend, metaLength, list) { - var fileNameText = typeof file.file == 'string' ? file.file : 'buffer'; - console.log("Sending file " + fileNameText); - var useContext = socket.getContextByUID(file.context), self = this; +Connection.prototype._sendFile = function(socket, sHandle, file, maxSend, metaLength, list) { + var fileNameText = typeof file.file === 'string' ? file.file : 'buffer'; + console.log('Sending file ' + fileNameText); + var useContext = socket.getContextByUID(file.context), + self = this; - PDU.generatePDatas(useContext.id, file.file, maxSend, null, metaLength, function (err, handle) { + PDU.generatePDatas(useContext.id, file.file, maxSend, null, metaLength, function(err, handle) { if (err) { console.log('Error while sending file'); return; } - var processNext = function () { + + var processNext = function() { var next = list.shift(); - if (next) + if (next) { self._sendFile(socket, sHandle, next, maxSend, metaLength, list); - else + } else { socket.release(); + } }; var store = socket.storeInstance(useContext.abstractSyntax, file.uid); - handle.on('pdv', function (pdv) { + handle.on('pdv', function(pdv) { socket.sendPData(pdv); }); - handle.on('error', function (err) { + handle.on('error', function(err) { sHandle.emit('file', err, fileNameText); processNext(); }); - store.on('response', function (msg) { + store.on('response', function(msg) { var statusText = msg.getStatus().toString(16); console.log('STORE reponse with status', statusText); var error = null; if (msg.failure()) { error = new Error(statusText); } + sHandle.emit('file', error, fileNameText); processNext(); }); }); }; -Connection.prototype.storeInstances = function (fileList) { - var contexts = {}, read = 0, length = fileList.length, toSend = [], self = this, handle = new StoreHandle(); +Connection.prototype.storeInstances = function(fileList) { + var contexts = {}, + read = 0, + length = fileList.length, + toSend = [], + self = this, + handle = new StoreHandle(); var lastProcessedMetaLength; - fileList.forEach(function (bufferOrFile) { - var fileNameText = typeof bufferOrFile == 'string' ? bufferOrFile : 'buffer'; - DicomMessage.readMetaHeader(bufferOrFile, function (err, metaMessage, metaLength) { + fileList.forEach(function(bufferOrFile) { + var fileNameText = typeof bufferOrFile === 'string' ? bufferOrFile : 'buffer'; + DicomMessage.readMetaHeader(bufferOrFile, function(err, metaMessage, metaLength) { read++; if (err) { handle.emit('file', err, fileNameText); - if (read == length && toSend.length > 0 && lastProcessedMetaLength) { + if (read === length && toSend.length > 0 && lastProcessedMetaLength) { sendProcessedFiles(self, contexts, toSend, handle, lastProcessedMetaLength); } + return; } - console.log('Dicom file ' + (typeof bufferOrFile == 'string' ? bufferOrFile : 'buffer') + ' found'); + + console.log('Dicom file ' + (typeof bufferOrFile === 'string' ? bufferOrFile : 'buffer') + ' found'); lastProcessedMetaLength = metaLength; var syntax = metaMessage.getValue(0x00020010), sopClassUID = metaMessage.getValue(0x00020002), @@ -133,12 +151,18 @@ Connection.prototype.storeInstances = function (fileList) { if (!contexts[sopClassUID]) { contexts[sopClassUID] = []; } - if (syntax && contexts[sopClassUID].indexOf(syntax) == -1) { + + if (syntax && contexts[sopClassUID].indexOf(syntax) === -1) { contexts[sopClassUID].push(syntax); } - toSend.push({file: bufferOrFile, context: sopClassUID, uid: instanceUID}); - if (read == length) { + toSend.push({ + file: bufferOrFile, + context: sopClassUID, + uid: instanceUID + }); + + if (read === length) { sendProcessedFiles(self, contexts, toSend, handle, metaLength); } }); @@ -147,27 +171,31 @@ Connection.prototype.storeInstances = function (fileList) { }; // Starts to send dcm files -sendProcessedFiles = function (self, contexts, toSend, handle, metaLength) { +sendProcessedFiles = function(self, contexts, toSend, handle, metaLength) { var useContexts = []; for (var context in contexts) { var useSyntaxes = contexts[context]; if (useSyntaxes.length > 0) { - useContexts.push({context: context, syntaxes: contexts[context]}); + useContexts.push({ + context: context, + syntaxes: contexts[context] + }); } else { - throw "No syntax specified for context " + context; + throw 'No syntax specified for context ' + context; } } self.associate({ contexts: useContexts - }, function (ac) { - var maxSend = ac.getMaxSize(), next = toSend.shift(); + }, function(ac) { + var maxSend = ac.getMaxSize(), + next = toSend.shift(); self._sendFile(this, handle, next, maxSend, metaLength, toSend); }); }; -Connection.prototype.storeResponse = function (messageId, msg) { +Connection.prototype.storeResponse = function(messageId, msg) { var rq = this.messages[messageId]; if (rq.listener[2]) { @@ -180,12 +208,12 @@ Connection.prototype.storeResponse = function (messageId, msg) { replyMessage.setReplyMessageId(this.lastCommand.messageId); this.sendMessage(replyMessage, null, null, storeSr); } else { - throw "Missing store status"; + throw 'Missing store status'; } } }; -Connection.prototype.allClosed = function () { +Connection.prototype.allClosed = function() { var allClosed = true; for (var i in o.peerSockets) { if (Object.keys(o.peerSockets[ae]).length > 0) { @@ -193,48 +221,61 @@ Connection.prototype.allClosed = function () { break; } } + return allClosed; }; -Connection.prototype.addSocket = function (ae, socket) { +Connection.prototype.addSocket = function(ae, socket) { if (!this.peerSockets[ae]) { this.peerSockets[ae] = {}; } + this.peerSockets[ae][socket.id] = socket; var o = this; - socket.on("close", function () { + socket.on('close', function() { if (o.peerSockets[ae][this.id]) { delete o.peerSockets[ae][this.id]; } }); }; -Connection.prototype.associate = function (options, callback) { +Connection.prototype.associate = function(options, callback) { var hostAE = options.hostAE ? options.hostAE : this.defaultPeer, sourceAE = options.sourceAE ? options.sourceAE : this.defaultServer; + if (!hostAE || !sourceAE) { - throw "Peers not provided or no defaults in settings"; + throw 'Peers not provided or no defaults in settings'; } - var peerInfo = this.selectPeer(hostAE), nativeSocket = new Socket(); - var socket = new CSocket(nativeSocket, this.options), o = this; + var peerInfo = this.selectPeer(hostAE), + nativeSocket = new Socket(); + + var socket = new CSocket(nativeSocket, this.options), + o = this; + if (callback) { socket.once('associated', callback); } + + console.log('Starting Connection...'); + socket.setCalledAe(hostAE); socket.setCallingAE(sourceAE); + console.log(peerInfo); + nativeSocket.connect({ - host: peerInfo.host, port: peerInfo.port - }, function () { + host: peerInfo.host, + port: peerInfo.port + }, function() { //connected o.addSocket(hostAE, socket); if (options.contexts) { socket.setPresentationContexts(options.contexts); } else { - throw "Contexts must be specified"; + throw 'Contexts must be specified'; } socket.associate(); diff --git a/Packages/dimseservice/server/DIMSE.js b/Packages/dimseservice/server/DIMSE.js index f5f0c7cb9..96554e2d5 100755 --- a/Packages/dimseservice/server/DIMSE.js +++ b/Packages/dimseservice/server/DIMSE.js @@ -56,12 +56,14 @@ var getInstanceRetrievalParams = function(studyInstanceUID, seriesInstanceUID) { Meteor.startup(function() { if (!Meteor.settings.servers.dimse || !Meteor.settings.servers.dimse.length) { - return; + console.error('dimse-config: ' + 'No DIMSE Servers provided.'); + throw new Meteor.Error('dimse-config', 'No DIMSE Servers provided.'); } // TODO: [custom-servers] use active server and check if type is DIMSE var peers = Meteor.settings.servers.dimse[0].peers; if (!peers || !peers.length) { + console.error('dimse-config: ' + 'No DIMSE Peers provided.'); throw new Meteor.Error('dimse-config', 'No DIMSE Peers provided.'); } @@ -71,7 +73,7 @@ Meteor.startup(function() { conn.addPeer(peer); }); } catch(error) { - console.warn('dimse-addPeers: ' + error); + console.error('dimse-addPeers: ' + error); throw new Meteor.Error('dimse-addPeers', error); } }); @@ -82,6 +84,7 @@ DIMSE.associate = function(contexts, callback, options) { }; options = Object.assign(defaults, options); + console.log('Associating...'); try { conn.associate(options, function(pdu) { // associated @@ -89,7 +92,7 @@ DIMSE.associate = function(contexts, callback, options) { callback.call(this, pdu); }); } catch(error) { - console.warn('dimse-associate: ' + error); + console.error('dimse-associate: ' + error); throw new Meteor.Error('dimse-associate', error); } }; @@ -165,7 +168,8 @@ DIMSE.retrieveStudies = function(params, options) { }; DIMSE._retrieveInstancesBySeries = function(conn, series, studyInstanceUID, callback, params) { - var aSeries = series.shift(), seriesInstanceUID = aSeries.getValue(0x0020000E), + var aSeries = series.shift(), + seriesInstanceUID = aSeries.getValue(0x0020000E), defaultParams = getInstanceRetrievalParams(studyInstanceUID, seriesInstanceUID); var result = conn.findInstances(Object.assign(defaultParams, params)), @@ -189,8 +193,9 @@ DIMSE.retrieveInstancesByStudyOnlyMulti = function(studyInstanceUID, params, opt return []; } - var series = DIMSE.retrieveSeries(studyInstanceUID, params, options), instances = []; - series.forEach(function(seriesData){ + var series = DIMSE.retrieveSeries(studyInstanceUID, params, options), + instances = []; + series.forEach(function(seriesData) { var seriesInstanceUID = seriesData.getValue(0x0020000E); var relatedInstances = DIMSE.retrieveInstances(studyInstanceUID, seriesInstanceUID, params, options); @@ -205,7 +210,7 @@ DIMSE.retrieveInstancesByStudyOnly = function(studyInstanceUID, params, options) } var future = new Future; - DIMSE.associate([C.SOP_STUDY_ROOT_FIND], function(pdu){ + DIMSE.associate([C.SOP_STUDY_ROOT_FIND], function(pdu) { var defaultParams = { 0x0020000D: studyInstanceUID, 0x00080005: '', @@ -220,14 +225,16 @@ DIMSE.retrieveInstancesByStudyOnly = function(studyInstanceUID, params, options) 0x00200011: '' }; var result = this.findSeries(Object.assign(defaultParams, params)), - series = [], conn = this, allInstances = []; + series = [], + conn = this, + allInstances = []; result.on('result', function(msg) { series.push(msg); }); - result.on('end', function(){ + result.on('end', function() { if (series.length > 0) { - DIMSE._retrieveInstancesBySeries(conn, series, studyInstanceUID, function(relatedInstances, isEnd){ + DIMSE._retrieveInstancesBySeries(conn, series, studyInstanceUID, function(relatedInstances, isEnd) { allInstances = allInstances.concat(relatedInstances); if (isEnd) { conn.release(); diff --git a/Packages/dimseservice/server/Data.js b/Packages/dimseservice/server/Data.js index 08bf69ca8..22a51dc62 100755 --- a/Packages/dimseservice/server/Data.js +++ b/Packages/dimseservice/server/Data.js @@ -1,954 +1,1021 @@ function paddingLeft(paddingValue, string) { - return String(paddingValue + string).slice(-paddingValue.length); -}; + return String(paddingValue + string).slice(-paddingValue.length); +} function rtrim(str) { - return str.replace(/\s*$/g, ''); + return str.replace(/\s*$/g, ''); } function ltrim(str) { - return str.replace(/^\s*/g, ''); + return str.replace(/^\s*/g, ''); } function fieldsLength(fields) { - var length = 0; - fields.forEach(function(field) { - length += field.length(); - }); - return length; -}; + var length = 0; + fields.forEach(function(field) { + length += field.length(); + }); + return length; +} Tag = function(value) { - this.value = value; + this.value = value; }; Tag.prototype.toString = function() { - return "(" + paddingLeft("0000", this.group().toString(16)) + "," + - paddingLeft("0000", this.element().toString(16)) + ")"; -} + return '(' + paddingLeft('0000', this.group().toString(16)) + ',' + + paddingLeft('0000', this.element().toString(16)) + ')'; +}; Tag.prototype.is = function(t) { - return this.value == t; -} + return this.value === t; +}; Tag.prototype.group = function() { - return this.value >>> 16; -} + return this.value >>> 16; +}; Tag.prototype.element = function() { - return this.value & 0xffff; -} + return this.value & 0xffff; +}; tagFromNumbers = function(group, element) { - return new Tag(((group << 16) | element) >>> 0); -} + return new Tag(((group << 16) | element) >>> 0); +}; function readTag(stream) { - var group = stream.read(C.TYPE_UINT16), - element = stream.read(C.TYPE_UINT16); + var group = stream.read(C.TYPE_UINT16), + element = stream.read(C.TYPE_UINT16); - var tag = tagFromNumbers(group, element); - return tag; + return tagFromNumbers(group, element); } -parseElements = function (stream, syntax) { - var pairs = {}; - stream.reset(); - while (!stream.end()) { - var elem = new DataElement(); - elem.setSyntax(syntax); - elem.readBytes(stream); - pairs[elem.tag.value] = elem; - } - return pairs; -} +parseElements = function(stream, syntax) { + var pairs = {}; + stream.reset(); + while (!stream.end()) { + var elem = new DataElement(); + elem.setSyntax(syntax); + elem.readBytes(stream); + pairs[elem.tag.value] = elem; + } + + return pairs; +}; ValueRepresentation = function(type) { - this.type = type; - this.multi = false; -} + this.type = type; + this.multi = false; +}; ValueRepresentation.prototype.read = function(stream, length, syntax) { - if (this.fixed && this.maxLength) { - if (!length) - return this.defaultValue; - if (this.maxLength != length) - console.log("Invalid length for fixed length tag, vr " + this.type + ", length " + this.maxLength + " != " + length); - } - return this.readBytes(stream, length, syntax); -} + if (this.fixed && this.maxLength) { + if (!length) { + return this.defaultValue; + } + + if (this.maxLength !== length) { + console.log('Invalid length for fixed length tag, vr ' + this.type + ', length ' + this.maxLength + ' !== ' + length); + } + } + + return this.readBytes(stream, length, syntax); +}; ValueRepresentation.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_ASCII, length); -} + return stream.read(C.TYPE_ASCII, length); +}; ValueRepresentation.prototype.readNullPaddedString = function(stream, length) { - if (!length) return ""; + if (!length) { + return ''; + } - var str = stream.read(C.TYPE_ASCII, length - 1); - if (stream.read(C.TYPE_UINT8) != 0) { - stream.increment(-1); - str += stream.read(C.TYPE_ASCII, 1); - } - return str; -} + var str = stream.read(C.TYPE_ASCII, length - 1); + if (stream.read(C.TYPE_UINT8) !== 0) { + stream.increment(-1); + str += stream.read(C.TYPE_ASCII, 1); + } + + return str; +}; ValueRepresentation.prototype.getFields = function(fields) { - var valid = true; - if (this.checkLength) { - valid = this.checkLength(fields); - } else if (this.maxCharLength) { - var check = this.maxCharLength, length = 0; - fields.forEach(function(field){ - if (typeof field.value == 'string') - length += field.value.length; - }); - valid = length <= check; - } else if (this.maxLength) { - var check = this.maxLength, length = fieldsLength(fields); - valid = length <= check; - } - if (!valid) - throw "Value exceeds max length"; - - //check for odd - var length = fieldsLength(fields); - if (length & 1) { - fields.push(new HexField(this.padByte)); - } - - for (var i = 0;i < fields.length;i++) { - if (fields[i].isNumeric() && (fields[i].value === "" || fields[i].value === null)) { - fields[i] = new StringField(""); + var valid = true; + if (this.checkLength) { + valid = this.checkLength(fields); + } else if (this.maxCharLength) { + var check = this.maxCharLength, + length = 0; + fields.forEach(function(field) { + if (typeof field.value === 'string') + length += field.value.length; + }); + valid = length <= check; + } else if (this.maxLength) { + var check = this.maxLength, + length = fieldsLength(fields); + valid = length <= check; } - } - return fields; -} + if (!valid) { + throw 'Value exceeds max length'; + } + + //check for odd + var length = fieldsLength(fields); + if (length & 1) { + fields.push(new HexField(this.padByte)); + } + + for (var i = 0;i < fields.length;i++) { + if (fields[i].isNumeric() && (fields[i].value === '' || fields[i].value === null)) { + fields[i] = new StringField(''); + } + } + + return fields; +}; ApplicationEntity = function() { - ValueRepresentation.call(this, "AE"); - this.maxLength = 16; - this.padByte = "20"; + ValueRepresentation.call(this, 'AE'); + this.maxLength = 16; + this.padByte = '20'; }; + util.inherits(ApplicationEntity, ValueRepresentation); ApplicationEntity.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_ASCII, length).trim(); -} + return stream.read(C.TYPE_ASCII, length).trim(); +}; ApplicationEntity.prototype.getFields = function(value) { - return ApplicationEntity.super_.prototype.getFields.call(this, [new FilledField(value, 16)]); -} + return ApplicationEntity.super_.prototype.getFields.call(this, [new FilledField(value, 16)]); +}; CodeString = function() { - ValueRepresentation.call(this, "CS"); - this.maxLength = 16; - this.padByte = "20"; + ValueRepresentation.call(this, 'CS'); + this.maxLength = 16; + this.padByte = '20'; }; + util.inherits(CodeString, ValueRepresentation); CodeString.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return str.trim(); -} + var str = this.readNullPaddedString(stream, length); + return str.trim(); +}; CodeString.prototype.getFields = function(value) { - return CodeString.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return CodeString.super_.prototype.getFields.call(this, [new StringField(value)]); +}; AgeString = function() { - ValueRepresentation.call(this, "AS"); - this.maxLength = 4; - this.padByte = "20"; - this.fixed = true; - this.defaultValue = ""; + ValueRepresentation.call(this, 'AS'); + this.maxLength = 4; + this.padByte = '20'; + this.fixed = true; + this.defaultValue = ''; }; + util.inherits(AgeString, ValueRepresentation); AgeString.prototype.getFields = function(value) { - var str = ""; - if (value) { - if (value.days) { - str = paddingLeft("000" + value.days) + "D"; - } else if (value.weeks) { - str = paddingLeft("000" + value.weeks) + "W"; - } else if (value.months) { - str = paddingLeft("000" + value.months) + "M"; - } else if (value.years) { - str = paddingLeft("000" + value.years) + "Y"; - } else { - throw "Invalid age string"; - } - } + var str = ''; + if (value) { + if (value.days) { + str = paddingLeft('000' + value.days) + 'D'; + } else if (value.weeks) { + str = paddingLeft('000' + value.weeks) + 'W'; + } else if (value.months) { + str = paddingLeft('000' + value.months) + 'M'; + } else if (value.years) { + str = paddingLeft('000' + value.years) + 'Y'; + } else { + throw 'Invalid age string'; + } + } - return AgeString.super_.prototype.getFields.call(this, [new StringField(str)]); -} + return AgeString.super_.prototype.getFields.call(this, [new StringField(str)]); +}; AttributeTag = function() { - ValueRepresentation.call(this, "AT"); - this.maxLength = 4; - this.padByte = "00"; - this.fixed = true; + ValueRepresentation.call(this, 'AT'); + this.maxLength = 4; + this.padByte = '00'; + this.fixed = true; }; + util.inherits(AttributeTag, ValueRepresentation); AttributeTag.prototype.readBytes = function(stream, length) { - var group = stream.read(C.TYPE_UINT16), element = stream.read(C.TYPE_UINT16); - return tagFromNumbers(group, element); -} + var group = stream.read(C.TYPE_UINT16), + element = stream.read(C.TYPE_UINT16); + return tagFromNumbers(group, element); +}; AttributeTag.prototype.getFields = function(value) { - return AttributeTag.super_.prototype.getFields.call(this, [new UInt16Field(value.group()), new UInt16Field(value.element())]); -} + return AttributeTag.super_.prototype.getFields.call(this, [new UInt16Field(value.group()), new UInt16Field(value.element())]); +}; DateValue = function() { - ValueRepresentation.call(this, "DA"); - this.maxLength = 8; - this.padByte = "20"; - this.fixed = true; - this.defaultValue = ""; + ValueRepresentation.call(this, 'DA'); + this.maxLength = 8; + this.padByte = '20'; + this.fixed = true; + this.defaultValue = ''; }; + util.inherits(DateValue, ValueRepresentation); DateValue.prototype.readBytes = function(stream, length) { - var datestr = stream.read(C.TYPE_ASCII, length); + var datestr = stream.read(C.TYPE_ASCII, length); - var year = parseInt(datestr.substring(0,4)), - month = parseInt(datestr.substring(4,6)), - day = parseInt(datestr.substring(6,8)); + var year = parseInt(datestr.substring(0, 4)), + month = parseInt(datestr.substring(4, 6)), + day = parseInt(datestr.substring(6, 8)); - return datestr;//new Date(year, month, day); -} + return datestr;//new Date(year, month, day); +}; DateValue.prototype.getFields = function(date) { - var str = null; - if (typeof date == 'object') { - var year = date.getFullYear(), month = paddingLeft("00", date.getMonth()), day = paddingLeft("00", date.getDate()); - str = year + month + day; - } else if (date && date.length > 0) { - this.maxLength = 18; - this.fixed = false; - str = date; - } else { - str = ""; - } + var str = null; + if (typeof date === 'object') { + var year = date.getFullYear(), + month = paddingLeft('00', date.getMonth()), + day = paddingLeft('00', date.getDate()); + str = year + month + day; + } else if (date && date.length > 0) { + this.maxLength = 18; + this.fixed = false; + str = date; + } else { + str = ''; + } - return DateValue.super_.prototype.getFields.call(this, [new StringField(str)]); -} + return DateValue.super_.prototype.getFields.call(this, [new StringField(str)]); +}; DecimalString = function() { - ValueRepresentation.call(this, "DS"); - this.maxLength = 16; - this.padByte = "20"; + ValueRepresentation.call(this, 'DS'); + this.maxLength = 16; + this.padByte = '20'; }; + util.inherits(DecimalString, ValueRepresentation); DecimalString.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return str.trim(); -} + var str = this.readNullPaddedString(stream, length); + return str.trim(); +}; DecimalString.prototype.getFields = function(value) { - var f = parseFloat(value); - return DecimalString.super_.prototype.getFields.call(this, [new StringField(isNaN(f) ? '' : f.toExponential())]); -} + var f = parseFloat(value); + return DecimalString.super_.prototype.getFields.call(this, [new StringField(isNaN(f) ? '' : f.toExponential())]); +}; DateTime = function() { - ValueRepresentation.call(this, "DT"); - this.maxLength = 26; - this.padByte = "20"; + ValueRepresentation.call(this, 'DT'); + this.maxLength = 26; + this.padByte = '20'; }; + util.inherits(DateTime, ValueRepresentation); DateTime.prototype.getFields = function(value) { - var year = date.getUTCFullYear(), month = paddingLeft("00", date.getUTCMonth()), - day = paddingLeft("00", date.getUTCDate()), hour = paddingLeft("00", date.getUTCHours()), - minute = paddingLeft("00", date.getUTCMinutes()), second = paddingLeft("00", date.getUTCSeconds()), - millisecond = paddingLeft("000", date.getUTCMilliseconds()); + var year = date.getUTCFullYear(), + month = paddingLeft('00', date.getUTCMonth()), + day = paddingLeft('00', date.getUTCDate()), + hour = paddingLeft('00', date.getUTCHours()), + minute = paddingLeft('00', date.getUTCMinutes()), + second = paddingLeft('00', date.getUTCSeconds()), + millisecond = paddingLeft('000', date.getUTCMilliseconds()); - return DateTime.super_.prototype.getFields.call(this, [new StringField(year + month + day + hour + minute + second + "." + millisecond + "+0000")]); -} + return DateTime.super_.prototype.getFields.call(this, [new StringField(year + month + day + hour + minute + second + '.' + millisecond + '+0000')]); +}; FloatingPointSingle = function() { - ValueRepresentation.call(this, "FL"); - this.maxLength = 4; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0.0; + ValueRepresentation.call(this, 'FL'); + this.maxLength = 4; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0.0; }; + util.inherits(FloatingPointSingle, ValueRepresentation); FloatingPointSingle.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_FLOAT); -} + return stream.read(C.TYPE_FLOAT); +}; FloatingPointSingle.prototype.getFields = function(value) { - return FloatingPointSingle.super_.prototype.getFields.call(this, [new FloatField(value)]); -} + return FloatingPointSingle.super_.prototype.getFields.call(this, [new FloatField(value)]); +}; FloatingPointDouble = function() { - ValueRepresentation.call(this, "FD"); - this.maxLength = 8; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0.0; + ValueRepresentation.call(this, 'FD'); + this.maxLength = 8; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0.0; }; + util.inherits(FloatingPointDouble, ValueRepresentation); FloatingPointDouble.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_DOUBLE); -} + return stream.read(C.TYPE_DOUBLE); +}; FloatingPointDouble.prototype.getFields = function(value) { - return FloatingPointDouble.super_.prototype.getFields.call(this, [new DoubleField(value)]); -} + return FloatingPointDouble.super_.prototype.getFields.call(this, [new DoubleField(value)]); +}; IntegerString = function() { - ValueRepresentation.call(this, "IS"); - this.maxLength = 12; - this.padByte = "20"; + ValueRepresentation.call(this, 'IS'); + this.maxLength = 12; + this.padByte = '20'; }; + util.inherits(IntegerString, ValueRepresentation); IntegerString.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return str.trim(); -} + var str = this.readNullPaddedString(stream, length); + return str.trim(); +}; IntegerString.prototype.getFields = function(value) { - return IntegerString.super_.prototype.getFields.call(this, [new StringField(value.toString())]); -} + return IntegerString.super_.prototype.getFields.call(this, [new StringField(value.toString())]); +}; LongString = function() { - ValueRepresentation.call(this, "LO"); - this.maxCharLength = 64; - this.padByte = "20"; + ValueRepresentation.call(this, 'LO'); + this.maxCharLength = 64; + this.padByte = '20'; }; + util.inherits(LongString, ValueRepresentation); LongString.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return str.trim(); -} + var str = this.readNullPaddedString(stream, length); + return str.trim(); +}; LongString.prototype.getFields = function(value) { - return LongString.super_.prototype.getFields.call(this, [new StringField(value ? value : "")]); -} + return LongString.super_.prototype.getFields.call(this, [new StringField(value ? value : '')]); +}; LongText = function() { - ValueRepresentation.call(this, "LT"); - this.maxCharLength = 10240; - this.padByte = "20"; + ValueRepresentation.call(this, 'LT'); + this.maxCharLength = 10240; + this.padByte = '20'; }; + util.inherits(LongText, ValueRepresentation); LongText.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return rtrim(str); -} + var str = this.readNullPaddedString(stream, length); + return rtrim(str); +}; LongText.prototype.getFields = function(value) { - return LongText.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return LongText.super_.prototype.getFields.call(this, [new StringField(value)]); +}; PersonName = function() { - ValueRepresentation.call(this, "PN"); - this.maxLength = null; - this.padByte = "20"; + ValueRepresentation.call(this, 'PN'); + this.maxLength = null; + this.padByte = '20'; }; + util.inherits(PersonName, ValueRepresentation); PersonName.prototype.checkLength = function(field) { - var cmps = field[0].value.split(/\^/); - for (var i in cmps) { - var cmp = cmps[i]; - if (cmp.length > 64) return false; - } - return true; -} + var cmps = field[0].value.split(/\^/); + for (var i in cmps) { + var cmp = cmps[i]; + if (cmp.length > 64) return false; + } + + return true; +}; PersonName.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return rtrim(str); -} + var str = this.readNullPaddedString(stream, length); + return rtrim(str); +}; PersonName.prototype.getFields = function(value) { - var str = null; - if (typeof value == 'string') { - str = value; - } else if (value) { - var fName = value.family || "", gName = value.given || "", - middle = value.middle || "", prefix = value.prefix || "", suffix = value.suffix || ""; + var str = null; + if (typeof value === 'string') { + str = value; + } else if (value) { + var fName = value.family || '', + gName = value.given || '', + middle = value.middle || '', + prefix = value.prefix || '', + suffix = value.suffix || ''; - str = [fName, gName, middle, prefix, suffix].join("^"); - } else str = ''; + str = [fName, gName, middle, prefix, suffix].join('^'); + } else str = ''; - return PersonName.super_.prototype.getFields.call(this, [new StringField(str)]); -} + return PersonName.super_.prototype.getFields.call(this, [new StringField(str)]); +}; ShortString = function() { - ValueRepresentation.call(this, "SH"); - this.maxCharLength = 16; - this.padByte = "20"; + ValueRepresentation.call(this, 'SH'); + this.maxCharLength = 16; + this.padByte = '20'; }; + util.inherits(ShortString, ValueRepresentation); ShortString.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return str.trim(); -} + var str = this.readNullPaddedString(stream, length); + return str.trim(); +}; ShortString.prototype.getFields = function(value) { - return ShortString.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return ShortString.super_.prototype.getFields.call(this, [new StringField(value)]); +}; SignedLong = function() { - ValueRepresentation.call(this, "SL"); - this.maxLength = 4; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0; + ValueRepresentation.call(this, 'SL'); + this.maxLength = 4; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0; }; + util.inherits(SignedLong, ValueRepresentation); SignedLong.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_INT32); -} + return stream.read(C.TYPE_INT32); +}; SignedLong.prototype.getFields = function(value) { - return SignedLong.super_.prototype.getFields.call(this, [new Int32Field(value)]); -} + return SignedLong.super_.prototype.getFields.call(this, [new Int32Field(value)]); +}; SequenceOfItems = function() { - ValueRepresentation.call(this, "SQ"); - this.maxLength = null; - this.padByte = "00"; + ValueRepresentation.call(this, 'SQ'); + this.maxLength = null; + this.padByte = '00'; }; + util.inherits(SequenceOfItems, ValueRepresentation); SequenceOfItems.prototype.readBytes = function(stream, sqlength, syntax) { - if (sqlength == 0x0) { - return []; //contains no dataset - } else { - var undefLength = sqlength == 0xffffffff, elements = [], read = 0; + if (sqlength === 0x0) { + return []; //contains no dataset + } else { + var undefLength = sqlength === 0xffffffff, + elements = [], + read = 0; - while (true) { - var tag = readTag(stream), length = null; - read += 4; + while (true) { + var tag = readTag(stream), + length = null; + read += 4; - if (tag.is(0xfffee0dd)) { - stream.read(C.TYPE_UINT32) - break; - } else if (!undefLength && (read == sqlength)) { - break; - } else if (tag.is(0xfffee000)) { - length = stream.read(C.TYPE_UINT32); - read += 4; - var itemStream = null, toRead = 0, undef = length == 0xffffffff; + if (tag.is(0xfffee0dd)) { + stream.read(C.TYPE_UINT32); + break; + } else if (!undefLength && (read === sqlength)) { + break; + } else if (tag.is(0xfffee000)) { + length = stream.read(C.TYPE_UINT32); + read += 4; + var itemStream = null, + toRead = 0, + undef = length === 0xffffffff; - if (undef) { - var stack = 0; - while (1) { - var g = stream.read(C.TYPE_UINT16); - if (g == 0xfffe) { - var ge = stream.read(C.TYPE_UINT16); - if (ge == 0xe00d) { - stack--; - if (stack < 0) { - stream.increment(4); - read += 8; - break; + if (undef) { + var stack = 0; + while (1) { + var g = stream.read(C.TYPE_UINT16); + if (g === 0xfffe) { + var ge = stream.read(C.TYPE_UINT16); + if (ge === 0xe00d) { + stack--; + if (stack < 0) { + stream.increment(4); + read += 8; + break; + } else { + toRead += 4; + } + } else if (ge === 0xe000) { + stack++; + toRead += 4; + } else { + toRead += 2; + stream.increment(-2); + } + } else { + toRead += 2; + } + } } else { - toRead += 4; + toRead = length; + } + + if (toRead) { + stream.increment(undef ? (-toRead - 8) : 0); + itemStream = stream.more(toRead);//parseElements + read += toRead; + if (undef) + stream.increment(8); + + elements.push(parseElements(itemStream, syntax)); + } + + if (!undefLength && (read === sqlength)) { + break; } - } else if (ge == 0xe000) { - stack++; - toRead += 4; - } else { - toRead += 2; - stream.increment(-2); - } - } else { - toRead += 2; } - } - } else { - toRead = length; } - if (toRead) { - stream.increment(undef ? (-toRead-8) : 0); - itemStream = stream.more(toRead);//parseElements - read += toRead; - if (undef) - stream.increment(8); - - elements.push(parseElements(itemStream, syntax)); - } - if (!undefLength && (read == sqlength)) { - break; - } - } + return elements; } - return elements; - } -} +}; SequenceOfItems.prototype.getFields = function(value, syntax) { - var fields = []; - if (value) { - value.forEach(function(message) { - fields.push(new UInt16Field(0xfffe)); - fields.push(new UInt16Field(0xe000)); - fields.push(new UInt32Field(0xffffffff)); + var fields = []; + if (value) { + value.forEach(function(message) { + fields.push(new UInt16Field(0xfffe)); + fields.push(new UInt16Field(0xe000)); + fields.push(new UInt32Field(0xffffffff)); - message.forEach(function(element) { - element.setSyntax(syntax); - fields = fields.concat(element.getFields()); - }); + message.forEach(function(element) { + element.setSyntax(syntax); + fields = fields.concat(element.getFields()); + }); - fields.push(new UInt16Field(0xfffe)); - fields.push(new UInt16Field(0xe00d)); - fields.push(new UInt32Field(0x00000000)); - }); - } + fields.push(new UInt16Field(0xfffe)); + fields.push(new UInt16Field(0xe00d)); + fields.push(new UInt32Field(0x00000000)); + }); + } - fields.push(new UInt16Field(0xfffe)); - fields.push(new UInt16Field(0xe0dd)); - fields.push(new UInt32Field(0x00000000)); + fields.push(new UInt16Field(0xfffe)); + fields.push(new UInt16Field(0xe0dd)); + fields.push(new UInt32Field(0x00000000)); - return SequenceOfItems.super_.prototype.getFields.call(this, fields); -} + return SequenceOfItems.super_.prototype.getFields.call(this, fields); +}; SignedShort = function() { - ValueRepresentation.call(this, "SS"); - this.maxLength = 2; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0; + ValueRepresentation.call(this, 'SS'); + this.maxLength = 2; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0; }; + util.inherits(SignedShort, ValueRepresentation); SignedShort.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_INT16); -} + return stream.read(C.TYPE_INT16); +}; SignedShort.prototype.getFields = function(value) { - return SignedShort.super_.prototype.getFields.call(this, [new Int16Field(value)]); -} + return SignedShort.super_.prototype.getFields.call(this, [new Int16Field(value)]); +}; ShortText = function() { - ValueRepresentation.call(this, "ST"); - this.maxCharLength = 1024; - this.padByte = "20"; + ValueRepresentation.call(this, 'ST'); + this.maxCharLength = 1024; + this.padByte = '20'; }; + util.inherits(ShortText, ValueRepresentation); ShortText.prototype.readBytes = function(stream, length) { - var str = this.readNullPaddedString(stream, length); - return rtrim(str); -} + var str = this.readNullPaddedString(stream, length); + return rtrim(str); +}; ShortText.prototype.getFields = function(value) { - return ShortText.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return ShortText.super_.prototype.getFields.call(this, [new StringField(value)]); +}; TimeValue = function() { - ValueRepresentation.call(this, "TM"); - this.maxLength = 14; - this.padByte = "20"; + ValueRepresentation.call(this, 'TM'); + this.maxLength = 14; + this.padByte = '20'; }; + util.inherits(TimeValue, ValueRepresentation); TimeValue.prototype.readBytes = function(stream, length) { - return rtrim(stream.read(C.TYPE_ASCII, length)); -} + return rtrim(stream.read(C.TYPE_ASCII, length)); +}; TimeValue.prototype.getFields = function(date) { - var dateStr = ''; - if (date) { - var hour = paddingLeft("00", date.getHours()), - minute = paddingLeft("00", date.getMinutes()), second = paddingLeft("00", date.getSeconds()), - millisecond = paddingLeft("000", date.getMilliseconds()); - dateStr = hour + minute + second + "." + millisecond; - } + var dateStr = ''; + if (date) { + var hour = paddingLeft('00', date.getHours()), + minute = paddingLeft('00', date.getMinutes()), + second = paddingLeft('00', date.getSeconds()), + millisecond = paddingLeft('000', date.getMilliseconds()); + dateStr = hour + minute + second + '.' + millisecond; + } - return TimeValue.super_.prototype.getFields.call(this, [new StringField(dateStr)]); -} + return TimeValue.super_.prototype.getFields.call(this, [new StringField(dateStr)]); +}; UnlimitedCharacters = function() { - ValueRepresentation.call(this, "UC"); - this.maxLength = null; - this.multi = true; - this.padByte = "20"; + ValueRepresentation.call(this, 'UC'); + this.maxLength = null; + this.multi = true; + this.padByte = '20'; }; + util.inherits(UnlimitedCharacters, ValueRepresentation); UnlimitedCharacters.prototype.readBytes = function(stream, length) { - return rtrim(stream.read(C.TYPE_ASCII, length)); -} + return rtrim(stream.read(C.TYPE_ASCII, length)); +}; UnlimitedCharacters.prototype.getFields = function(value) { - return UnlimitedCharacters.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return UnlimitedCharacters.super_.prototype.getFields.call(this, [new StringField(value)]); +}; UnlimitedText = function() { - ValueRepresentation.call(this, "UT"); - this.maxLength = null; - this.padByte = "20"; + ValueRepresentation.call(this, 'UT'); + this.maxLength = null; + this.padByte = '20'; }; + util.inherits(UnlimitedText, ValueRepresentation); UnlimitedText.prototype.readBytes = function(stream, length) { - return this.readNullPaddedString(stream, length); -} + return this.readNullPaddedString(stream, length); +}; UnlimitedText.prototype.getFields = function(value) { - return UnlimitedText.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return UnlimitedText.super_.prototype.getFields.call(this, [new StringField(value)]); +}; UnsignedShort = function() { - ValueRepresentation.call(this, "US"); - this.maxLength = 2; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0; + ValueRepresentation.call(this, 'US'); + this.maxLength = 2; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0; }; + util.inherits(UnsignedShort, ValueRepresentation); UnsignedShort.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_UINT16); -} + return stream.read(C.TYPE_UINT16); +}; UnsignedShort.prototype.getFields = function(value) { - return UnsignedShort.super_.prototype.getFields.call(this, [new UInt16Field(value)]); -} + return UnsignedShort.super_.prototype.getFields.call(this, [new UInt16Field(value)]); +}; UnsignedLong = function() { - ValueRepresentation.call(this, "UL"); - this.maxLength = 4; - this.padByte = "00"; - this.fixed = true; - this.defaultValue = 0; + ValueRepresentation.call(this, 'UL'); + this.maxLength = 4; + this.padByte = '00'; + this.fixed = true; + this.defaultValue = 0; }; + util.inherits(UnsignedLong, ValueRepresentation); UnsignedLong.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_UINT32); -} + return stream.read(C.TYPE_UINT32); +}; UnsignedLong.prototype.getFields = function(value) { - return UnsignedLong.super_.prototype.getFields.call(this, [new UInt32Field(value)]); -} + return UnsignedLong.super_.prototype.getFields.call(this, [new UInt32Field(value)]); +}; UniqueIdentifier = function() { - ValueRepresentation.call(this, "UI"); - this.maxLength = 64; - this.padByte = "00"; + ValueRepresentation.call(this, 'UI'); + this.maxLength = 64; + this.padByte = '00'; }; + util.inherits(UniqueIdentifier, ValueRepresentation); UniqueIdentifier.prototype.readBytes = function(stream, length) { - return this.readNullPaddedString(stream, length); -} + return this.readNullPaddedString(stream, length); +}; UniqueIdentifier.prototype.getFields = function(value) { - return UniqueIdentifier.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return UniqueIdentifier.super_.prototype.getFields.call(this, [new StringField(value)]); +}; UniversalResource = function() { - ValueRepresentation.call(this, "UR"); - this.maxLength = null; - this.padByte = "20"; + ValueRepresentation.call(this, 'UR'); + this.maxLength = null; + this.padByte = '20'; }; + util.inherits(UniversalResource, ValueRepresentation); UniversalResource.prototype.readBytes = function(stream, length) { - return rtrim(stream.read(C.TYPE_ASCII, length)); -} + return rtrim(stream.read(C.TYPE_ASCII, length)); +}; UniversalResource.prototype.getFields = function(value) { - return UniversalResource.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return UniversalResource.super_.prototype.getFields.call(this, [new StringField(value)]); +}; UnknownValue = function() { - ValueRepresentation.call(this, "UN"); - this.maxLength = null; - this.padByte = "00"; + ValueRepresentation.call(this, 'UN'); + this.maxLength = null; + this.padByte = '00'; }; + util.inherits(UnknownValue, ValueRepresentation); UnknownValue.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_ASCII, length); -} + return stream.read(C.TYPE_ASCII, length); +}; UnknownValue.prototype.getFields = function(value) { - return UnknownValue.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return UnknownValue.super_.prototype.getFields.call(this, [new StringField(value)]); +}; OtherWordString = function() { - ValueRepresentation.call(this, "OW"); - this.maxLength = null; - this.padByte = "00"; + ValueRepresentation.call(this, 'OW'); + this.maxLength = null; + this.padByte = '00'; }; + util.inherits(OtherWordString, ValueRepresentation); OtherWordString.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_ASCII, length); -} + return stream.read(C.TYPE_ASCII, length); +}; OtherWordString.prototype.getFields = function(value) { - return OtherWordString.super_.prototype.getFields.call(this, [new StringField(value)]); -} + return OtherWordString.super_.prototype.getFields.call(this, [new StringField(value)]); +}; OtherByteString = function() { - ValueRepresentation.call(this, "OB"); - this.maxLength = null; - this.padByte = "00"; + ValueRepresentation.call(this, 'OB'); + this.maxLength = null; + this.padByte = '00'; }; + util.inherits(OtherByteString, ValueRepresentation); OtherByteString.prototype.readBytes = function(stream, length) { - return stream.read(C.TYPE_HEX, length); -} + return stream.read(C.TYPE_HEX, length); +}; OtherByteString.prototype.getFields = function(value) { - return OtherByteString.super_.prototype.getFields.call(this, [new HexField(value)]); -} + return OtherByteString.super_.prototype.getFields.call(this, [new HexField(value)]); +}; elementByType = function(type, value, syntax) { - var elem = null, nk = DicomElements.dicomNDict[type]; - if (nk) { - if (nk.vr == 'SQ') { - var sq = []; - if (value) - value.forEach(function(el) { - var values = []; - for (var tag in el) { - values.push(elementByType(tag, el[tag], syntax)); - } - sq.push(values); - }); - elem = new DataElement(type, nk.vr, nk.vm, sq, false, syntax); + var elem = null, + nk = DicomElements.dicomNDict[type]; + if (nk) { + if (nk.vr === 'SQ') { + var sq = []; + if (value) + value.forEach(function(el) { + var values = []; + for (var tag in el) { + values.push(elementByType(tag, el[tag], syntax)); + } + + sq.push(values); + }); + elem = new DataElement(type, nk.vr, nk.vm, sq, false, syntax); + } else { + elem = new DataElement(type, nk.vr, nk.vm, value, false, syntax); + } } else { - elem = new DataElement(type, nk.vr, nk.vm, value, false, syntax); + throw 'Unrecognized element type'; } - } else { - throw "Unrecognized element type"; - } - return elem; -} + + return elem; +}; elementDataByTag = function(tag) { - var nk = DicomElements.dicomNDict[tag]; - if (nk) { - return nk; - } - throw ("Unrecognized tag " + (tag >>> 0).toString(16)); -} + var nk = DicomElements.dicomNDict[tag]; + if (nk) { + return nk; + } + + throw ('Unrecognized tag ' + (tag >>> 0).toString(16)); +}; elementKeywordByTag = function(tag) { - var nk = elementDataByTag(tag); - return nk.keyword; -} + var nk = elementDataByTag(tag); + return nk.keyword; +}; vrByType = function(type) { - var vr = null; - if (type == "AE") vr = new ApplicationEntity(); - else if (type == "AS") vr = new AgeString(); - else if (type == "AT") vr = new AttributeTag(); - else if (type == "CS") vr = new CodeString(); - else if (type == "DA") vr = new DateValue(); - else if (type == "DS") vr = new DecimalString(); - else if (type == "DT") vr = new DateTime(); - else if (type == "FL") vr = new FloatingPointSingle(); - else if (type == "FD") vr = new FloatingPointDouble(); - else if (type == "IS") vr = new IntegerString(); - else if (type == "LO") vr = new LongString(); - else if (type == "LT") vr = new LongText(); - else if (type == "OB") vr = new OtherByteString(); - else if (type == "OD") vr = new OtherDoubleString(); - else if (type == "OF") vr = new OtherFloatString(); - else if (type == "OW") vr = new OtherWordString(); - else if (type == "PN") vr = new PersonName(); - else if (type == "SH") vr = new ShortString(); - else if (type == "SL") vr = new SignedLong(); - else if (type == "SQ") vr = new SequenceOfItems(); - else if (type == "SS") vr = new SignedShort(); - else if (type == "ST") vr = new ShortText(); - else if (type == "TM") vr = new TimeValue(); - else if (type == "UC") vr = new UnlimitedCharacters(); - else if (type == "UI") vr = new UniqueIdentifier(); - else if (type == "UL") vr = new UnsignedLong(); - else if (type == "UN") vr = new UnknownValue(); - else if (type == "UR") vr = new UniversalResource(); - else if (type == "US") vr = new UnsignedShort(); - else if (type == "UT") vr = new UnlimitedText(); - else throw "Invalid vr type " + type; + var vr = null; + if (type === 'AE') vr = new ApplicationEntity(); + else if (type === 'AS') vr = new AgeString(); + else if (type === 'AT') vr = new AttributeTag(); + else if (type === 'CS') vr = new CodeString(); + else if (type === 'DA') vr = new DateValue(); + else if (type === 'DS') vr = new DecimalString(); + else if (type === 'DT') vr = new DateTime(); + else if (type === 'FL') vr = new FloatingPointSingle(); + else if (type === 'FD') vr = new FloatingPointDouble(); + else if (type === 'IS') vr = new IntegerString(); + else if (type === 'LO') vr = new LongString(); + else if (type === 'LT') vr = new LongText(); + else if (type === 'OB') vr = new OtherByteString(); + else if (type === 'OD') vr = new OtherDoubleString(); + else if (type === 'OF') vr = new OtherFloatString(); + else if (type === 'OW') vr = new OtherWordString(); + else if (type === 'PN') vr = new PersonName(); + else if (type === 'SH') vr = new ShortString(); + else if (type === 'SL') vr = new SignedLong(); + else if (type === 'SQ') vr = new SequenceOfItems(); + else if (type === 'SS') vr = new SignedShort(); + else if (type === 'ST') vr = new ShortText(); + else if (type === 'TM') vr = new TimeValue(); + else if (type === 'UC') vr = new UnlimitedCharacters(); + else if (type === 'UI') vr = new UniqueIdentifier(); + else if (type === 'UL') vr = new UnsignedLong(); + else if (type === 'UN') vr = new UnknownValue(); + else if (type === 'UR') vr = new UniversalResource(); + else if (type === 'US') vr = new UnsignedShort(); + else if (type === 'UT') vr = new UnlimitedText(); + else throw 'Invalid vr type ' + type; - return vr; -} + return vr; +}; readElements = function(stream, syntax) { - if (stream.end()) return false; + if (stream.end()) return false; - var oldEndian = stream.endian; - stream.setEndian(this.endian); + var oldEndian = stream.endian; + stream.setEndian(this.endian); - var group = stream.read(C.TYPE_UINT16), - element = stream.read(C.TYPE_UINT16), - tag = new Tag((group << 16) | element), - length = stream.read(C.TYPE_UINT32); + var group = stream.read(C.TYPE_UINT16), + element = stream.read(C.TYPE_UINT16), + tag = new Tag((group << 16) | element), + length = stream.read(C.TYPE_UINT32); - stream.setEndian(oldEndian); -} + stream.setEndian(oldEndian); +}; readAElement = function(stream, syntax) { - var elem = newElementWithSyntax(syntax); - elem.readBytes(stream); - return elem; -} + var elem = newElementWithSyntax(syntax); + elem.readBytes(stream); + return elem; +}; newElementWithSyntax = function(syntax) { - var elem = new DataElement(); - elem.setSyntax(syntax); - return elem; -} + var elem = new DataElement(); + elem.setSyntax(syntax); + return elem; +}; -var explicitVRList = ["OB", "OW", "OF", "SQ", "UC", "UR", "UT", "UN"], - binaryVRs = ["FL", "FD", "SL", "SS", "UL", "US"]; +var explicitVRList = ['OB', 'OW', 'OF', 'SQ', 'UC', 'UR', 'UT', 'UN'], + binaryVRs = ['FL', 'FD', 'SL', 'SS', 'UL', 'US']; DataElement = function(tag, vr, vm, value, vvr, syntax, options) { - this.vr = vr ? vrByType(vr) : null; - this.tag = !vvr ? new Tag(tag) : tag; - this.value = value; - this.vm = vm; - this.vvr = vvr ? true : false; - this.setOptions(options); - this.setSyntax(syntax ? syntax : C.IMPLICIT_LITTLE_ENDIAN); + this.vr = vr ? vrByType(vr) : null; + this.tag = !vvr ? new Tag(tag) : tag; + this.value = value; + this.vm = vm; + this.vvr = vvr ? true : false; + this.setOptions(options); + this.setSyntax(syntax ? syntax : C.IMPLICIT_LITTLE_ENDIAN); }; DataElement.prototype.setOptions = function(options) { - this.options = Object.assign({split : true}, options); -} + this.options = Object.assign({ + split: true + }, options); +}; DataElement.prototype.setSyntax = function(syn) { - this.syntax = syn; - this.implicit = this.syntax == C.IMPLICIT_LITTLE_ENDIAN ? true : false; - this.endian = (this.syntax == C.IMPLICIT_LITTLE_ENDIAN || this.syntax == C.EXPLICIT_LITTLE_ENDIAN) ? C.LITTLE_ENDIAN : C.BIG_ENDIAN; -} + this.syntax = syn; + this.implicit = this.syntax === C.IMPLICIT_LITTLE_ENDIAN ? true : false; + this.endian = (this.syntax === C.IMPLICIT_LITTLE_ENDIAN || this.syntax === C.EXPLICIT_LITTLE_ENDIAN) ? C.LITTLE_ENDIAN : C.BIG_ENDIAN; +}; DataElement.prototype.getValue = function() { - if (!this.singleValue() && !this.isBinaryNumber()) { - return this.options.split ? this.value.split(String.fromCharCode(0x5c)) : this.value; - } else { - return this.value; - } -} + if (!this.singleValue() && !this.isBinaryNumber()) { + return this.options.split ? this.value.split(String.fromCharCode(0x5c)) : this.value; + } else { + return this.value; + } +}; DataElement.prototype.singleValue = function() { - return this.vm == C.VM_SINGLE ? true : false; -} + return this.vm === C.VM_SINGLE ? true : false; +}; DataElement.prototype.getVMNum = function() { - var num = 1; - switch(this.vm) { + var num = 1; + switch (this.vm) { case C.VM_SINGLE : num = 1; break; case C.VM_TWO : num = 2; break; case C.VM_THREE : num = 3; break; case C.VM_FOUR : num = 4; break; case C.VM_16 : num = 16; break; default : break; - } - return num; } + return num; +}; DataElement.prototype.isBinaryNumber = function() { - return binaryVRs.indexOf(this.vr.type) != -1; -} + return binaryVRs.indexOf(this.vr.type) !== -1; +}; DataElement.prototype.length = function(fields) { - //let fields = this.vr.getFields(this.value); - return fieldsLength(fields); -} + //let fields = this.vr.getFields(this.value); + return fieldsLength(fields); +}; DataElement.prototype.readBytes = function(stream) { - var oldEndian = stream.endian; - stream.setEndian(this.endian); + var oldEndian = stream.endian; + stream.setEndian(this.endian); - var group = stream.read(C.TYPE_UINT16), - element = stream.read(C.TYPE_UINT16), - tag = tagFromNumbers(group, element); + var group = stream.read(C.TYPE_UINT16), + element = stream.read(C.TYPE_UINT16), + tag = tagFromNumbers(group, element); - var length = null, vr = null, edata = elementDataByTag(tag.value), - vm = edata.vm; + var length = null, + vr = null, + edata = elementDataByTag(tag.value), + vm = edata.vm; - if (this.implicit) { - length = stream.read(C.TYPE_UINT32); - vr = edata.vr; - } else { - vr = stream.read(C.TYPE_ASCII, 2); - if (explicitVRList.indexOf(vr) != -1) { - stream.increment(2); - length = stream.read(C.TYPE_UINT32); + if (this.implicit) { + length = stream.read(C.TYPE_UINT32); + vr = edata.vr; } else { - length = stream.read(C.TYPE_UINT16); + vr = stream.read(C.TYPE_ASCII, 2); + if (explicitVRList.indexOf(vr) !== -1) { + stream.increment(2); + length = stream.read(C.TYPE_UINT32); + } else { + length = stream.read(C.TYPE_UINT16); + } } - } - this.vr = vrByType(vr); - this.tag = tag; - this.vm = vm; - //try { - if (this.isBinaryNumber() && length > this.vr.maxLength) { - var times = length / this.vr.maxLength, i = 0; - this.value = [];//console.log(times, length, this.vr.maxLength);return; + this.vr = vrByType(vr); + this.tag = tag; + this.vm = vm; //try { - while (i++ < times) { - this.value.push(this.vr.read(stream, this.vr.maxLength)); + if (this.isBinaryNumber() && length > this.vr.maxLength) { + var times = length / this.vr.maxLength, + i = 0; + this.value = [];//console.log(times, length, this.vr.maxLength);return; + //try { + while (i++ < times) { + this.value.push(this.vr.read(stream, this.vr.maxLength)); + } + //} catch (e) { } + } else { + this.value = this.vr.read(stream, length, this.syntax); } - //} catch (e) { } - } else { - this.value = this.vr.read(stream, length, this.syntax); - } - //} catch (e) { console.log('error', vr, length); } + //} catch (e) { console.log('error', vr, length); } - stream.setEndian(oldEndian); -} + stream.setEndian(oldEndian); +}; DataElement.prototype.write = function(stream) { - var oldEndian = stream.endian; - stream.setEndian(this.endian); + var oldEndian = stream.endian; + stream.setEndian(this.endian); - var fields = this.getFields(); - fields.forEach(function(field){ - field.write(stream); - }); + var fields = this.getFields(); + fields.forEach(function(field) { + field.write(stream); + }); - stream.setEndian(oldEndian); -} + stream.setEndian(oldEndian); +}; DataElement.prototype.getFields = function() { - var fields = [new UInt16Field(this.tag.group()), new UInt16Field(this.tag.element())], - valueFields = this.vr.getFields(this.value, this.syntax), valueLength = fieldsLength(valueFields), vrType = this.vr.type; + var fields = [new UInt16Field(this.tag.group()), new UInt16Field(this.tag.element())], + valueFields = this.vr.getFields(this.value, this.syntax), + valueLength = fieldsLength(valueFields), + vrType = this.vr.type; - if (vrType == "SQ") { - valueLength = 0xffffffff; - } + if (vrType === 'SQ') { + valueLength = 0xffffffff; + } - if (this.implicit) { - fields.push(new UInt32Field(valueLength)); - } else { - if (explicitVRList.indexOf(vrType) != -1) { - fields.push(new StringField(vrType), new ReservedField(2), new UInt32Field(valueLength)); + if (this.implicit) { + fields.push(new UInt32Field(valueLength)); } else { - fields.push(new StringField(vrType), new UInt16Field(valueLength)); - } - } - - fields = fields.concat(valueFields); - return fields; -} + if (explicitVRList.indexOf(vrType) !== -1) { + fields.push(new StringField(vrType), new ReservedField(2), new UInt32Field(valueLength)); + } else { + fields.push(new StringField(vrType), new UInt16Field(valueLength)); + } + } + fields = fields.concat(valueFields); + return fields; +}; diff --git a/Packages/dimseservice/server/Field.js b/Packages/dimseservice/server/Field.js index b8d2b1790..afa3a2a8f 100755 --- a/Packages/dimseservice/server/Field.js +++ b/Packages/dimseservice/server/Field.js @@ -1,143 +1,156 @@ Field = function(type, value) { - this.type = type; - this.value = value; + this.type = type; + this.value = value; }; Field.prototype.length = function() { - return calcLength(this.type, this.value); -} + return calcLength(this.type, this.value); +}; Field.prototype.write = function(stream) { - stream.write(this.type, this.value); -} + stream.write(this.type, this.value); +}; Field.prototype.isNumeric = function() { - return false; -} + return false; +}; BufferField = function(buffer, start, length) { - Field.call(this, C.TYPE_BUFFER, buffer); - this.bufferLength = length; - this.bufferStart = start; -} + Field.call(this, C.TYPE_BUFFER, buffer); + this.bufferLength = length; + this.bufferStart = start; +}; + util.inherits(BufferField, Field); BufferField.prototype.length = function() { - return this.bufferLength; -} + return this.bufferLength; +}; BufferField.prototype.write = function(stream) { - stream.writeRawBuffer(this.value, this.bufferStart, this.bufferLength); -} + stream.writeRawBuffer(this.value, this.bufferStart, this.bufferLength); +}; StringField = function(str) { - Field.call(this, C.TYPE_ASCII, typeof str == 'string' ? str : ""); -} + Field.call(this, C.TYPE_ASCII, typeof str == 'string' ? str : ''); +}; + util.inherits(StringField, Field); FilledField = function(value, length) { - Field.call(this, C.TYPE_COMPOSITE, value); - this.fillLength = length; -} + Field.call(this, C.TYPE_COMPOSITE, value); + this.fillLength = length; +}; + util.inherits(FilledField, Field); FilledField.prototype.length = function() { - return this.fillLength; -} + return this.fillLength; +}; FilledField.prototype.write = function(stream) { - var len = this.value.length; - if (len < this.fillLength && len >= 0) { - if (len > 0) - stream.write(C.TYPE_ASCII, this.value); - var zeroLength = this.fillLength - len; - stream.write(C.TYPE_HEX, "20".repeat(zeroLength)); - } else if (len == this.fillLength) { - stream.write(C.TYPE_ASCII, this.value); - } else { - throw "Length mismatch"; - } -} + var len = this.value.length; + if (len < this.fillLength && len >= 0) { + if (len > 0) + stream.write(C.TYPE_ASCII, this.value); + var zeroLength = this.fillLength - len; + stream.write(C.TYPE_HEX, '20'.repeat(zeroLength)); + } else if (len == this.fillLength) { + stream.write(C.TYPE_ASCII, this.value); + } else { + throw 'Length mismatch'; + } +}; HexField = function(hex) { - Field.call(this, C.TYPE_HEX, hex); -} + Field.call(this, C.TYPE_HEX, hex); +}; + util.inherits(HexField, Field); ReservedField = function(length) { - length = length || 1; - Field.call(this, C.TYPE_HEX, "00".repeat(length)); -} + length = length || 1; + Field.call(this, C.TYPE_HEX, '00'.repeat(length)); +}; + util.inherits(ReservedField, Field); UInt8Field = function(value) { - Field.call(this, C.TYPE_UINT8, value); -} + Field.call(this, C.TYPE_UINT8, value); +}; + util.inherits(UInt8Field, Field); UInt8Field.prototype.isNumeric = function() { - return true; -} + return true; +}; UInt16Field = function(value) { - Field.call(this, C.TYPE_UINT16, value); -} + Field.call(this, C.TYPE_UINT16, value); +}; + util.inherits(UInt16Field, Field); UInt16Field.prototype.isNumeric = function() { - return true; -} + return true; +}; UInt32Field = function(value) { - Field.call(this, C.TYPE_UINT32, value); -} + Field.call(this, C.TYPE_UINT32, value); +}; + util.inherits(UInt32Field, Field); UInt32Field.prototype.isNumeric = function() { - return true; -} + return true; +}; Int8Field = function(value) { - Field.call(this, C.TYPE_INT8, value); -} + Field.call(this, C.TYPE_INT8, value); +}; + util.inherits(Int8Field, Field); Int8Field.prototype.isNumeric = function() { - return true; -} + return true; +}; Int16Field = function(value) { - Field.call(this, C.TYPE_INT16, value); -} + Field.call(this, C.TYPE_INT16, value); +}; + util.inherits(Int16Field, Field); Int16Field.prototype.isNumeric = function() { - return true; -} + return true; +}; Int32Field = function(value) { - Field.call(this, C.TYPE_INT32, value); -} + Field.call(this, C.TYPE_INT32, value); +}; + util.inherits(Int32Field, Field); Int32Field.prototype.isNumeric = function() { - return true; -} + return true; +}; FloatField = function(value) { - Field.call(this, C.TYPE_FLOAT, value); -} + Field.call(this, C.TYPE_FLOAT, value); +}; + util.inherits(FloatField, Field); FloatField.prototype.isNumeric = function() { - return true; -} + return true; +}; DoubleField = function(value) { - Field.call(this, C.TYPE_DOUBLE, value); -} + Field.call(this, C.TYPE_DOUBLE, value); +}; + util.inherits(DoubleField, Field); DoubleField.prototype.isNumeric = function() { - return true; -} \ No newline at end of file + return true; +}; diff --git a/Packages/dimseservice/server/Message.js b/Packages/dimseservice/server/Message.js index 6cf30e63f..472a95be1 100755 --- a/Packages/dimseservice/server/Message.js +++ b/Packages/dimseservice/server/Message.js @@ -1,556 +1,590 @@ DicomMessage = function(syntax) { - this.syntax = syntax ? syntax : null; - this.type = C.DATA_TYPE_COMMAND; - this.messageId = C.DEFAULT_MESSAGE_ID; - this.elementPairs = {}; + this.syntax = syntax ? syntax : null; + this.type = C.DATA_TYPE_COMMAND; + this.messageId = C.DEFAULT_MESSAGE_ID; + this.elementPairs = {}; }; DicomMessage.prototype.isCommand = function() { - return this.type == C.DATA_TYPE_COMMAND; -} + return this.type == C.DATA_TYPE_COMMAND; +}; DicomMessage.prototype.setSyntax = function(syntax) { - this.syntax = syntax; + this.syntax = syntax; - for (var tag in this.elementPairs) { - this.elementPairs[tag].setSyntax(this.syntax); - } -} + for (var tag in this.elementPairs) { + this.elementPairs[tag].setSyntax(this.syntax); + } +}; DicomMessage.prototype.setMessageId = function(id) { - this.messageId = id; -} + this.messageId = id; +}; DicomMessage.prototype.setReplyMessageId = function(id) { - this.replyMessageId = id; -} + this.replyMessageId = id; +}; DicomMessage.prototype.command = function(cmds) { - cmds.unshift(this.newElement(0x00000800, this.dataSetPresent ? C.DATA_SET_PRESENT : C.DATE_SET_ABSENCE)); - cmds.unshift(this.newElement(0x00000700, this.priority)); - cmds.unshift(this.newElement(0x00000110, this.messageId)); - cmds.unshift(this.newElement(0x00000100, this.commandType)); - cmds.unshift(this.newElement(0x00000002, this.contextUID)); - - var length = 0; - cmds.forEach(function(cmd) { - length += cmd.length(cmd.getFields()); - }); - - cmds.unshift(this.newElement(0x00000000, length)); - return cmds; -} - -DicomMessage.prototype.response = function(cmds) { - cmds.unshift(this.newElement(0x00000800, this.dataSetPresent ? C.DATA_SET_PRESENT : C.DATE_SET_ABSENCE)); - cmds.unshift(this.newElement(0x00000120, this.replyMessageId)); - cmds.unshift(this.newElement(0x00000100, this.commandType)); - if (this.contextUID) + cmds.unshift(this.newElement(0x00000800, this.dataSetPresent ? C.DATA_SET_PRESENT : C.DATE_SET_ABSENCE)); + cmds.unshift(this.newElement(0x00000700, this.priority)); + cmds.unshift(this.newElement(0x00000110, this.messageId)); + cmds.unshift(this.newElement(0x00000100, this.commandType)); cmds.unshift(this.newElement(0x00000002, this.contextUID)); - var length = 0; - cmds.forEach(function(cmd) { - length += cmd.length(cmd.getFields()); - }); + var length = 0; + cmds.forEach(function(cmd) { + length += cmd.length(cmd.getFields()); + }); - cmds.unshift(this.newElement(0x00000000, length)); - return cmds; -} + cmds.unshift(this.newElement(0x00000000, length)); + return cmds; +}; + +DicomMessage.prototype.response = function(cmds) { + cmds.unshift(this.newElement(0x00000800, this.dataSetPresent ? C.DATA_SET_PRESENT : C.DATE_SET_ABSENCE)); + cmds.unshift(this.newElement(0x00000120, this.replyMessageId)); + cmds.unshift(this.newElement(0x00000100, this.commandType)); + if (this.contextUID) + cmds.unshift(this.newElement(0x00000002, this.contextUID)); + + var length = 0; + cmds.forEach(function(cmd) { + length += cmd.length(cmd.getFields()); + }); + + cmds.unshift(this.newElement(0x00000000, length)); + return cmds; +}; DicomMessage.prototype.setElements = function(pairs) { - var p = {}; - for (var tag in pairs) { - p[tag] = this.newElement(tag, pairs[tag]); - } - this.elementPairs = p; -} + var p = {}; + for (var tag in pairs) { + p[tag] = this.newElement(tag, pairs[tag]); + } + + this.elementPairs = p; +}; DicomMessage.prototype.newElement = function(tag, value) { - return elementByType(tag, value, this.syntax); -} + return elementByType(tag, value, this.syntax); +}; DicomMessage.prototype.setElement = function(key, value) { - this.elementPairs[key] = elementByType(key, value); -} + this.elementPairs[key] = elementByType(key, value); +}; DicomMessage.prototype.setElementPairs = function(pairs) { - this.elementPairs = pairs; -} + this.elementPairs = pairs; +}; DicomMessage.prototype.setContextId = function(context) { - this.contextUID = context; -} + this.contextUID = context; +}; DicomMessage.prototype.setPriority = function(pri) { - this.priority = pri; -} + this.priority = pri; +}; DicomMessage.prototype.setType = function(type) { - this.type = type; -} + this.type = type; +}; DicomMessage.prototype.setDataSetPresent = function(present) { - this.dataSetPresent = present == 0x0101 ? false : true; -} + this.dataSetPresent = present == 0x0101 ? false : true; +}; DicomMessage.prototype.haveData = function() { - return this.dataSetPresent; -} + return this.dataSetPresent; +}; DicomMessage.prototype.tags = function() { - return Object.keys(this.elementPairs); -} + return Object.keys(this.elementPairs); +}; DicomMessage.prototype.key = function(tag) { - return elementKeywordByTag(tag); -} + return elementKeywordByTag(tag); +}; DicomMessage.prototype.getValue = function(tag) { - return this.elementPairs[tag] ? this.elementPairs[tag].getValue() : null; -} + return this.elementPairs[tag] ? this.elementPairs[tag].getValue() : null; +}; DicomMessage.prototype.affectedSOPClassUID = function() { - return this.getValue(0x00000002); -} + return this.getValue(0x00000002); +}; DicomMessage.prototype.getMessageId = function() { - return this.getValue(0x00000110); -} + return this.getValue(0x00000110); +}; DicomMessage.prototype.getFields = function() { - var eles = []; - for (var tag in this.elementPairs) { - eles.push(this.elementPairs[tag]); - } - return eles; -} + var eles = []; + for (var tag in this.elementPairs) { + eles.push(this.elementPairs[tag]); + } + + return eles; +}; DicomMessage.prototype.length = function(elems) { - var len = 0; - elems.forEach(function(elem){ - len += elem.length(elem.getFields()); - }); - return len; -} + var len = 0; + elems.forEach(function(elem) { + len += elem.length(elem.getFields()); + }); + return len; +}; DicomMessage.prototype.isResponse = function() { - return false; -} + return false; +}; DicomMessage.prototype.is = function(type) { - return this.commandType == type; -} + return this.commandType == type; +}; DicomMessage.prototype.write = function(stream) { - var fields = this.getFields(), o = this; - fields.forEach(function(field){ - field.setSyntax(o.syntax); - field.write(stream); - }); -} + var fields = this.getFields(), + o = this; + fields.forEach(function(field) { + field.setSyntax(o.syntax); + field.write(stream); + }); +}; DicomMessage.prototype.printElements = function(pairs, indent) { - var typeName = ""; - for (var tag in pairs) { - var value = pairs[tag].getValue(); - typeName += (" ".repeat(indent)) + this.key(tag) + " : "; - if (value instanceof Array) { - var o = this; - value.forEach(function(p) { - if (typeof p == "object") { - typeName += "[\n" + o.printElements(p, indent + 2) + (" ".repeat(indent)) + "]"; + var typeName = ''; + for (var tag in pairs) { + var value = pairs[tag].getValue(); + typeName += (' '.repeat(indent)) + this.key(tag) + ' : '; + if (value instanceof Array) { + var o = this; + value.forEach(function(p) { + if (typeof p == 'object') { + typeName += '[\n' + o.printElements(p, indent + 2) + (' '.repeat(indent)) + ']'; + } else { + typeName += '[' + p + ']'; + } + }); + if (typeName[typeName.length - 1] != '\n') { + typeName += '\n'; + } } else { - typeName += "[" + p + "]"; + typeName += value + '\n'; } - }); - if (typeName[typeName.length-1] != "\n") { - typeName += "\n"; - } - } else { - typeName += value + "\n"; } - } - return typeName; -} + + return typeName; +}; DicomMessage.prototype.typeString = function() { - var typeName = ""; - if (!this.isCommand()) { - typeName = "DateSet Message"; - } else { - switch (this.commandType) { - case C.COMMAND_C_GET_RSP : typeName = "C-GET-RSP"; break; - case C.COMMAND_C_MOVE_RSP : typeName = "C-MOVE-RSP"; break; - case C.COMMAND_C_GET_RQ : typeName = "C-GET-RQ"; break; - case C.COMMAND_C_STORE_RQ : typeName = "C-STORE-RQ"; break; - case C.COMMAND_C_FIND_RSP : typeName = "C-FIND-RSP"; break; - case C.COMMAND_C_MOVE_RQ : typeName = "C-MOVE-RQ"; break; - case C.COMMAND_C_FIND_RQ : typeName = "C-FIND-RQ"; break; - case C.COMMAND_C_STORE_RSP : typeName = "C-STORE-RSP"; break; + var typeName = ''; + if (!this.isCommand()) { + typeName = 'DateSet Message'; + } else { + switch (this.commandType) { + case C.COMMAND_C_GET_RSP : typeName = 'C-GET-RSP'; break; + case C.COMMAND_C_MOVE_RSP : typeName = 'C-MOVE-RSP'; break; + case C.COMMAND_C_GET_RQ : typeName = 'C-GET-RQ'; break; + case C.COMMAND_C_STORE_RQ : typeName = 'C-STORE-RQ'; break; + case C.COMMAND_C_FIND_RSP : typeName = 'C-FIND-RSP'; break; + case C.COMMAND_C_MOVE_RQ : typeName = 'C-MOVE-RQ'; break; + case C.COMMAND_C_FIND_RQ : typeName = 'C-FIND-RQ'; break; + case C.COMMAND_C_STORE_RSP : typeName = 'C-STORE-RSP'; break; } - } - return typeName; -} + } + + return typeName; +}; DicomMessage.prototype.toString = function() { - var typeName = this.typeString(); - typeName += " [\n"; - typeName += this.printElements(this.elementPairs, 0); - typeName += "]"; - return typeName; -} + var typeName = this.typeString(); + typeName += ' [\n'; + typeName += this.printElements(this.elementPairs, 0); + typeName += ']'; + return typeName; +}; DicomMessage.prototype.walkObject = function(pairs) { - var obj = {}, o = this; - for (var tag in pairs) { - var v = pairs[tag].getValue(), u = v; - if (v instanceof Array) { - u = []; - v.forEach(function(a) { - if (typeof a == 'object') { - u.push(o.walkObject(a)); - } else u.push(a); - }); - } - obj[tag] = u; - } + var obj = {}, + o = this; + for (var tag in pairs) { + var v = pairs[tag].getValue(), + u = v; + if (v instanceof Array) { + u = []; + v.forEach(function(a) { + if (typeof a == 'object') { + u.push(o.walkObject(a)); + } else u.push(a); + }); + } - return obj; -} + obj[tag] = u; + } + + return obj; +}; DicomMessage.prototype.toObject = function() { - return this.walkObject(this.elementPairs); -} + return this.walkObject(this.elementPairs); +}; DicomMessage.readToPairs = function(stream, syntax, options) { - var pairs = {}; - while (!stream.end()) { - var elem = new DataElement(); - if (options) { - elem.setOptions(options); + var pairs = {}; + while (!stream.end()) { + var elem = new DataElement(); + if (options) { + elem.setOptions(options); + } + + elem.setSyntax(syntax); + elem.readBytes(stream); + pairs[elem.tag.value] = elem; } - elem.setSyntax(syntax); - elem.readBytes(stream); - pairs[elem.tag.value] = elem; - } - return pairs; -} + + return pairs; +}; var fileValid = function(stream) { - return stream.readString(4, C.TYPE_ASCII) == 'DICM'; -} + return stream.readString(4, C.TYPE_ASCII) == 'DICM'; +}; var readMetaStream = function(stream, useSyntax, length, callback) { - var message = new FileMetaMessage(); - message.setElementPairs(DicomMessage.readToPairs(stream, useSyntax)); - if (callback) { - callback(null, message, length); - } - return message; -} + var message = new FileMetaMessage(); + message.setElementPairs(DicomMessage.readToPairs(stream, useSyntax)); + if (callback) { + callback(null, message, length); + } + + return message; +}; DicomMessage.readMetaHeader = function(bufferOrFile, callback) { - var useSyntax = C.EXPLICIT_LITTLE_ENDIAN; - if (bufferOrFile instanceof Buffer) { - var stream = new ReadStream(bufferOrFile); - stream.reset(); - stream.increment(128); - if (!fileValid(stream)) { - return quitWithError('Invalid a dicom file ', callback); - } - var el = readAElement(stream, useSyntax), - metaLength = el.value, - metaStream = stream.more(metaLength); - - return readMetaStream(metaStream, useSyntax, metaLength, callback); - } else if (typeof bufferOrFile == 'string') { - fs.open(bufferOrFile, 'r', function(err, fd) { - if (err) { - //fs.closeSync(fd); - return quitWithError('Cannot open file', callback); - } - var buffer = new Buffer(16); - fs.read(fd, buffer, 0, 16, 128, function(err, bytesRead) { - if (err || bytesRead != 16) { - fs.closeSync(fd); - return quitWithError('Cannot read file', callback); - } - var stream = new ReadStream(buffer); + var useSyntax = C.EXPLICIT_LITTLE_ENDIAN; + if (bufferOrFile instanceof Buffer) { + var stream = new ReadStream(bufferOrFile); + stream.reset(); + stream.increment(128); if (!fileValid(stream)) { - fs.closeSync(fd); - return quitWithError('Not a dicom file ' + bufferOrFile, callback); - } - var el = readAElement(stream, useSyntax), + return quitWithError('Invalid a dicom file ', callback); + } + + var el = readAElement(stream, useSyntax), metaLength = el.value, - metaBuffer = new Buffer(metaLength); + metaStream = stream.more(metaLength); - fs.read(fd, metaBuffer, 0, metaLength, 144, function(err, bytesRead) { - fs.closeSync(fd); - if (err || bytesRead != metaLength) { - return quitWithError('Invalid a dicom file ' + bufferOrFile, callback); - } - var metaStream = new ReadStream(metaBuffer); - return readMetaStream(metaStream, useSyntax, metaLength, callback); + return readMetaStream(metaStream, useSyntax, metaLength, callback); + } else if (typeof bufferOrFile == 'string') { + fs.open(bufferOrFile, 'r', function(err, fd) { + if (err) { + //fs.closeSync(fd); + return quitWithError('Cannot open file', callback); + } + + var buffer = new Buffer(16); + fs.read(fd, buffer, 0, 16, 128, function(err, bytesRead) { + if (err || bytesRead != 16) { + fs.closeSync(fd); + return quitWithError('Cannot read file', callback); + } + + var stream = new ReadStream(buffer); + if (!fileValid(stream)) { + fs.closeSync(fd); + return quitWithError('Not a dicom file ' + bufferOrFile, callback); + } + + var el = readAElement(stream, useSyntax), + metaLength = el.value, + metaBuffer = new Buffer(metaLength); + + fs.read(fd, metaBuffer, 0, metaLength, 144, function(err, bytesRead) { + fs.closeSync(fd); + if (err || bytesRead != metaLength) { + return quitWithError('Invalid a dicom file ' + bufferOrFile, callback); + } + + var metaStream = new ReadStream(metaBuffer); + return readMetaStream(metaStream, useSyntax, metaLength, callback); + }); + }); }); - }); - }); - } + } - return null; -} + return null; +}; DicomMessage.read = function(stream, type, syntax, options) { - var elements = [], pairs = {}, useSyntax = type == C.DATA_TYPE_COMMAND ? C.IMPLICIT_LITTLE_ENDIAN : syntax; - stream.reset(); - while (!stream.end()) { - var elem = new DataElement(); - if (options) { - elem.setOptions(options); - } - elem.setSyntax(useSyntax); - elem.readBytes(stream);//return; - pairs[elem.tag.value] = elem; - } + var elements = [], + pairs = {}, + useSyntax = type == C.DATA_TYPE_COMMAND ? C.IMPLICIT_LITTLE_ENDIAN : syntax; + stream.reset(); + while (!stream.end()) { + var elem = new DataElement(); + if (options) { + elem.setOptions(options); + } - var message = null; - if (type == C.DATA_TYPE_COMMAND) { - var cmdType = pairs[0x00000100].value; - - switch (cmdType) { - case 0x8020 : message = new CFindRSP(useSyntax); break; - case 0x8021 : message = new CMoveRSP(useSyntax); break; - case 0x8010 : message = new CGetRSP(useSyntax); break; - case 0x0001 : message = new CStoreRQ(useSyntax); break; - case 0x0020 : message = new CFindRQ(useSyntax); break; - case 0x8001 : message = new CStoreRSP(useSyntax); break; - default : throw "Unrecognized command type " + cmdType.toString(16); break; + elem.setSyntax(useSyntax); + elem.readBytes(stream);//return; + pairs[elem.tag.value] = elem; } - message.setElementPairs(pairs); - message.setDataSetPresent(message.getValue(0x00000800)); - message.setContextId(message.getValue(0x00000002)); - if (!message.isResponse()) { - message.setMessageId(message.getValue(0x00000110)); + var message = null; + if (type == C.DATA_TYPE_COMMAND) { + var cmdType = pairs[0x00000100].value; + + switch (cmdType) { + case 0x8020 : message = new CFindRSP(useSyntax); break; + case 0x8021 : message = new CMoveRSP(useSyntax); break; + case 0x8010 : message = new CGetRSP(useSyntax); break; + case 0x0001 : message = new CStoreRQ(useSyntax); break; + case 0x0020 : message = new CFindRQ(useSyntax); break; + case 0x8001 : message = new CStoreRSP(useSyntax); break; + default : throw 'Unrecognized command type ' + cmdType.toString(16); break; + } + + message.setElementPairs(pairs); + message.setDataSetPresent(message.getValue(0x00000800)); + message.setContextId(message.getValue(0x00000002)); + if (!message.isResponse()) { + message.setMessageId(message.getValue(0x00000110)); + } else { + message.setReplyMessageId(message.getValue(0x00000120)); + } + } else if (type == C.DATA_TYPE_DATA) { + message = new DataSetMessage(useSyntax); + message.setElementPairs(pairs); } else { - message.setReplyMessageId(message.getValue(0x00000120)); + throw 'Unrecognized message type'; } - } else if (type == C.DATA_TYPE_DATA) { - message = new DataSetMessage(useSyntax); - message.setElementPairs(pairs); - } else { - throw "Unrecognized message type"; - } - return message; -} -DataSetMessage = function(syntax){ - DicomMessage.call(this, syntax); - this.type = C.DATA_TYPE_DATA; + return message; }; + +DataSetMessage = function(syntax) { + DicomMessage.call(this, syntax); + this.type = C.DATA_TYPE_DATA; +}; + util.inherits(DataSetMessage, DicomMessage); DataSetMessage.prototype.is = function(type) { - return false; -} - -FileMetaMessage = function(syntax){ - DicomMessage.call(this, syntax); - this.type = null + return false; }; + +FileMetaMessage = function(syntax) { + DicomMessage.call(this, syntax); + this.type = null; +}; + util.inherits(FileMetaMessage, DicomMessage); CommandMessage = function(syntax) { - DicomMessage.call(this, syntax); - this.type = C.DATA_TYPE_COMMAND; - this.priority = C.PRIORITY_MEDIUM; - this.dataSetPresent = true; -} + DicomMessage.call(this, syntax); + this.type = C.DATA_TYPE_COMMAND; + this.priority = C.PRIORITY_MEDIUM; + this.dataSetPresent = true; +}; + util.inherits(CommandMessage, DicomMessage); CommandMessage.prototype.getFields = function() { - return this.command(CommandMessage.super_.prototype.getFields.call(this)); -} + return this.command(CommandMessage.super_.prototype.getFields.call(this)); +}; CommandResponse = function(syntax) { - DicomMessage.call(this, syntax); - this.type = C.DATA_TYPE_COMMAND; - this.dataSetPresent = true; + DicomMessage.call(this, syntax); + this.type = C.DATA_TYPE_COMMAND; + this.dataSetPresent = true; }; + util.inherits(CommandResponse, DicomMessage); CommandResponse.prototype.isResponse = function() { - return true; -} + return true; +}; CommandResponse.prototype.respondedTo = function() { - return this.getValue(0x00000120); -} + return this.getValue(0x00000120); +}; CommandResponse.prototype.isFinal = function() { - return this.success() || this.failure() || this.cancel(); -} + return this.success() || this.failure() || this.cancel(); +}; CommandResponse.prototype.warning = function() { - var status = this.getStatus(); - return (status == 0x0001) || (status >> 12 == 0xb); -} + var status = this.getStatus(); + return (status == 0x0001) || (status >> 12 == 0xb); +}; CommandResponse.prototype.success = function() { - return this.getStatus() == 0x0000; -} + return this.getStatus() == 0x0000; +}; CommandResponse.prototype.failure = function() { - var status = this.getStatus(); - return (status >> 12 == 0xa) || (status >> 12 == 0xc) || (status >> 8 == 0x1) -} + var status = this.getStatus(); + return (status >> 12 == 0xa) || (status >> 12 == 0xc) || (status >> 8 == 0x1); +}; CommandResponse.prototype.cancel = function() { - return this.getStatus() == C.STATUS_CANCEL; -} + return this.getStatus() == C.STATUS_CANCEL; +}; CommandResponse.prototype.pending = function() { - var status = this.getStatus(); - return (status == 0xff00) || (status == 0xff01); -} + var status = this.getStatus(); + return (status == 0xff00) || (status == 0xff01); +}; CommandResponse.prototype.getStatus = function() { - return this.getValue(0x00000900); -} + return this.getValue(0x00000900); +}; CommandResponse.prototype.setStatus = function(status) { - this.setElement(0x00000900, status); -} + this.setElement(0x00000900, status); +}; // following four methods only available to C-GET-RSP and C-MOVE-RSP CommandResponse.prototype.getNumOfRemainingSubOperations = function() { - return this.getValue(0x00001020); -} + return this.getValue(0x00001020); +}; CommandResponse.prototype.getNumOfCompletedSubOperations = function() { - return this.getValue(0x00001021); -} + return this.getValue(0x00001021); +}; CommandResponse.prototype.getNumOfFailedSubOperations = function() { - return this.getValue(0x00001022); -} + return this.getValue(0x00001022); +}; CommandResponse.prototype.getNumOfWarningSubOperations = function() { - return this.getValue(0x00001023); -} + return this.getValue(0x00001023); +}; //end CommandResponse.prototype.getFields = function() { - return this.response(CommandResponse.super_.prototype.getFields.call(this)); -} + return this.response(CommandResponse.super_.prototype.getFields.call(this)); +}; CFindRSP = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x8020; + CommandResponse.call(this, syntax); + this.commandType = 0x8020; }; + util.inherits(CFindRSP, CommandResponse); CGetRSP = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x8010; + CommandResponse.call(this, syntax); + this.commandType = 0x8010; }; + util.inherits(CGetRSP, CommandResponse); CMoveRSP = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x8021; + CommandResponse.call(this, syntax); + this.commandType = 0x8021; }; + util.inherits(CMoveRSP, CommandResponse); CFindRQ = function(syntax) { - CommandMessage.call(this, syntax); - this.commandType = 0x20; - this.contextUID = C.SOP_STUDY_ROOT_FIND; + CommandMessage.call(this, syntax); + this.commandType = 0x20; + this.contextUID = C.SOP_STUDY_ROOT_FIND; }; + util.inherits(CFindRQ, CommandMessage); CCancelRQ = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x0fff; - this.contextUID = null; - this.dataSetPresent = false; + CommandResponse.call(this, syntax); + this.commandType = 0x0fff; + this.contextUID = null; + this.dataSetPresent = false; }; + util.inherits(CCancelRQ, CommandResponse); CCancelMoveRQ = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x0fff; - this.contextUID = null; - this.dataSetPresent = false; + CommandResponse.call(this, syntax); + this.commandType = 0x0fff; + this.contextUID = null; + this.dataSetPresent = false; }; + util.inherits(CCancelMoveRQ, CommandResponse); CMoveRQ = function(syntax, destination) { - CommandMessage.call(this, syntax); - this.commandType = 0x21; - this.contextUID = C.SOP_STUDY_ROOT_MOVE; - this.setDestination(destination || ""); + CommandMessage.call(this, syntax); + this.commandType = 0x21; + this.contextUID = C.SOP_STUDY_ROOT_MOVE; + this.setDestination(destination || ''); }; + util.inherits(CMoveRQ, CommandMessage); CMoveRQ.prototype.setStore = function(cstr) { - this.store = cstr; -} + this.store = cstr; +}; CMoveRQ.prototype.setDestination = function(dest) { - this.setElement(0x00000600, dest); -} + this.setElement(0x00000600, dest); +}; CGetRQ = function(syntax) { - CommandMessage.call(this, syntax); - this.commandType = 0x10; - this.contextUID = C.SOP_STUDY_ROOT_GET; - this.store = null; + CommandMessage.call(this, syntax); + this.commandType = 0x10; + this.contextUID = C.SOP_STUDY_ROOT_GET; + this.store = null; }; + util.inherits(CGetRQ, CommandMessage); CGetRQ.prototype.setStore = function(cstr) { - this.store = cstr; -} + this.store = cstr; +}; CStoreRQ = function(syntax) { - CommandMessage.call(this, syntax); - this.commandType = 0x01; - this.contextUID = C.SOP_STUDY_ROOT_GET; + CommandMessage.call(this, syntax); + this.commandType = 0x01; + this.contextUID = C.SOP_STUDY_ROOT_GET; }; + util.inherits(CStoreRQ, CommandMessage); CStoreRQ.prototype.getOriginAETitle = function() { - return this.getValue(0x00001030); -} + return this.getValue(0x00001030); +}; CStoreRQ.prototype.getMoveMessageId = function() { - return this.getValue(0x00001031); -} + return this.getValue(0x00001031); +}; CStoreRQ.prototype.getAffectedSOPInstanceUID = function() { - return this.getValue(0x00001000); -} + return this.getValue(0x00001000); +}; CStoreRQ.prototype.setAffectedSOPInstanceUID = function(uid) { - this.setElement(0x00001000, uid); -} + this.setElement(0x00001000, uid); +}; CStoreRQ.prototype.setAffectedSOPClassUID = function(uid) { - this.setElement(0x00000002, uid); -} + this.setElement(0x00000002, uid); +}; CStoreRSP = function(syntax) { - CommandResponse.call(this, syntax); - this.commandType = 0x8001; - this.contextUID = C.SOP_STUDY_ROOT_GET; - this.dataSetPresent = false; + CommandResponse.call(this, syntax); + this.commandType = 0x8001; + this.contextUID = C.SOP_STUDY_ROOT_GET; + this.dataSetPresent = false; }; + util.inherits(CStoreRSP, CommandResponse); CStoreRSP.prototype.setAffectedSOPInstanceUID = function(uid) { - this.setElement(0x00001000, uid); -} + this.setElement(0x00001000, uid); +}; CStoreRSP.prototype.getAffectedSOPInstanceUID = function(uid) { - return this.getValue(0x00001000); -} \ No newline at end of file + return this.getValue(0x00001000); +}; diff --git a/Packages/dimseservice/server/RWStream.js b/Packages/dimseservice/server/RWStream.js index cfa6de04c..498372b82 100755 --- a/Packages/dimseservice/server/RWStream.js +++ b/Packages/dimseservice/server/RWStream.js @@ -1,236 +1,239 @@ var isString = function(type) { - if (type == C.TYPE_ASCII || type == C.TYPE_HEX) { - return true; - } else return false; + if (type === C.TYPE_ASCII || type === C.TYPE_HEX) { + return true; + } else { + return false; + } }; calcLength = function(type, value) { - var size = NaN; - switch (type) { - case C.TYPE_HEX : size = Buffer.byteLength(value, 'hex'); break; - case C.TYPE_ASCII : size = Buffer.byteLength(value, 'ascii'); break; - case C.TYPE_UINT8 : size = 1; break; + var size = NaN; + switch (type) { + case C.TYPE_HEX : size = Buffer.byteLength(value, 'hex'); break; + case C.TYPE_ASCII : size = Buffer.byteLength(value, 'ascii'); break; + case C.TYPE_UINT8 : size = 1; break; case C.TYPE_UINT16 : size = 2; break; case C.TYPE_UINT32 : size = 4; break; - case C.TYPE_FLOAT : size = 4; break; + case C.TYPE_FLOAT : size = 4; break; case C.TYPE_DOUBLE : size = 8; break; - case C.TYPE_INT8 : size = 1; break; - case C.TYPE_INT16 : size = 2; break; - case C.TYPE_INT32 : size = 4; break; + case C.TYPE_INT8 : size = 1; break; + case C.TYPE_INT16 : size = 2; break; + case C.TYPE_INT32 : size = 4; break; default :break; - } - return size; } + return size; +}; var RWStream = function() { - this.endian = C.BIG_ENDIAN; + this.endian = C.BIG_ENDIAN; }; RWStream.prototype.setEndian = function(endian) { - this.endian = endian; -} + this.endian = endian; +}; RWStream.prototype.getEncoding = function(type) { - return RWStream.encodings[type]; -} + return RWStream.encodings[type]; +}; RWStream.prototype.getWriteType = function(type) { - return RWStream.writes[this.endian][type]; -} + return RWStream.writes[this.endian][type]; +}; RWStream.prototype.getReadType = function(type) { - return RWStream.reads[this.endian][type]; -} + return RWStream.reads[this.endian][type]; +}; WriteStream = function() { - RWStream.call(this); - this.defaultBufferSize = 512; //512 bytes - this.rawBuffer = new Buffer(this.defaultBufferSize); - this.offset = 0; - this.contentSize = 0; -} + RWStream.call(this); + this.defaultBufferSize = 512; //512 bytes + this.rawBuffer = new Buffer(this.defaultBufferSize); + this.offset = 0; + this.contentSize = 0; +}; util.inherits(WriteStream, RWStream); WriteStream.prototype.increment = function(add) { - this.offset += add; - if (this.offset > this.contentSize) { - this.contentSize = this.offset; - } -} + this.offset += add; + if (this.offset > this.contentSize) { + this.contentSize = this.offset; + } +}; WriteStream.prototype.size = function() { - return this.contentSize; -} + return this.contentSize; +}; WriteStream.prototype.skip = function(amount) { - this.increment(amount); -} + this.increment(amount); +}; WriteStream.prototype.checkSize = function(length) { - if (this.offset + length > this.rawBuffer.length) { - // we need more size, copying old one to new buffer - var oldLength = this.rawBuffer.length, - newBuffer = new Buffer(oldLength + length + (oldLength / 2)); - this.rawBuffer.copy(newBuffer, 0, 0, this.contentSize); - this.rawBuffer = newBuffer; - } -} + if (this.offset + length > this.rawBuffer.length) { + // we need more size, copying old one to new buffer + var oldLength = this.rawBuffer.length, + newBuffer = new Buffer(oldLength + length + (oldLength / 2)); + this.rawBuffer.copy(newBuffer, 0, 0, this.contentSize); + this.rawBuffer = newBuffer; + } +}; WriteStream.prototype.writeToBuffer = function(type, value, length) { - if (value === "" || value === null) return; + if (value === '' || value === null) return; - this.checkSize(length); - this.rawBuffer[this.getWriteType(type)](value, this.offset); - this.increment(length); -} + this.checkSize(length); + this.rawBuffer[this.getWriteType(type)](value, this.offset); + this.increment(length); +}; WriteStream.prototype.writeRawBuffer = function(source, start, length) { - if (!source) return; - this.checkSize(length); - source.copy(this.rawBuffer, this.offset, start, length); - this.increment(length); -} + if (!source) return; + this.checkSize(length); + source.copy(this.rawBuffer, this.offset, start, length); + this.increment(length); +}; WriteStream.prototype.write = function(type, value) { - if (isString(type)) { - this.writeString(value, type); - } else { - this.writeToBuffer(type, value, calcLength(type)); - } -} + if (isString(type)) { + this.writeString(value, type); + } else { + this.writeToBuffer(type, value, calcLength(type)); + } +}; WriteStream.prototype.writeString = function(string, type) { - var encoding = this.getEncoding(type), length = Buffer.byteLength(string, encoding); - this.rawBuffer.write(string, this.offset, length, encoding); - this.increment(length); -} + var encoding = this.getEncoding(type), + length = Buffer.byteLength(string, encoding); + this.rawBuffer.write(string, this.offset, length, encoding); + this.increment(length); +}; WriteStream.prototype.buffer = function() { - return this.rawBuffer.slice(0, this.contentSize); -} + return this.rawBuffer.slice(0, this.contentSize); +}; WriteStream.prototype.toReadBuffer = function() { - return new ReadStream(this.buffer()); -} + return new ReadStream(this.buffer()); +}; WriteStream.prototype.concat = function(newStream) { - var newSize = this.size() + newStream.size(); - this.rawBuffer = Buffer.concat([this.buffer(), newStream.buffer()], newSize); - this.contentSize = newSize; - this.offset = newSize; -} + var newSize = this.size() + newStream.size(); + this.rawBuffer = Buffer.concat([this.buffer(), newStream.buffer()], newSize); + this.contentSize = newSize; + this.offset = newSize; +}; ReadStream = function(buffer) { - RWStream.call(this); - this.rawBuffer = buffer; - this.offset = 0; + RWStream.call(this); + this.rawBuffer = buffer; + this.offset = 0; }; util.inherits(ReadStream, RWStream); ReadStream.prototype.size = function() { - return this.rawBuffer.length; -} + return this.rawBuffer.length; +}; ReadStream.prototype.increment = function(add) { - this.offset += add; -} + this.offset += add; +}; ReadStream.prototype.more = function(length) { - var newBuf = this.rawBuffer.slice(this.offset, this.offset + length); - this.increment(length); - return new ReadStream(newBuf); -} + var newBuf = this.rawBuffer.slice(this.offset, this.offset + length); + this.increment(length); + return new ReadStream(newBuf); +}; ReadStream.prototype.reset = function() { - this.offset = 0; - return this; -} + this.offset = 0; + return this; +}; ReadStream.prototype.end = function() { - return this.offset >= this.size(); -} + return this.offset >= this.size(); +}; ReadStream.prototype.readFromBuffer = function(type, length) { - //this.checkSize(length); - //if (this.offset + length > this.rawBuffer.length) throw ("out of bound " + this.offset + "," + length + "," + this.rawBuffer.length); - var value = this.rawBuffer[this.getReadType(type)](this.offset); - this.increment(length); - return value; -} + //this.checkSize(length); + //if (this.offset + length > this.rawBuffer.length) throw ("out of bound " + this.offset + "," + length + "," + this.rawBuffer.length); + var value = this.rawBuffer[this.getReadType(type)](this.offset); + this.increment(length); + return value; +}; ReadStream.prototype.read = function(type, length) { - var value = null; - if (isString(type)) { - value = this.readString(length, type); - } else { - value = this.readFromBuffer(type, calcLength(type)); - } + var value = null; + if (isString(type)) { + value = this.readString(length, type); + } else { + value = this.readFromBuffer(type, calcLength(type)); + } - return value; -} + return value; +}; ReadStream.prototype.readString = function(length, type) { - var encoding = this.getEncoding(type), - str = this.rawBuffer.toString(encoding, this.offset, this.offset + length); - this.increment(length); - return str; -} + var encoding = this.getEncoding(type), + str = this.rawBuffer.toString(encoding, this.offset, this.offset + length); + this.increment(length); + return str; +}; ReadStream.prototype.buffer = function() { - return this.rawBuffer; -} + return this.rawBuffer; +}; ReadStream.prototype.concat = function(newStream) { - var newSize = this.size() + newStream.size(); - this.rawBuffer = Buffer.concat([this.buffer(), newStream.buffer()], newSize); - this.contentSize = newSize; - this.offset = newSize; -} + var newSize = this.size() + newStream.size(); + this.rawBuffer = Buffer.concat([this.buffer(), newStream.buffer()], newSize); + this.contentSize = newSize; + this.offset = newSize; +}; RWStream.writes = {}; RWStream.writes[C.BIG_ENDIAN] = {}; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT8] = "writeUInt8"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT16] = "writeUInt16BE"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT32] = "writeUInt32BE"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT8] = "writeInt8"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT16] = "writeInt16BE"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT32] = "writeInt32BE"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_FLOAT] = "writeFloatBE"; -RWStream.writes[C.BIG_ENDIAN][C.TYPE_DOUBLE] = "writeDoubleBE"; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT8] = 'writeUInt8'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT16] = 'writeUInt16BE'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_UINT32] = 'writeUInt32BE'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT8] = 'writeInt8'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT16] = 'writeInt16BE'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_INT32] = 'writeInt32BE'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_FLOAT] = 'writeFloatBE'; +RWStream.writes[C.BIG_ENDIAN][C.TYPE_DOUBLE] = 'writeDoubleBE'; RWStream.writes[C.LITTLE_ENDIAN] = {}; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT8] = "writeUInt8"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT16] = "writeUInt16LE"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT32] = "writeUInt32LE"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT8] = "writeInt8"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT16] = "writeInt16LE"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT32] = "writeInt32LE"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_FLOAT] = "writeFloatLE"; -RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_DOUBLE] = "writeDoubleLE"; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT8] = 'writeUInt8'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT16] = 'writeUInt16LE'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_UINT32] = 'writeUInt32LE'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT8] = 'writeInt8'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT16] = 'writeInt16LE'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_INT32] = 'writeInt32LE'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_FLOAT] = 'writeFloatLE'; +RWStream.writes[C.LITTLE_ENDIAN][C.TYPE_DOUBLE] = 'writeDoubleLE'; RWStream.reads = {}; RWStream.reads[C.BIG_ENDIAN] = {}; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT8] = "readUInt8"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT16] = "readUInt16BE"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT32] = "readUInt32BE"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT8] = "readInt8"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT16] = "readInt16BE"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT32] = "readInt32BE"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_FLOAT] = "readFloatBE"; -RWStream.reads[C.BIG_ENDIAN][C.TYPE_DOUBLE] = "readDoubleBE"; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT8] = 'readUInt8'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT16] = 'readUInt16BE'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_UINT32] = 'readUInt32BE'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT8] = 'readInt8'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT16] = 'readInt16BE'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_INT32] = 'readInt32BE'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_FLOAT] = 'readFloatBE'; +RWStream.reads[C.BIG_ENDIAN][C.TYPE_DOUBLE] = 'readDoubleBE'; RWStream.reads[C.LITTLE_ENDIAN] = {}; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT8] = "readUInt8"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT16] = "readUInt16LE"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT32] = "readUInt32LE"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT8] = "readInt8"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT16] = "readInt16LE"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT32] = "readInt32LE"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_FLOAT] = "readFloatLE"; -RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_DOUBLE] = "readDoubleLE"; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT8] = 'readUInt8'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT16] = 'readUInt16LE'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_UINT32] = 'readUInt32LE'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT8] = 'readInt8'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT16] = 'readInt16LE'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_INT32] = 'readInt32LE'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_FLOAT] = 'readFloatLE'; +RWStream.reads[C.LITTLE_ENDIAN][C.TYPE_DOUBLE] = 'readDoubleLE'; RWStream.encodings = {}; -RWStream.encodings[C.TYPE_HEX] = "hex"; -RWStream.encodings[C.TYPE_ASCII] = "ascii"; \ No newline at end of file +RWStream.encodings[C.TYPE_HEX] = 'hex'; +RWStream.encodings[C.TYPE_ASCII] = 'ascii'; diff --git a/Packages/dimseservice/server/methods.js b/Packages/dimseservice/server/methods.js deleted file mode 100755 index 442923f84..000000000 --- a/Packages/dimseservice/server/methods.js +++ /dev/null @@ -1,3 +0,0 @@ -Meteor.methods({ - -}); \ No newline at end of file diff --git a/Packages/worklist/both/schema.js b/Packages/worklist/both/schema.js new file mode 100644 index 000000000..0f7ed6f37 --- /dev/null +++ b/Packages/worklist/both/schema.js @@ -0,0 +1,160 @@ +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +export const DICOMWebRequestOptions = new SimpleSchema({ + auth: { + type: String, + label: 'Username:Password Authentication String', + }, + logRequests: { + type: Boolean, + defaultValue: true, + label: 'Log Requests?', + }, + logResponses: { + type: Boolean, + defaultValue: false, + label: 'Log Responses?', + }, + logTiming: { + type: Boolean, + defaultValue: true, + label: 'Log Timing?', + }, +}); + +export const DICOMWebServer = new SimpleSchema({ + name: { + type: String, + label: 'Name', + max: 100 + }, + wadoUriRoot: { + type: String, + label: 'WADO URI Root', + max: 1000 + }, + qidoRoot: { + type: String, + label: 'QIDO Root', + max: 1000 + }, + // TODO: Remove this + wadoUriRootNOTE: { + type: String, + label: 'WADO URI Root Note', + optional: true + }, + wadoRoot: { + type: String, + label: 'WADO Root', + max: 1000 + }, + qidoSupportsIncludeField: { + type: Boolean, + label: 'QIDO Supports Include Field?', + defaultValue: false + }, + imageRendering: { + type: String, + label: 'Image Rendering', + defaultValue: 'wadouri' + }, + requestOptions: { + type: DICOMWebRequestOptions, + label: 'Request Options' + } +}); + +export const DIMSEPeer = new SimpleSchema({ + host: { + type: String, + label: 'Host URL', + }, + port: { + type: Number, + label: 'Port', + min: 1, + defaultValue: 11112, + max: 65535 + }, + aeTitle: { + type: String, + label: 'Application Entity (AE) Title', + }, + default: { + type: Boolean, + label: 'Default?', + defaultValue: false + }, + server: { + type: Boolean, + label: 'Server?', + defaultValue: false + }, + supportsInstanceRetrievalByStudyUid: { + type: Boolean, + label: 'Supports instance retrieval by StudyUid?', + defaultValue: true + } +}); + +export const DIMSEServer = new SimpleSchema({ + name: { + type: String, + label: 'Name', + max: 100 + }, + peers: { + type: [ DIMSEPeer ], + label: 'DIMSE Peers', + } +}); + +export const UISettings = new SimpleSchema({ + studyListFunctionsEnabled: { + type: Boolean, + label: 'Study List Functions Enabled?', + defaultValue: true + } +}); + +export const PublicServerConfig = new SimpleSchema({ + verifyEmail: { + type: Boolean, + label: 'Verify Email', + defaultValue: false + }, + ui: { + type: UISettings, + label: 'UI Settings' + } +}); + +export const Servers = new SimpleSchema({ + dicomWeb: { + type: [ DICOMWebServer ], + label: 'DICOMWeb Servers', + optional: true + }, + dimse: { + type: [ DIMSEServer ], + label: 'DIMSE Servers', + optional: true + } +}); + +export const ServerConfiguration = new SimpleSchema({ + servers: { + type: Servers, + label: 'Servers' + }, + defaultServiceType: { + type: String, + label: 'Default Service Type', + defaultValue: 'dicomWeb' + }, + public: { + type: PublicServerConfig, + label: 'Public Server Configuration', + } +}); diff --git a/Packages/worklist/package.js b/Packages/worklist/package.js index bfd48e455..8da6024ea 100644 --- a/Packages/worklist/package.js +++ b/Packages/worklist/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function (api) { - api.versionsFrom('1.3.5.1'); + api.versionsFrom('1.4'); api.use('ecmascript'); api.use('standard-app-packages'); @@ -15,6 +15,7 @@ Package.onUse(function (api) { api.use('practicalmeteor:loglevel'); api.use('rwatts:uuid'); api.use('silentcicero:jszip'); + api.use('aldeed:simple-schema'); // Note: MomentJS appears to be required for Bootstrap3 Datepicker, but not a dependency for some reason api.use('momentjs:moment'); @@ -37,6 +38,9 @@ Package.onUse(function (api) { // console for debugging purposes api.addFiles('log.js'); + api.addFiles('both/collections.js', [ 'client', 'server' ]); + api.addFiles('both/schema.js', [ 'client', 'server' ]); + // Components api.addFiles('client/components/worklist.html', 'client'); api.addFiles('client/components/worklist.js', 'client'); @@ -78,6 +82,7 @@ Package.onUse(function (api) { // Server-side functions api.addFiles('server/collections.js', 'server'); + api.addFiles('server/validateServerConfiguration.js', 'server'); api.addFiles('server/lib/namespace.js', 'server'); api.addFiles('server/lib/encodeQueryData.js', 'server'); api.addFiles('server/methods/getStudyMetadata.js', 'server'); @@ -99,16 +104,12 @@ Package.onUse(function (api) { api.addFiles('server/services/remote/studies.js', 'server'); api.addFiles('server/services/remote/retrieveMetadata.js', 'server'); - api.addFiles('both/collections.js', [ 'client', 'server' ]); - api.export('Services', 'server'); // Export Worklist helper functions for usage in Routes - api.export('getTimepointName', 'client'); api.export('getStudyMetadata', 'client'); api.export('getStudiesMetadata', 'client'); api.export('openNewTab', 'client'); - api.export('setWorklistSubscriptions', 'client'); api.export('switchToTab', 'client'); api.export('progressDialog', 'client'); api.export('Worklist'); diff --git a/Packages/worklist/server/validateServerConfiguration.js b/Packages/worklist/server/validateServerConfiguration.js new file mode 100644 index 000000000..38006a52b --- /dev/null +++ b/Packages/worklist/server/validateServerConfiguration.js @@ -0,0 +1,12 @@ +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; +import { ServerConfiguration } from '../both/schema.js'; + +Meteor.startup(() => { + console.log('------ Testing Meteor Settings ------'); + let config = ServerConfiguration.clean(Meteor.settings); + console.log(JSON.stringify(config, null, 2)); + + Meteor.settings = config; + check(config, ServerConfiguration); +});