From 854049e6f0f6445a6ba408e4afaf0609fe7cec1d Mon Sep 17 00:00:00 2001 From: Vignesh Prabhu Date: Mon, 2 Mar 2015 01:59:07 +0530 Subject: [PATCH 1/2] Added useOnlyUTC pref support in header_emitter.js. --- headeremitter.js | 66 ++++++++++++++++++------- test/test_header_emitter.js | 99 +++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 17 deletions(-) diff --git a/headeremitter.js b/headeremitter.js index 6497cca..078fe02 100644 --- a/headeremitter.js +++ b/headeremitter.js @@ -76,6 +76,10 @@ function clamp(value, min, max, def) { function HeaderEmitter(handler, options) { /// The inferred value of options.useASCII this._useASCII = options.useASCII === undefined ? true : options.useASCII; + + /// The inferred value of options.useOnlyUTC + this._useOnlyUTC = options.useOnlyUTC === undefined ? false : options.useOnlyUTC; + /// The handler to use. this._handler = handler; /** @@ -728,26 +732,54 @@ HeaderEmitter.prototype.addDate = function (date) { if (date.getFullYear() < 1900 || date.getFullYear() > 9999) throw new Error("Date year is out of encodable range"); - // Start by computing the timezone offset for a day. We lack a good format, so - // the the 0-padding is done by hand. Note that the tzoffset we output is in - // the form ±hhmm, so we need to separate the offset (in minutes) into an hour - // and minute pair. - let tzOffset = date.getTimezoneOffset(); - let tzOffHours = Math.abs(Math.trunc(tzOffset / 60)); - let tzOffMinutes = Math.abs(tzOffset) % 60; - let tzOffsetStr = (tzOffset > 0 ? "-" : "+") + - padTo2Digits(tzOffHours) + padTo2Digits(tzOffMinutes); + let day = "", dDate = "", month = "", fullYear = "", hours = "", + minutes = "", seconds = "", tzOffsetStr = "" + + //handle OnlyUTC based date pref + if (this._useOnlyUTC){ + + day = date.getUTCDay(); + dDate = date.getUTCDate(); + month = date.getUTCMonth(); + fullYear = date.getUTCFullYear(); + hours = date.getUTCHours(); + minutes = date.getUTCMinutes(); + seconds = date.getUTCSeconds(); + + // Because we are setting time corresponding to UTC + tzOffsetStr = "+0000"; + + } else { + + // Start by computing the timezone offset for a day. We lack a good format, so + // the the 0-padding is done by hand. Note that the tzoffset we output is in + // the form ±hhmm, so we need to separate the offset (in minutes) into an hour + // and minute pair. + let tzOffset = date.getTimezoneOffset(); + let tzOffHours = Math.abs(Math.trunc(tzOffset / 60)); + let tzOffMinutes = Math.abs(tzOffset) % 60; + + tzOffsetStr = (tzOffset > 0 ? "-" : "+") + + padTo2Digits(tzOffHours) + padTo2Digits(tzOffMinutes); + + day = date.getDay(); + dDate = date.getDate(); + month = date.getMonth(); + fullYear = date.getFullYear(); + hours = date.getHours(); + minutes = date.getMinutes(); + seconds = date.getSeconds(); + } // Convert the day-time figure into a single value to avoid unwanted line // breaks in the middle. - let dayTime = [ - kDaysOfWeek[date.getDay()] + ",", - date.getDate(), - mimeutils.kMonthNames[date.getMonth()], - date.getFullYear(), - padTo2Digits(date.getHours()) + ":" + - padTo2Digits(date.getMinutes()) + ":" + - padTo2Digits(date.getSeconds()), + let dayTime = [ kDaysOfWeek[day] + ",", + dDate, + mimeutils.kMonthNames[month], + fullYear, + padTo2Digits(hours) + ":" + + padTo2Digits(minutes) + ":" + + padTo2Digits(seconds), tzOffsetStr ].join(" "); this.addText(dayTime, false); diff --git a/test/test_header_emitter.js b/test/test_header_emitter.js index d0a4135..b6b7880 100644 --- a/test/test_header_emitter.js +++ b/test/test_header_emitter.js @@ -305,6 +305,105 @@ suite('headeremitter', function () { assert.equal(now.getTime() - now.getMilliseconds(), reparsed.getTime()); }); }); + + /** + * Test addDate method when displayUTC flag is set. This is to support add-ons which dont want + * emails to contain TimeStamp information when email is sent. For example, Torbirdy add-on doesnt + * want timestamp to be shown as it can leak the user location. + */ + suite("addDateAsUTCOnly", function () { + let handler = { + reset: function (expected) { + this.output = ''; + this.expected = expected; + }, + deliverData: function (data) { this.output += data; }, + deliverEOF: function () { + assert.equal(this.output, this.expected + '\r\n'); + } + }; + let header_tests = [ + ["2000-01-01T00:00:00Z", "Sat, 1 Jan 2000 00:00:00 +0000"], + ["2000-02-01T00:00:00Z", "Tue, 1 Feb 2000 00:00:00 +0000"], + ["2000-03-01T00:00:00Z", "Wed, 1 Mar 2000 00:00:00 +0000"], + ["2000-04-01T00:00:00Z", "Sat, 1 Apr 2000 00:00:00 +0000"], + ["2000-05-01T00:00:00Z", "Mon, 1 May 2000 00:00:00 +0000"], + ["2000-06-01T00:00:00Z", "Thu, 1 Jun 2000 00:00:00 +0000"], + ["2000-07-01T00:00:00Z", "Sat, 1 Jul 2000 00:00:00 +0000"], + ["2000-08-01T00:00:00Z", "Tue, 1 Aug 2000 00:00:00 +0000"], + ["2000-09-01T00:00:00Z", "Fri, 1 Sep 2000 00:00:00 +0000"], + ["2000-10-01T00:00:00Z", "Sun, 1 Oct 2000 00:00:00 +0000"], + ["2000-11-01T00:00:00Z", "Wed, 1 Nov 2000 00:00:00 +0000"], + ["2000-12-01T00:00:00Z", "Fri, 1 Dec 2000 00:00:00 +0000"], + + // Test timezone offsets + ["2000-06-01T12:00:00Z", "Thu, 1 Jun 2000 12:00:00 +0000"], + ["2000-06-01T12:00:00+0100", "Thu, 1 Jun 2000 11:00:00 +0000"], + ["2000-06-01T12:00:00+0130", "Thu, 1 Jun 2000 10:30:00 +0000"], + ["2000-06-01T12:00:00-0100", "Thu, 1 Jun 2000 13:00:00 +0000"], + ["2000-06-01T12:00:00-0130", "Thu, 1 Jun 2000 13:30:00 +0000"], + ["2000-06-01T12:00:00+1345", "Wed, 31 May 2000 22:15:00 +0000"], + ["2000-06-01T12:00:00-1200", "Fri, 2 Jun 2000 00:00:00 +0000"], + ["2000-06-01T12:00:00+1337", "Wed, 31 May 2000 22:23:00 +0000"], + ["2000-06-01T12:00:00+0101", "Thu, 1 Jun 2000 10:59:00 +0000"], + ["2000-06-01T12:00:00-1337", "Fri, 2 Jun 2000 01:37:00 +0000"], + + //Some new cases with respect to changing Timezone to UTC + + // Trying change of year conversion + ["2000-12-31T12:00:00-1200", "Mon, 1 Jan 2001 00:00:00 +0000"], + ["2001-01-01T00:00:00+1200", "Sun, 31 Dec 2000 12:00:00 +0000"], + + // Trying leap year conversion + ["2000-02-28T12:00:00-1200", "Tue, 29 Feb 2000 00:00:00 +0000"], + ["2000-03-01T00:00:00+1200", "Tue, 29 Feb 2000 12:00:00 +0000"], + + // Trying non-leap year conversion + ["2001-02-28T12:00:00-1200", "Thu, 1 Mar 2001 00:00:00 +0000"], + ["2001-03-01T00:00:00+1200", "Wed, 28 Feb 2001 12:00:00 +0000"], + + // Try some varying hour, minute, and second amounts, to double-check + // padding and time dates. + ["2000-06-01T01:02:03Z", "Thu, 1 Jun 2000 01:02:03 +0000"], + ["2000-06-01T23:13:17Z", "Thu, 1 Jun 2000 23:13:17 +0000"], + ["2000-06-01T00:05:04Z", "Thu, 1 Jun 2000 00:05:04 +0000"], + ["2000-06-01T23:59:59Z", "Thu, 1 Jun 2000 23:59:59 +0000"], + ["2000-06-01T13:17:40Z", "Thu, 1 Jun 2000 13:17:40 +0000"], + ["2000-06-01T11:15:34Z", "Thu, 1 Jun 2000 11:15:34 +0000"], + ["2000-06-01T04:09:09Z", "Thu, 1 Jun 2000 04:09:09 +0000"], + ["2000-06-01T04:10:10Z", "Thu, 1 Jun 2000 04:10:10 +0000"], + ["2000-06-01T09:13:17Z", "Thu, 1 Jun 2000 09:13:17 +0000"], + ["2000-06-01T13:12:14Z", "Thu, 1 Jun 2000 13:12:14 +0000"], + ["2000-06-01T14:16:48Z", "Thu, 1 Jun 2000 14:16:48 +0000"], + + // Try varying month, date, and year values. + ["2000-01-31T00:00:00Z", "Mon, 31 Jan 2000 00:00:00 +0000"], + ["2000-02-28T00:00:00Z", "Mon, 28 Feb 2000 00:00:00 +0000"], + ["2000-02-29T00:00:00Z", "Tue, 29 Feb 2000 00:00:00 +0000"], + ["2001-02-28T00:00:00Z", "Wed, 28 Feb 2001 00:00:00 +0000"], + ["2000-03-31T00:00:00Z", "Fri, 31 Mar 2000 00:00:00 +0000"], + ["2000-04-30T00:00:00Z", "Sun, 30 Apr 2000 00:00:00 +0000"], + ["2000-05-31T00:00:00Z", "Wed, 31 May 2000 00:00:00 +0000"], + ["2000-06-30T00:00:00Z", "Fri, 30 Jun 2000 00:00:00 +0000"], + ["2000-07-31T00:00:00Z", "Mon, 31 Jul 2000 00:00:00 +0000"], + ["2000-08-31T00:00:00Z", "Thu, 31 Aug 2000 00:00:00 +0000"], + ["2000-09-30T00:00:00Z", "Sat, 30 Sep 2000 00:00:00 +0000"], + ["2000-10-31T00:00:00Z", "Tue, 31 Oct 2000 00:00:00 +0000"], + ["2000-11-30T00:00:00Z", "Thu, 30 Nov 2000 00:00:00 +0000"], + ["2000-12-31T00:00:00Z", "Sun, 31 Dec 2000 00:00:00 +0000"], + ["1900-01-01T00:00:00Z", "Mon, 1 Jan 1900 00:00:00 +0000"], + ["9999-12-31T23:59:59Z", "Fri, 31 Dec 9999 23:59:59 +0000"], + ]; + header_tests.forEach(function (data) { + arrayTest(data, function () { + let emitter = headeremitter.makeStreamingEmitter(handler, { useOnlyUTC: true }); + handler.reset(data[1]); + emitter.addDate(new MockDate(data[0])); + emitter.finish(true); + }); + }); + }); + suite("addParameter", function () { let handler = { reset: function (expected) { From fb5c2845a6ed2f57da9a334daace404f2a631c86 Mon Sep 17 00:00:00 2001 From: Vignesh Prabhu Date: Tue, 3 Mar 2015 00:49:18 +0530 Subject: [PATCH 2/2] Added comment in the code for the option --- headeremitter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/headeremitter.js b/headeremitter.js index 078fe02..85c4c04 100644 --- a/headeremitter.js +++ b/headeremitter.js @@ -72,6 +72,9 @@ function clamp(value, min, max, def) { * @param [options.useASCII=true] {Boolean} * If true, then RFC 2047 and RFC 2231 encoding of headers will be performed * as needed to retain headers as ASCII. + * @param [options.useOnlyUTC=true] {Boolean} + * If true, then date added in header is always in UTC. This is to provide + * user location privacy by not revealing Timezone location. */ function HeaderEmitter(handler, options) { /// The inferred value of options.useASCII