Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,117 @@
define([
'mailbuild',
'../mailchew',
'../util'
], function (MimeNode, $mailchew, $imaputil) {
var formatAddresses = $imaputil.formatAddresses;
MimeNode.prototype.removeHeader = function (key) {
for (var i = 0, len = this._headers.length; i < len; i++) {
if (this._headers[i].key === key) {
this._headers.splice(i, 1);
break;
}
}
};
function normalizeNewlines(body) {
return body.replace(/\r?\n|\r/g, '\r\n');
}
function Composer(newRecords, account, identity) {
var header = this.header = newRecords.header;
var body = this.body = newRecords.body;
this.account = account;
this.identity = identity;
this.sentDate = new Date(this.header.date);
this._smartWakeLock = null;
this.messageId = '<' + Date.now() + Math.random().toString(16).substr(1) + '@mozgaia>';
var messageNode;
var textContent = body.bodyReps[0].content[1];
if (body.bodyReps.length === 2) {
var htmlContent = body.bodyReps[1].content;
messageNode = new MimeNode('text/html');
messageNode.setContent(normalizeNewlines($mailchew.mergeUserTextWithHTML(textContent, htmlContent)));
} else {
messageNode = new MimeNode('text/plain');
messageNode.setContent(normalizeNewlines(textContent));
}
var root;
if (body.attachments.length) {
root = this._rootNode = new MimeNode('multipart/mixed');
root.appendChild(messageNode);
} else {
root = this._rootNode = messageNode;
}
root.setHeader('From', formatAddresses([this.identity]));
root.setHeader('Subject', header.subject);
if (this.identity.replyTo) {
root.setHeader('Reply-To', this.identity.replyTo);
}
if (header.to && header.to.length) {
root.setHeader('To', formatAddresses(header.to));
}
if (header.cc && header.cc.length) {
root.setHeader('Cc', formatAddresses(header.cc));
}
if (header.bcc && header.bcc.length) {
root.setHeader('Bcc', formatAddresses(header.bcc));
}
root.setHeader('User-Agent', 'GaiaMail/0.2');
root.setHeader('Date', this.sentDate.toUTCString());
root.setHeader('Message-Id', this.messageId);
if (body.references) {
root.setHeader('References', body.references);
}
root.setHeader('Content-Transfer-Encoding', 'quoted-printable');
this._blobReplacements = [];
this._uniqueBlobBoundary = '{{blob!' + Math.random() + Date.now() + '}}';
body.attachments.forEach(function (attachment) {
try {
var attachmentNode = new MimeNode(attachment.type, { filename: attachment.name });
attachmentNode.setHeader('Content-Transfer-Encoding', 'base64');
attachmentNode.setContent(this._uniqueBlobBoundary);
root.appendChild(attachmentNode);
this._blobReplacements.push(new Blob(attachment.file));
} catch (ex) {
console.error('Problem attaching attachment:', ex, '\n', ex.stack);
}
}.bind(this));
}
Composer.prototype = {
getEnvelope: function () {
return this._rootNode.getEnvelope();
},
withMessageBlob: function (opts, callback) {
var TEMP_BCC = 'Bcc-Temp';
var TEMP_BCC_REGEX = /^Bcc-Temp: /m;
var hasBcc = opts.includeBcc && this.header.bcc && this.header.bcc.length;
if (hasBcc) {
this._rootNode.setHeader(TEMP_BCC, formatAddresses(this.header.bcc));
} else {
this._rootNode.removeHeader(TEMP_BCC);
}
var str = this._rootNode.build();
if (opts.smtp) {
str = str.replace(/\n\./g, '\n..');
}
if (hasBcc) {
str = str.replace(TEMP_BCC_REGEX, 'Bcc: ');
}
if (str.slice(-2) !== '\r\n') {
str += '\r\n';
}
var splits = str.split(btoa(this._uniqueBlobBoundary) + '\r\n');
this._blobReplacements.forEach(function (blob, i) {
splits.splice(i * 2 + 1, 0, blob);
});
callback(new Blob(splits, { type: this._rootNode.getHeader('content-type') }));
},
setSmartWakeLock: function (wakeLock) {
this._smartWakeLock = wakeLock;
},
renewSmartWakeLock: function (reason) {
if (this._smartWakeLock) {
this._smartWakeLock.renew(reason);
}
}
};
return { Composer: Composer };
});

View file

@ -0,0 +1,74 @@
(function (root, factory) {
if (typeof exports === 'object') {
define = function (deps, factory) {
deps = deps.map.forEach(function (id) {
return require(id);
});
module.exports = factory(deps);
};
define.amd = {};
}
if (typeof define === 'function' && define.amd) {
define([
'wbxml',
'./codepages/Common',
'./codepages/AirSync',
'./codepages/Contacts',
'./codepages/Email',
'./codepages/Calendar',
'./codepages/Move',
'./codepages/ItemEstimate',
'./codepages/FolderHierarchy',
'./codepages/MeetingResponse',
'./codepages/Tasks',
'./codepages/ResolveRecipients',
'./codepages/ValidateCert',
'./codepages/Contacts2',
'./codepages/Ping',
'./codepages/Provision',
'./codepages/Search',
'./codepages/GAL',
'./codepages/AirSyncBase',
'./codepages/Settings',
'./codepages/DocumentLibrary',
'./codepages/ItemOperations',
'./codepages/ComposeMail',
'./codepages/Email2',
'./codepages/Notes',
'./codepages/RightsManagement'
], factory);
} else {
root.ActiveSyncCodepages = factory(WBXML, ASCPCommon, ASCPAirSync, ASCPContacts, ASCPEmail, ASCPCalendar, ASCPMove, ASCPItemEstimate, ASCPHierarchy, ASCPMeetingResponse, ASCPTasks, ASCPResolveRecipients, ASCPValidateCert, ASCPContacts2, ASCPPing, ASCPProvision, ASCPSearch, ASCPGAL, ASCPAirSyncBase, ASCPSettings, ASCPDocumentLibrary, ASCPItemOperations, ASCPComposeMail, ASCPEmail2, ASCPNotes, ASCPRightsManagement);
}
}(this, function (WBXML, Common, AirSync, Contacts, Email, Calendar, Move, ItemEstimate, FolderHierarchy, MeetingResponse, Tasks, ResolveRecipients, ValidateCert, Contacts2, Ping, Provision, Search, GAL, AirSyncBase, Settings, DocumentLibrary, ItemOperations, ComposeMail, Email2, Notes, RightsManagement) {
'use strict';
var codepages = {
Common: Common,
AirSync: AirSync,
Contacts: Contacts,
Email: Email,
Calendar: Calendar,
Move: Move,
ItemEstimate: ItemEstimate,
FolderHierarchy: FolderHierarchy,
MeetingResponse: MeetingResponse,
Tasks: Tasks,
ResolveRecipients: ResolveRecipients,
ValidateCert: ValidateCert,
Contacts2: Contacts2,
Ping: Ping,
Provision: Provision,
Search: Search,
GAL: GAL,
AirSyncBase: AirSyncBase,
Settings: Settings,
DocumentLibrary: DocumentLibrary,
ItemOperations: ItemOperations,
ComposeMail: ComposeMail,
Email2: Email2,
Notes: Notes,
RightsManagement: RightsManagement
};
WBXML.CompileCodepages(codepages);
return codepages;
}));

View file

@ -0,0 +1,99 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPAirSync = factory();
}(this, function () {
'use strict';
return {
Tags: {
Sync: 5,
Responses: 6,
Add: 7,
Change: 8,
Delete: 9,
Fetch: 10,
SyncKey: 11,
ClientId: 12,
ServerId: 13,
Status: 14,
Collection: 15,
Class: 16,
Version: 17,
CollectionId: 18,
GetChanges: 19,
MoreAvailable: 20,
WindowSize: 21,
Commands: 22,
Options: 23,
FilterType: 24,
Truncation: 25,
RtfTruncation: 26,
Conflict: 27,
Collections: 28,
ApplicationData: 29,
DeletesAsMoves: 30,
NotifyGUID: 31,
Supported: 32,
SoftDelete: 33,
MIMESupport: 34,
MIMETruncation: 35,
Wait: 36,
Limit: 37,
Partial: 38,
ConversationMode: 39,
MaxItems: 40,
HeartbeatInterval: 41
},
Enums: {
Status: {
Success: '1',
InvalidSyncKey: '3',
ProtocolError: '4',
ServerError: '5',
ConversionError: '6',
MatchingConflict: '7',
ObjectNotFound: '8',
OutOfSpace: '9',
HierarchyChanged: '12',
IncompleteRequest: '13',
InvalidInterval: '14',
InvalidRequest: '15',
Retry: '16'
},
FilterType: {
NoFilter: '0',
OneDayBack: '1',
ThreeDaysBack: '2',
OneWeekBack: '3',
TwoWeeksBack: '4',
OneMonthBack: '5',
ThreeMonthsBack: '6',
SixMonthsBack: '7',
IncompleteTasks: '8'
},
Conflict: {
ClientReplacesServer: '0',
ServerReplacesClient: '1'
},
MIMESupport: {
Never: '0',
SMIMEOnly: '1',
Always: '2'
},
MIMETruncation: {
TruncateAll: '0',
Truncate4K: '1',
Truncate5K: '2',
Truncate7K: '3',
Truncate10K: '4',
Truncate20K: '5',
Truncate50K: '6',
Truncate100K: '7',
NoTruncate: '8'
}
}
};
}));

View file

@ -0,0 +1,56 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPAirSyncBase = factory();
}(this, function () {
'use strict';
return {
Tags: {
BodyPreference: 4357,
Type: 4358,
TruncationSize: 4359,
AllOrNone: 4360,
Reserved: 4361,
Body: 4362,
Data: 4363,
EstimatedDataSize: 4364,
Truncated: 4365,
Attachments: 4366,
Attachment: 4367,
DisplayName: 4368,
FileReference: 4369,
Method: 4370,
ContentId: 4371,
ContentLocation: 4372,
IsInline: 4373,
NativeBodyType: 4374,
ContentType: 4375,
Preview: 4376,
BodyPartPreference: 4377,
BodyPart: 4378,
Status: 4379
},
Enums: {
Type: {
PlainText: '1',
HTML: '2',
RTF: '3',
MIME: '4'
},
Method: {
Normal: '1',
EmbeddedMessage: '5',
AttachOLE: '6'
},
NativeBodyType: {
PlainText: '1',
HTML: '2',
RTF: '3'
},
Status: { Success: '1' }
}
};
}));

View file

@ -0,0 +1,69 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPCalendar = factory();
}(this, function () {
'use strict';
return {
Tags: {
TimeZone: 1029,
AllDayEvent: 1030,
Attendees: 1031,
Attendee: 1032,
Email: 1033,
Name: 1034,
Body: 1035,
BodyTruncated: 1036,
BusyStatus: 1037,
Categories: 1038,
Category: 1039,
CompressedRTF: 1040,
DtStamp: 1041,
EndTime: 1042,
Exception: 1043,
Exceptions: 1044,
Deleted: 1045,
ExceptionStartTime: 1046,
Location: 1047,
MeetingStatus: 1048,
OrganizerEmail: 1049,
OrganizerName: 1050,
Recurrence: 1051,
Type: 1052,
Until: 1053,
Occurrences: 1054,
Interval: 1055,
DayOfWeek: 1056,
DayOfMonth: 1057,
WeekOfMonth: 1058,
MonthOfYear: 1059,
Reminder: 1060,
Sensitivity: 1061,
Subject: 1062,
StartTime: 1063,
UID: 1064,
AttendeeStatus: 1065,
AttendeeType: 1066,
Attachment: 1067,
Attachments: 1068,
AttName: 1069,
AttSize: 1070,
AttOid: 1071,
AttMethod: 1072,
AttRemoved: 1073,
DisplayName: 1074,
DisallowNewTimeProposal: 1075,
ResponseRequested: 1076,
AppointmentReplyTime: 1077,
ResponseType: 1078,
CalendarType: 1079,
IsLeapMonth: 1080,
FirstDayOfWeek: 1081,
OnlineMeetingConfLink: 1082,
OnlineMeetingExternalLink: 1083
}
};
}));

View file

@ -0,0 +1,90 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPCommon = factory();
}(this, function () {
'use strict';
return {
Enums: {
Status: {
InvalidContent: '101',
InvalidWBXML: '102',
InvalidXML: '103',
InvalidDateTime: '104',
InvalidCombinationOfIDs: '105',
InvalidIDs: '106',
InvalidMIME: '107',
DeviceIdMissingOrInvalid: '108',
DeviceTypeMissingOrInvalid: '109',
ServerError: '110',
ServerErrorRetryLater: '111',
ActiveDirectoryAccessDenied: '112',
MailboxQuotaExceeded: '113',
MailboxServerOffline: '114',
SendQuotaExceeded: '115',
MessageRecipientUnresolved: '116',
MessageReplyNotAllowed: '117',
MessagePreviouslySent: '118',
MessageHasNoRecipient: '119',
MailSubmissionFailed: '120',
MessageReplyFailed: '121',
AttachmentIsTooLarge: '122',
UserHasNoMailbox: '123',
UserCannotBeAnonymous: '124',
UserPrincipalCouldNotBeFound: '125',
UserDisabledForSync: '126',
UserOnNewMailboxCannotSync: '127',
UserOnLegacyMailboxCannotSync: '128',
DeviceIsBlockedForThisUser: '129',
AccessDenied: '130',
AccountDisabled: '131',
SyncStateNotFound: '132',
SyncStateLocked: '133',
SyncStateCorrupt: '134',
SyncStateAlreadyExists: '135',
SyncStateVersionInvalid: '136',
CommandNotSupported: '137',
VersionNotSupported: '138',
DeviceNotFullyProvisionable: '139',
RemoteWipeRequested: '140',
LegacyDeviceOnStrictPolicy: '141',
DeviceNotProvisioned: '142',
PolicyRefresh: '143',
InvalidPolicyKey: '144',
ExternallyManagedDevicesNotAllowed: '145',
NoRecurrenceInCalendar: '146',
UnexpectedItemClass: '147',
RemoteServerHasNoSSL: '148',
InvalidStoredRequest: '149',
ItemNotFound: '150',
TooManyFolders: '151',
NoFoldersFounds: '152',
ItemsLostAfterMove: '153',
FailureInMoveOperation: '154',
MoveCommandDisallowedForNonPersistentMoveAction: '155',
MoveCommandInvalidDestinationFolder: '156',
AvailabilityTooManyRecipients: '160',
AvailabilityDLLimitReached: '161',
AvailabilityTransientFailure: '162',
AvailabilityFailure: '163',
BodyPartPreferenceTypeNotSupported: '164',
DeviceInformationRequired: '165',
InvalidAccountId: '166',
AccountSendDisabled: '167',
IRM_FeatureDisabled: '168',
IRM_TransientError: '169',
IRM_PermanentError: '170',
IRM_InvalidTemplateID: '171',
IRM_OperationNotPermitted: '172',
NoPicture: '173',
PictureTooLarge: '174',
PictureLimitReached: '175',
BodyPart_ConversationTooLarge: '176',
MaximumDevicesReached: '177'
}
}
};
}));

View file

@ -0,0 +1,28 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPComposeMail = factory();
}(this, function () {
'use strict';
return {
Tags: {
SendMail: 5381,
SmartForward: 5382,
SmartReply: 5383,
SaveInSentItems: 5384,
ReplaceMime: 5385,
Source: 5387,
FolderId: 5388,
ItemId: 5389,
LongId: 5390,
InstanceId: 5391,
Mime: 5392,
ClientId: 5393,
Status: 5394,
AccountId: 5395
}
};
}));

View file

@ -0,0 +1,72 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPContacts = factory();
}(this, function () {
'use strict';
return {
Tags: {
Anniversary: 261,
AssistantName: 262,
AssistantPhoneNumber: 263,
Birthday: 264,
Body: 265,
BodySize: 266,
BodyTruncated: 267,
Business2PhoneNumber: 268,
BusinessAddressCity: 269,
BusinessAddressCountry: 270,
BusinessAddressPostalCode: 271,
BusinessAddressState: 272,
BusinessAddressStreet: 273,
BusinessFaxNumber: 274,
BusinessPhoneNumber: 275,
CarPhoneNumber: 276,
Categories: 277,
Category: 278,
Children: 279,
Child: 280,
CompanyName: 281,
Department: 282,
Email1Address: 283,
Email2Address: 284,
Email3Address: 285,
FileAs: 286,
FirstName: 287,
Home2PhoneNumber: 288,
HomeAddressCity: 289,
HomeAddressCountry: 290,
HomeAddressPostalCode: 291,
HomeAddressState: 292,
HomeAddressStreet: 293,
HomeFaxNumber: 294,
HomePhoneNumber: 295,
JobTitle: 296,
LastName: 297,
MiddleName: 298,
MobilePhoneNumber: 299,
OfficeLocation: 300,
OtherAddressCity: 301,
OtherAddressCountry: 302,
OtherAddressPostalCode: 303,
OtherAddressState: 304,
OtherAddressStreet: 305,
PagerNumber: 306,
RadioPhoneNumber: 307,
Spouse: 308,
Suffix: 309,
Title: 310,
WebPage: 311,
YomiCompanyName: 312,
YomiFirstName: 313,
YomiLastName: 314,
CompressedRTF: 315,
Picture: 316,
Alias: 317,
WeightedRank: 318
}
};
}));

View file

@ -0,0 +1,24 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPContacts2 = factory();
}(this, function () {
'use strict';
return {
Tags: {
CustomerId: 3077,
GovernmentId: 3078,
IMAddress: 3079,
IMAddress2: 3080,
IMAddress3: 3081,
ManagerName: 3082,
CompanyMainPhone: 3083,
AccountName: 3084,
NickName: 3085,
MMS: 3086
}
};
}));

View file

@ -0,0 +1,22 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPDocumentLibrary = factory();
}(this, function () {
'use strict';
return {
Tags: {
LinkId: 4869,
DisplayName: 4870,
IsFolder: 4871,
CreationDate: 4872,
LastModifiedDate: 4873,
IsHidden: 4874,
ContentLength: 4875,
ContentType: 4876
}
};
}));

View file

@ -0,0 +1,111 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPEmail = factory();
}(this, function () {
'use strict';
return {
Tags: {
Attachment: 517,
Attachments: 518,
AttName: 519,
AttSize: 520,
Att0Id: 521,
AttMethod: 522,
AttRemoved: 523,
Body: 524,
BodySize: 525,
BodyTruncated: 526,
DateReceived: 527,
DisplayName: 528,
DisplayTo: 529,
Importance: 530,
MessageClass: 531,
Subject: 532,
Read: 533,
To: 534,
Cc: 535,
From: 536,
ReplyTo: 537,
AllDayEvent: 538,
Categories: 539,
Category: 540,
DTStamp: 541,
EndTime: 542,
InstanceType: 543,
BusyStatus: 544,
Location: 545,
MeetingRequest: 546,
Organizer: 547,
RecurrenceId: 548,
Reminder: 549,
ResponseRequested: 550,
Recurrences: 551,
Recurrence: 552,
Recurrence_Type: 553,
Recurrence_Until: 554,
Recurrence_Occurrences: 555,
Recurrence_Interval: 556,
Recurrence_DayOfWeek: 557,
Recurrence_DayOfMonth: 558,
Recurrence_WeekOfMonth: 559,
Recurrence_MonthOfYear: 560,
StartTime: 561,
Sensitivity: 562,
TimeZone: 563,
GlobalObjId: 564,
ThreadTopic: 565,
MIMEData: 566,
MIMETruncated: 567,
MIMESize: 568,
InternetCPID: 569,
Flag: 570,
Status: 571,
ContentClass: 572,
FlagType: 573,
CompleteTime: 574,
DisallowNewTimeProposal: 575
},
Enums: {
Importance: {
Low: '0',
Normal: '1',
High: '2'
},
InstanceType: {
Single: '0',
RecurringMaster: '1',
RecurringInstance: '2',
RecurringException: '3'
},
BusyStatus: {
Free: '0',
Tentative: '1',
Busy: '2',
Oof: '3'
},
Recurrence_Type: {
Daily: '0',
Weekly: '1',
MonthlyNthDay: '2',
Monthly: '3',
YearlyNthDay: '5',
YearlyNthDayOfWeek: '6'
},
Sensitivity: {
Normal: '0',
Personal: '1',
Private: '2',
Confidential: '3'
},
Status: {
Cleared: '0',
Complete: '1',
Active: '2'
}
}
};
}));

View file

@ -0,0 +1,73 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPEmail2 = factory();
}(this, function () {
'use strict';
return {
Tags: {
UmCallerID: 5637,
UmUserNotes: 5638,
UmAttDuration: 5639,
UmAttOrder: 5640,
ConversationId: 5641,
ConversationIndex: 5642,
LastVerbExecuted: 5643,
LastVerbExecutionTime: 5644,
ReceivedAsBcc: 5645,
Sender: 5646,
CalendarType: 5647,
IsLeapMonth: 5648,
AccountId: 5649,
FirstDayOfWeek: 5650,
MeetingMessageType: 5651
},
Enums: {
LastVerbExecuted: {
Unknown: '0',
ReplyToSender: '1',
ReplyToAll: '2',
Forward: '3'
},
CalendarType: {
Default: '0',
Gregorian: '1',
GregorianUS: '2',
Japan: '3',
Taiwan: '4',
Korea: '5',
Hijri: '6',
Thai: '7',
Hebrew: '8',
GregorianMeFrench: '9',
GregorianArabic: '10',
GregorianTranslatedEnglish: '11',
GregorianTranslatedFrench: '12',
JapaneseLunar: '14',
ChineseLunar: '15',
KoreanLunar: '20'
},
FirstDayOfWeek: {
Sunday: '0',
Monday: '1',
Tuesday: '2',
Wednesday: '3',
Thursday: '4',
Friday: '5',
Saturday: '6'
},
MeetingMessageType: {
Unspecified: '0',
InitialRequest: '1',
FullUpdate: '2',
InformationalUpdate: '3',
Outdated: '4',
DelegatorsCopy: '5',
Delegated: '6'
}
}
};
}));

View file

@ -0,0 +1,68 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPHierarchy = factory();
}(this, function () {
'use strict';
return {
Tags: {
Folders: 1797,
Folder: 1798,
DisplayName: 1799,
ServerId: 1800,
ParentId: 1801,
Type: 1802,
Response: 1803,
Status: 1804,
ContentClass: 1805,
Changes: 1806,
Add: 1807,
Delete: 1808,
Update: 1809,
SyncKey: 1810,
FolderCreate: 1811,
FolderDelete: 1812,
FolderUpdate: 1813,
FolderSync: 1814,
Count: 1815
},
Enums: {
Type: {
Generic: '1',
DefaultInbox: '2',
DefaultDrafts: '3',
DefaultDeleted: '4',
DefaultSent: '5',
DefaultOutbox: '6',
DefaultTasks: '7',
DefaultCalendar: '8',
DefaultContacts: '9',
DefaultNotes: '10',
DefaultJournal: '11',
Mail: '12',
Calendar: '13',
Contacts: '14',
Tasks: '15',
Journal: '16',
Notes: '17',
Unknown: '18',
RecipientCache: '19'
},
Status: {
Success: '1',
FolderExists: '2',
SystemFolder: '3',
FolderNotFound: '4',
ParentFolderNotFound: '5',
ServerError: '6',
InvalidSyncKey: '9',
MalformedRequest: '10',
UnknownError: '11',
CodeUnknown: '12'
}
}
};
}));

View file

@ -0,0 +1,28 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPGAL = factory();
}(this, function () {
'use strict';
return {
Tags: {
DisplayName: 4101,
Phone: 4102,
Office: 4103,
Title: 4104,
Company: 4105,
Alias: 4106,
FirstName: 4107,
LastName: 4108,
HomePhone: 4109,
MobilePhone: 4110,
EmailAddress: 4111,
Picture: 4112,
Status: 4113,
Data: 4114
}
};
}));

View file

@ -0,0 +1,32 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPItemEstimate = factory();
}(this, function () {
'use strict';
return {
Tags: {
GetItemEstimate: 1541,
Version: 1542,
Collections: 1543,
Collection: 1544,
Class: 1545,
CollectionId: 1546,
DateTime: 1547,
Estimate: 1548,
Response: 1549,
Status: 1550
},
Enums: {
Status: {
Success: '1',
InvalidCollection: '2',
NoSyncState: '3',
InvalidSyncKey: '4'
}
}
};
}));

View file

@ -0,0 +1,54 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPItemOperations = factory();
}(this, function () {
'use strict';
return {
Tags: {
ItemOperations: 5125,
Fetch: 5126,
Store: 5127,
Options: 5128,
Range: 5129,
Total: 5130,
Properties: 5131,
Data: 5132,
Status: 5133,
Response: 5134,
Version: 5135,
Schema: 5136,
Part: 5137,
EmptyFolderContents: 5138,
DeleteSubFolders: 5139,
UserName: 5140,
Password: 5141,
Move: 5142,
DstFldId: 5143,
ConversationId: 5144,
MoveAlways: 5145
},
Enums: {
Status: {
Success: '1',
ProtocolError: '2',
ServerError: '3',
BadURI: '4',
AccessDenied: '5',
ObjectNotFound: '6',
ConnectionFailure: '7',
InvalidByteRange: '8',
UnknownStore: '9',
EmptyFile: '10',
DataTooLarge: '11',
IOFailure: '12',
ConversionFailure: '14',
InvalidAttachment: '15',
ResourceAccessDenied: '16'
}
}
};
}));

View file

@ -0,0 +1,36 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPMeetingResponse = factory();
}(this, function () {
'use strict';
return {
Tags: {
CalendarId: 2053,
CollectionId: 2054,
MeetingResponse: 2055,
RequestId: 2056,
Request: 2057,
Result: 2058,
Status: 2059,
UserResponse: 2060,
InstanceId: 2062
},
Enums: {
Status: {
Success: '1',
InvalidRequest: '2',
MailboxError: '3',
ServerError: '4'
},
UserResponse: {
Accepted: '1',
Tentative: '2',
Declined: '3'
}
}
};
}));

View file

@ -0,0 +1,32 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPMove = factory();
}(this, function () {
'use strict';
return {
Tags: {
MoveItems: 1285,
Move: 1286,
SrcMsgId: 1287,
SrcFldId: 1288,
DstFldId: 1289,
Response: 1290,
Status: 1291,
DstMsgId: 1292
},
Enums: {
Status: {
InvalidSourceID: '1',
InvalidDestID: '2',
Success: '3',
SourceIsDest: '4',
MoveFailure: '5',
ItemLocked: '7'
}
}
};
}));

View file

@ -0,0 +1,19 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPNotes = factory();
}(this, function () {
'use strict';
return {
Tags: {
Subject: 5893,
MessageClass: 5894,
LastModifiedDate: 5895,
Categories: 5896,
Category: 5897
}
};
}));

View file

@ -0,0 +1,35 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPPing = factory();
}(this, function () {
'use strict';
return {
Tags: {
Ping: 3333,
AutdState: 3334,
Status: 3335,
HeartbeatInterval: 3336,
Folders: 3337,
Folder: 3338,
Id: 3339,
Class: 3340,
MaxFolders: 3341
},
Enums: {
Status: {
Expired: '1',
Changed: '2',
MissingParameters: '3',
SyntaxError: '4',
InvalidInterval: '5',
TooManyFolders: '6',
SyncFolders: '7',
ServerError: '8'
}
}
};
}));

View file

@ -0,0 +1,68 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPProvision = factory();
}(this, function () {
'use strict';
return {
Tags: {
Provision: 3589,
Policies: 3590,
Policy: 3591,
PolicyType: 3592,
PolicyKey: 3593,
Data: 3594,
Status: 3595,
RemoteWipe: 3596,
EASProvisionDoc: 3597,
DevicePasswordEnabled: 3598,
AlphanumericDevicePasswordRequired: 3599,
DeviceEncryptionEnabled: 3600,
RequireStorageCardEncryption: 3600,
PasswordRecoveryEnabled: 3601,
AttachmentsEnabled: 3603,
MinDevicePasswordLength: 3604,
MaxInactivityTimeDeviceLock: 3605,
MaxDevicePasswordFailedAttempts: 3606,
MaxAttachmentSize: 3607,
AllowSimpleDevicePassword: 3608,
DevicePasswordExpiration: 3609,
DevicePasswordHistory: 3610,
AllowStorageCard: 3611,
AllowCamera: 3612,
RequireDeviceEncryption: 3613,
AllowUnsignedApplications: 3614,
AllowUnsignedInstallationPackages: 3615,
MinDevicePasswordComplexCharacters: 3616,
AllowWiFi: 3617,
AllowTextMessaging: 3618,
AllowPOPIMAPEmail: 3619,
AllowBluetooth: 3620,
AllowIrDA: 3621,
RequireManualSyncWhenRoaming: 3622,
AllowDesktopSync: 3623,
MaxCalendarAgeFilter: 3624,
AllowHTMLEmail: 3625,
MaxEmailAgeFilter: 3626,
MaxEmailBodyTruncationSize: 3627,
MaxEmailHTMLBodyTruncationSize: 3628,
RequireSignedSMIMEMessages: 3629,
RequireEncryptedSMIMEMessages: 3630,
RequireSignedSMIMEAlgorithm: 3631,
RequireEncryptionSMIMEAlgorithm: 3632,
AllowSMIMEEncryptionAlgorithmNegotiation: 3633,
AllowSMIMESoftCerts: 3634,
AllowBrowser: 3635,
AllowConsumerEmail: 3636,
AllowRemoteDesktop: 3637,
AllowInternetSharing: 3638,
UnapprovedInROMApplicationList: 3639,
ApplicationName: 3640,
ApprovedApplicationList: 3641,
Hash: 3642
}
};
}));

View file

@ -0,0 +1,63 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPResolveRecipients = factory();
}(this, function () {
'use strict';
return {
Tags: {
ResolveRecipients: 2565,
Response: 2566,
Status: 2567,
Type: 2568,
Recipient: 2569,
DisplayName: 2570,
EmailAddress: 2571,
Certificates: 2572,
Certificate: 2573,
MiniCertificate: 2574,
Options: 2575,
To: 2576,
CertificateRetrieval: 2577,
RecipientCount: 2578,
MaxCertificates: 2579,
MaxAmbiguousRecipients: 2580,
CertificateCount: 2581,
Availability: 2582,
StartTime: 2583,
EndTime: 2584,
MergedFreeBusy: 2585,
Picture: 2586,
MaxSize: 2587,
Data: 2588,
MaxPictures: 2589
},
Enums: {
Status: {
Success: '1',
AmbiguousRecipientFull: '2',
AmbiguousRecipientPartial: '3',
RecipientNotFound: '4',
ProtocolError: '5',
ServerError: '6',
InvalidSMIMECert: '7',
CertLimitReached: '8'
},
CertificateRetrieval: {
None: '1',
Full: '2',
Mini: '3'
},
MergedFreeBusy: {
Free: '0',
Tentative: '1',
Busy: '2',
Oof: '3',
NoData: '4'
}
}
};
}));

View file

@ -0,0 +1,34 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPRightsManagement = factory();
}(this, function () {
'use strict';
return {
Tags: {
RightsManagementSupport: 6149,
RightsManagementTemplates: 6150,
RightsManagementTemplate: 6151,
RightsManagementLicense: 6152,
EditAllowed: 6153,
ReplyAllowed: 6154,
ReplyAllAllowed: 6155,
ForwardAllowed: 6156,
ModifyRecipientsAllowed: 6157,
ExtractAllowed: 6158,
PrintAllowed: 6159,
ExportAllowed: 6160,
ProgrammaticAccessAllowed: 6161,
Owner: 6162,
ContentExpiryDate: 6163,
TemplateID: 6164,
TemplateName: 6165,
TemplateDescription: 6166,
ContentOwner: 6167,
RemoveRightsManagementDistribution: 6168
}
};
}));

View file

@ -0,0 +1,61 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPSearch = factory();
}(this, function () {
'use strict';
return {
Tags: {
Search: 3845,
Stores: 3846,
Store: 3847,
Name: 3848,
Query: 3849,
Options: 3850,
Range: 3851,
Status: 3852,
Response: 3853,
Result: 3854,
Properties: 3855,
Total: 3856,
EqualTo: 3857,
Value: 3858,
And: 3859,
Or: 3860,
FreeText: 3861,
DeepTraversal: 3863,
LongId: 3864,
RebuildResults: 3865,
LessThan: 3866,
GreaterThan: 3867,
Schema: 3868,
Supported: 3869,
UserName: 3870,
Password: 3871,
ConversationId: 3872,
Picture: 3873,
MaxSize: 3874,
MaxPictures: 3875
},
Enums: {
Status: {
Success: '1',
InvalidRequest: '2',
ServerError: '3',
BadLink: '4',
AccessDenied: '5',
NotFound: '6',
ConnectionFailure: '7',
TooComplex: '8',
Timeout: '10',
SyncFolders: '11',
EndOfRange: '12',
AccessBlocked: '13',
CredentialsRequired: '14'
}
}
};
}));

View file

@ -0,0 +1,68 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPSettings = factory();
}(this, function () {
'use strict';
return {
Tags: {
Settings: 4613,
Status: 4614,
Get: 4615,
Set: 4616,
Oof: 4617,
OofState: 4618,
StartTime: 4619,
EndTime: 4620,
OofMessage: 4621,
AppliesToInternal: 4622,
AppliesToExternalKnown: 4623,
AppliesToExternalUnknown: 4624,
Enabled: 4625,
ReplyMessage: 4626,
BodyType: 4627,
DevicePassword: 4628,
Password: 4629,
DeviceInformation: 4630,
Model: 4631,
IMEI: 4632,
FriendlyName: 4633,
OS: 4634,
OSLanguage: 4635,
PhoneNumber: 4636,
UserInformation: 4637,
EmailAddresses: 4638,
SmtpAddress: 4639,
UserAgent: 4640,
EnableOutboundSMS: 4641,
MobileOperator: 4642,
PrimarySmtpAddress: 4643,
Accounts: 4644,
Account: 4645,
AccountId: 4646,
AccountName: 4647,
UserDisplayName: 4648,
SendDisabled: 4649,
RightsManagementInformation: 4651
},
Enums: {
Status: {
Success: '1',
ProtocolError: '2',
AccessDenied: '3',
ServerError: '4',
InvalidArguments: '5',
ConflictingArguments: '6',
DeniedByPolicy: '7'
},
OofState: {
Disabled: '0',
Global: '1',
TimeBased: '2'
}
}
};
}));

View file

@ -0,0 +1,48 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPTasks = factory();
}(this, function () {
'use strict';
return {
Tags: {
Body: 2309,
BodySize: 2310,
BodyTruncated: 2311,
Categories: 2312,
Category: 2313,
Complete: 2314,
DateCompleted: 2315,
DueDate: 2316,
UtcDueDate: 2317,
Importance: 2318,
Recurrence: 2319,
Recurrence_Type: 2320,
Recurrence_Start: 2321,
Recurrence_Until: 2322,
Recurrence_Occurrences: 2323,
Recurrence_Interval: 2324,
Recurrence_DayOfMonth: 2325,
Recurrence_DayOfWeek: 2326,
Recurrence_WeekOfMonth: 2327,
Recurrence_MonthOfYear: 2328,
Recurrence_Regenerate: 2329,
Recurrence_DeadOccur: 2330,
ReminderSet: 2331,
ReminderTime: 2332,
Sensitivity: 2333,
StartDate: 2334,
UtcStartDate: 2335,
Subject: 2336,
CompressedRTF: 2337,
OrdinalDate: 2338,
SubOrdinalDate: 2339,
CalendarType: 2340,
IsLeapMonth: 2341,
FirstDayOfWeek: 2342
}
};
}));

View file

@ -0,0 +1,41 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else
root.ASCPValidateCert = factory();
}(this, function () {
'use strict';
return {
Tags: {
ValidateCert: 2821,
Certificates: 2822,
Certificate: 2823,
CertificateChain: 2824,
CheckCRL: 2825,
Status: 2826
},
Enums: {
Status: {
Success: '1',
ProtocolError: '2',
InvalidSignature: '3',
UntrustedSource: '4',
InvalidChain: '5',
NotForEmail: '6',
Expired: '7',
InconsistentTimes: '8',
IdMisused: '9',
MissingInformation: '10',
CAEndMismatch: '11',
EmailAddressMismatch: '12',
Revoked: '13',
ServerOffline: '14',
ChainRevoked: '15',
RevocationUnknown: '16',
UnknownError: '17'
}
}
};
}));

View file

@ -0,0 +1,397 @@
(function (root, factory) {
if (typeof exports === 'object')
module.exports = factory(require('wbxml'), require('activesync/codepages'));
else if (typeof define === 'function' && define.amd)
define([
'wbxml',
'activesync/codepages'
], factory);
else
root.ActiveSyncProtocol = factory(WBXML, ActiveSyncCodepages);
}(this, function (WBXML, ASCP) {
'use strict';
var exports = {};
var USER_AGENT = 'JavaScript ActiveSync (jsas) Client';
function nullCallback() {
}
function makeError(name, parent, extraArgs) {
function CustomError() {
var self = this instanceof CustomError ? this : Object.create(CustomError.prototype);
var tmp = Error();
var offset = 1;
self.stack = tmp.stack.substring(tmp.stack.indexOf('\n') + 1);
self.message = arguments[0] || tmp.message;
if (extraArgs) {
offset += extraArgs.length;
for (var i = 0; i < extraArgs.length; i++)
self[extraArgs[i]] = arguments[i + 1];
}
var m = /@(.+):(.+)/.exec(self.stack);
self.fileName = arguments[offset] || m && m[1] || '';
self.lineNumber = arguments[offset + 1] || m && m[2] || 0;
return self;
}
CustomError.prototype = Object.create((parent || Error).prototype);
CustomError.prototype.name = name;
CustomError.prototype.constructor = CustomError;
return CustomError;
}
var AutodiscoverError = makeError('ActiveSync.AutodiscoverError');
exports.AutodiscoverError = AutodiscoverError;
var AutodiscoverDomainError = makeError('ActiveSync.AutodiscoverDomainError', AutodiscoverError);
exports.AutodiscoverDomainError = AutodiscoverDomainError;
var HttpError = makeError('ActiveSync.HttpError', null, ['status']);
exports.HttpError = HttpError;
function nsResolver(prefix) {
var baseUrl = 'http://schemas.microsoft.com/exchange/autodiscover/';
var ns = {
rq: baseUrl + 'mobilesync/requestschema/2006',
ad: baseUrl + 'responseschema/2006',
ms: baseUrl + 'mobilesync/responseschema/2006'
};
return ns[prefix] || null;
}
function Version(str) {
var details = str.split('.').map(function (x) {
return parseInt(x);
});
this.major = details[0], this.minor = details[1];
}
exports.Version = Version;
Version.prototype = {
eq: function (other) {
if (!(other instanceof Version))
other = new Version(other);
return this.major === other.major && this.minor === other.minor;
},
ne: function (other) {
return !this.eq(other);
},
gt: function (other) {
if (!(other instanceof Version))
other = new Version(other);
return this.major > other.major || this.major === other.major && this.minor > other.minor;
},
gte: function (other) {
if (!(other instanceof Version))
other = new Version(other);
return this.major >= other.major || this.major === other.major && this.minor >= other.minor;
},
lt: function (other) {
return !this.gte(other);
},
lte: function (other) {
return !this.gt(other);
},
toString: function () {
return this.major + '.' + this.minor;
}
};
function setAuthHeader(xhr, username, password) {
var authorization = 'Basic ' + btoa(username + ':' + password);
xhr.setRequestHeader('Authorization', authorization);
}
function autodiscover(aEmailAddress, aPassword, aTimeout, aCallback, aNoRedirect) {
if (!aCallback)
aCallback = nullCallback;
var domain = aEmailAddress.substring(aEmailAddress.indexOf('@') + 1);
do_autodiscover(domain, aEmailAddress, aPassword, aTimeout, aNoRedirect, function (aError, aConfig) {
if (aError instanceof AutodiscoverDomainError || aError instanceof HttpError)
do_autodiscover('autodiscover.' + domain, aEmailAddress, aPassword, aTimeout, aNoRedirect, aCallback);
else
aCallback(aError, aConfig);
});
}
exports.autodiscover = autodiscover;
function do_autodiscover(aHost, aEmailAddress, aPassword, aTimeout, aNoRedirect, aCallback) {
var url = 'https://' + aHost + '/autodiscover/autodiscover.xml';
return raw_autodiscover(url, aEmailAddress, aPassword, aTimeout, aNoRedirect, aCallback);
}
function raw_autodiscover(aUrl, aEmailAddress, aPassword, aTimeout, aNoRedirect, aCallback) {
var xhr = new XMLHttpRequest({
mozSystem: true,
mozAnon: true
});
xhr.open('POST', aUrl, true);
setAuthHeader(xhr, aEmailAddress, aPassword);
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.setRequestHeader('User-Agent', USER_AGENT);
xhr.timeout = aTimeout;
xhr.upload.onprogress = xhr.upload.onload = function () {
xhr.timeout = 0;
};
xhr.onload = function () {
if (xhr.status < 200 || xhr.status >= 300)
return aCallback(new HttpError(xhr.statusText, xhr.status));
var uid = Math.random();
self.postMessage({
uid: uid,
type: 'configparser',
cmd: 'accountactivesync',
args: [
xhr.responseText,
aNoRedirect
]
});
self.addEventListener('message', function onworkerresponse(evt) {
var data = evt.data;
if (data.type != 'configparser' || data.cmd != 'accountactivesync' || data.uid != uid) {
return;
}
self.removeEventListener(evt.type, onworkerresponse);
var args = data.args;
var config = args[0], error = args[1], redirectedEmail = args[2];
if (error) {
aCallback(new AutodiscoverDomainError(error), config);
} else if (redirectedEmail) {
autodiscover(redirectedEmail, aPassword, aTimeout, aCallback, true);
} else {
aCallback(null, config);
}
});
};
xhr.ontimeout = xhr.onerror = function () {
aCallback(new HttpError('Error getting Autodiscover URL', null));
};
var postdata = '<?xml version="1.0" encoding="utf-8"?>\n' + '<Autodiscover xmlns="' + nsResolver('rq') + '">\n' + ' <Request>\n' + ' <EMailAddress>' + aEmailAddress + '</EMailAddress>\n' + ' <AcceptableResponseSchema>' + nsResolver('ms') + '</AcceptableResponseSchema>\n' + ' </Request>\n' + '</Autodiscover>';
xhr.send(postdata);
}
exports.raw_autodiscover = raw_autodiscover;
function Connection(aDeviceId, aDeviceType) {
this._deviceId = aDeviceId || 'v140Device';
this._deviceType = aDeviceType || 'SmartPhone';
this.timeout = 0;
this._connected = false;
this._waitingForConnection = false;
this._connectionError = null;
this._connectionCallbacks = [];
this.baseUrl = null;
this._username = null;
this._password = null;
this.versions = [];
this.supportedCommands = [];
this.currentVersion = null;
this.onmessage = null;
}
exports.Connection = Connection;
Connection.prototype = {
_notifyConnected: function (aError) {
if (aError)
this.disconnect();
for (var iter in Iterator(this._connectionCallbacks)) {
var callback = iter[1];
callback.apply(callback, arguments);
}
this._connectionCallbacks = [];
},
get connected() {
return this._connected;
},
open: function (aURL, aUsername, aPassword) {
var servicePath = '/Microsoft-Server-ActiveSync';
this.baseUrl = aURL;
if (!this.baseUrl.endsWith(servicePath))
this.baseUrl += servicePath;
this._username = aUsername;
this._password = aPassword;
},
connect: function (aCallback) {
if (this.connected) {
if (aCallback)
aCallback(null);
return;
}
if (aCallback)
this._connectionCallbacks.push(aCallback);
if (this._waitingForConnection)
return;
this._waitingForConnection = true;
this._connectionError = null;
this.getOptions(function (aError, aOptions) {
this._waitingForConnection = false;
this._connectionError = aError;
if (aError) {
console.error('Error connecting to ActiveSync:', aError);
return this._notifyConnected(aError, aOptions);
}
this._connected = true;
this.versions = aOptions.versions;
this.supportedCommands = aOptions.commands;
this.currentVersion = new Version(aOptions.versions.slice(-1)[0]);
return this._notifyConnected(null, aOptions);
}.bind(this));
},
disconnect: function () {
if (this._waitingForConnection)
throw new Error('Can\'t disconnect while waiting for server response');
this._connected = false;
this.versions = [];
this.supportedCommands = [];
this.currentVersion = null;
},
provision: function (aCallback) {
var pv = ASCP.Provision.Tags;
var w = new WBXML.Writer('1.3', 1, 'UTF-8');
w.stag(pv.Provision).etag();
this.postCommand(w, aCallback);
},
getOptions: function (aCallback) {
if (!aCallback)
aCallback = nullCallback;
var conn = this;
var xhr = new XMLHttpRequest({
mozSystem: true,
mozAnon: true
});
xhr.open('OPTIONS', this.baseUrl, true);
setAuthHeader(xhr, this._username, this._password);
xhr.setRequestHeader('User-Agent', USER_AGENT);
xhr.timeout = this.timeout;
xhr.upload.onprogress = xhr.upload.onload = function () {
xhr.timeout = 0;
};
xhr.onload = function () {
if (xhr.status < 200 || xhr.status >= 300) {
console.error('ActiveSync options request failed with response ' + xhr.status);
if (conn.onmessage)
conn.onmessage('options', 'error', xhr, null, null, null, null);
aCallback(new HttpError(xhr.statusText, xhr.status));
return;
}
var result = {
versions: xhr.getResponseHeader('MS-ASProtocolVersions').split(/\s*,\s*/),
commands: xhr.getResponseHeader('MS-ASProtocolCommands').split(/\s*,\s*/)
};
if (conn.onmessage)
conn.onmessage('options', 'ok', xhr, null, null, null, result);
aCallback(null, result);
};
xhr.ontimeout = xhr.onerror = function () {
var error = new Error('Error getting OPTIONS URL');
console.error(error);
if (conn.onmessage)
conn.onmessage('options', 'timeout', xhr, null, null, null, null);
aCallback(error);
};
xhr.responseType = 'text';
xhr.send();
},
supportsCommand: function (aCommand) {
if (!this.connected)
throw new Error('Connection required to get command');
if (typeof aCommand === 'number')
aCommand = ASCP.__tagnames__[aCommand];
return this.supportedCommands.indexOf(aCommand) !== -1;
},
doCommand: function () {
console.warn('doCommand is deprecated. Use postCommand instead.');
this.postCommand.apply(this, arguments);
},
postCommand: function (aCommand, aCallback, aExtraParams, aExtraHeaders, aProgressCallback) {
var contentType = 'application/vnd.ms-sync.wbxml';
if (typeof aCommand === 'string' || typeof aCommand === 'number') {
this.postData(aCommand, contentType, null, aCallback, aExtraParams, aExtraHeaders);
} else {
var commandName = ASCP.__tagnames__[aCommand.rootTag];
this.postData(commandName, contentType, aCommand.dataType === 'blob' ? aCommand.blob : aCommand.buffer, aCallback, aExtraParams, aExtraHeaders, aProgressCallback);
}
},
postData: function (aCommand, aContentType, aData, aCallback, aExtraParams, aExtraHeaders, aProgressCallback) {
if (typeof aCommand === 'number')
aCommand = ASCP.__tagnames__[aCommand];
if (!this.supportsCommand(aCommand)) {
var error = new Error('This server doesn\'t support the command ' + aCommand);
console.error(error);
aCallback(error);
return;
}
var params = [
[
'Cmd',
aCommand
],
[
'User',
this._username
],
[
'DeviceId',
this._deviceId
],
[
'DeviceType',
this._deviceType
]
];
if (aExtraParams) {
for (var iter in Iterator(params)) {
var param = iter[1];
if (param[0] in aExtraParams)
throw new TypeError('reserved URL parameter found');
}
for (var kv in Iterator(aExtraParams))
params.push(kv);
}
var paramsStr = params.map(function (i) {
return encodeURIComponent(i[0]) + '=' + encodeURIComponent(i[1]);
}).join('&');
var xhr = new XMLHttpRequest({
mozSystem: true,
mozAnon: true
});
xhr.open('POST', this.baseUrl + '?' + paramsStr, true);
setAuthHeader(xhr, this._username, this._password);
xhr.setRequestHeader('MS-ASProtocolVersion', this.currentVersion);
xhr.setRequestHeader('Content-Type', aContentType);
xhr.setRequestHeader('User-Agent', USER_AGENT);
if (aExtraHeaders) {
for (var iter in Iterator(aExtraHeaders)) {
var key = iter[0], key = iter[1];
xhr.setRequestHeader(key, value);
}
}
xhr.timeout = this.timeout;
xhr.upload.onprogress = xhr.upload.onload = function () {
xhr.timeout = 0;
};
xhr.onprogress = function (event) {
if (aProgressCallback)
aProgressCallback(event.loaded, event.total);
};
var conn = this;
var parentArgs = arguments;
xhr.onload = function () {
if (xhr.status === 451) {
conn.baseUrl = xhr.getResponseHeader('X-MS-Location');
if (conn.onmessage)
conn.onmessage(aCommand, 'redirect', xhr, params, aExtraHeaders, aData, null);
conn.postData.apply(conn, parentArgs);
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
console.error('ActiveSync command ' + aCommand + ' failed with ' + 'response ' + xhr.status);
if (conn.onmessage)
conn.onmessage(aCommand, 'error', xhr, params, aExtraHeaders, aData, null);
aCallback(new HttpError(xhr.statusText, xhr.status));
return;
}
var response = null;
if (xhr.response.byteLength > 0)
response = new WBXML.Reader(new Uint8Array(xhr.response), ASCP);
if (conn.onmessage)
conn.onmessage(aCommand, 'ok', xhr, params, aExtraHeaders, aData, response);
aCallback(null, response);
};
xhr.ontimeout = xhr.onerror = function (evt) {
var error = new Error('Command URL ' + evt.type + ' for command ' + aCommand + ' at baseUrl ' + this.baseUrl);
console.error(error);
if (conn.onmessage)
conn.onmessage(aCommand, evt.type, xhr, params, aExtraHeaders, aData, null);
aCallback(error);
}.bind(this);
xhr.responseType = 'arraybuffer';
xhr.send(aData);
}
};
return exports;
}));

View file

@ -0,0 +1,81 @@
function Blob(parts, properties) {
this._parts = parts;
var size = 0;
parts.forEach(function (part) {
if (part instanceof Blob)
size += part.size;
else if (part instanceof ArrayBuffer)
size += part.byteLength;
else
size += part.length;
});
this.size = size;
this.type = properties ? properties.type : null;
}
;
exports.Blob = Blob;
Blob.prototype = {
_asArrayBuffer: function () {
var buffer = new ArrayBuffer(this.size);
var u8 = new Uint8Array(buffer);
var offset = 0;
this._parts.forEach(function (part) {
var sub8;
if (part instanceof Blob) {
var subarr = part._asArrayBuffer();
sub8 = new Uint8Array(subarr);
u8.set(sub8, offset);
offset += sub8.length;
} else if (typeof part === 'string') {
var encoder = new TextEncoder('utf-8');
sub8 = encoder.encode(part);
u8.set(sub8, offset);
offset += sub8.length;
} else if (part instanceof ArrayBuffer) {
sub8 = new Uint8Array(part);
u8.set(sub8, offset);
offset += sub8.length;
} else {
u8.set(part, offset);
offset += part.length;
}
});
return buffer;
}
};
function FileReader() {
this.error = null;
this.readyState = this.EMPTY;
this.result = null;
this.onabort = null;
this.onerror = null;
this.onload = null;
this.onloadend = null;
this.onloadstart = null;
this.onprogress = null;
}
exports.FileReader = FileReader;
FileReader.prototype = {
EMPTY: 0,
LOADING: 1,
DONE: 2,
readAsArrayBuffer: function (blob) {
process.nextTick(function () {
var event = { target: this };
if (this.onload)
this.onload(event);
if (this.onloadend)
this.onloadend(event);
}.bind(this));
this.result = blob._asArrayBuffer();
},
readAsBinaryString: function (blob) {
throw new Error('not implemented');
},
readAsDataURL: function (blob) {
throw new Error('not implemented');
},
readAsText: function (blob, encoding) {
throw new Error('not implemented');
}
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,932 @@
(function (root, factory) {
if (typeof exports === 'object') {
module.exports = factory();
this.Blob = require('./blob').Blob;
var stringencoding = require('stringencoding');
this.TextEncoder = stringencoding.TextEncoder;
this.TextDecoder = stringencoding.TextDecoder;
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
root.WBXML = factory();
}
}(this, function () {
'use strict';
var exports = {};
var Tokens = {
SWITCH_PAGE: 0,
END: 1,
ENTITY: 2,
STR_I: 3,
LITERAL: 4,
EXT_I_0: 64,
EXT_I_1: 65,
EXT_I_2: 66,
PI: 67,
LITERAL_C: 68,
EXT_T_0: 128,
EXT_T_1: 129,
EXT_T_2: 130,
STR_T: 131,
LITERAL_A: 132,
EXT_0: 192,
EXT_1: 193,
EXT_2: 194,
OPAQUE: 195,
LITERAL_AC: 196
};
var EndOfData = { message: 'THIS IS AN INTERNAL CONTROL FLOW HACK THAT YOU SHOULD NOT SEE' };
function makeError(name, parent, extraArgs) {
function CustomError() {
var self = this instanceof CustomError ? this : Object.create(CustomError.prototype);
var tmp = Error();
var offset = 1;
self.stack = tmp.stack.substring(tmp.stack.indexOf('\n') + 1);
self.message = arguments[0] || tmp.message;
if (extraArgs) {
offset += extraArgs.length;
for (var i = 0; i < extraArgs.length; i++)
self[extraArgs[i]] = arguments[i + 1];
}
var m = /@(.+):(.+)/.exec(self.stack);
self.fileName = arguments[offset] || m && m[1] || '';
self.lineNumber = arguments[offset + 1] || m && m[2] || 0;
return self;
}
CustomError.prototype = Object.create((parent || Error).prototype);
CustomError.prototype.name = name;
CustomError.prototype.constructor = CustomError;
return CustomError;
}
var ParseError = makeError('WBXML.ParseError');
exports.ParseError = ParseError;
function StringTable(data, decoder) {
this.strings = [];
this.offsets = {};
var start = 0;
for (var i = 0; i < data.length; i++) {
if (data[i] === 0) {
this.offsets[start] = this.strings.length;
this.strings.push(decoder.decode(data.subarray(start, i)));
start = i + 1;
}
}
}
StringTable.prototype = {
get: function (offset) {
if (offset in this.offsets)
return this.strings[this.offsets[offset]];
else {
if (offset < 0)
throw new ParseError('offset must be >= 0');
var curr = 0;
for (var i = 0; i < this.strings.length; i++) {
if (offset < curr + this.strings[i].length + 1)
return this.strings[i].slice(offset - curr);
curr += this.strings[i].length + 1;
}
}
throw new ParseError('invalid offset');
}
};
function CompileCodepages(codepages) {
codepages.__nsnames__ = {};
codepages.__tagnames__ = {};
codepages.__attrdata__ = {};
for (var name in codepages) {
var page = codepages[name];
if (name.match(/^__/))
continue;
if (page.Tags) {
var tagName, tagValue;
for (tagName in page.Tags) {
tagValue = page.Tags[tagName];
codepages.__nsnames__[tagValue >> 8] = name;
break;
}
for (tagName in page.Tags) {
tagValue = page.Tags[tagName];
codepages.__tagnames__[tagValue] = tagName;
}
}
if (page.Attrs) {
for (var attrName in page.Attrs) {
var attrData = page.Attrs[attrName];
if (!('name' in attrData))
attrData.name = attrName;
codepages.__attrdata__[attrData.value] = attrData;
page.Attrs[attrName] = attrData.value;
}
}
}
}
exports.CompileCodepages = CompileCodepages;
var mib2str = {
3: 'US-ASCII',
4: 'ISO-8859-1',
5: 'ISO-8859-2',
6: 'ISO-8859-3',
7: 'ISO-8859-4',
8: 'ISO-8859-5',
9: 'ISO-8859-6',
10: 'ISO-8859-7',
11: 'ISO-8859-8',
12: 'ISO-8859-9',
13: 'ISO-8859-10',
106: 'UTF-8'
};
var str2mib = {};
for (var mibId in mib2str) {
var mibStr = mib2str[mibId];
str2mib[mibStr] = mibId;
}
function Element(ownerDocument, type, tag) {
this.ownerDocument = ownerDocument;
this.type = type;
this._attrs = {};
if (typeof tag === 'string') {
var pieces = tag.split(':');
if (pieces.length === 1) {
this.localTagName = pieces[0];
} else {
this.namespaceName = pieces[0];
this.localTagName = pieces[1];
}
} else {
this.tag = tag;
Object.defineProperties(this, {
'namespace': {
get: function () {
return this.tag >> 8;
}
},
'localTag': {
get: function () {
return this.tag & 255;
}
},
'namespaceName': {
get: function () {
return this.ownerDocument._codepages.__nsnames__[this.namespace];
}
},
'localTagName': {
get: function () {
return this.ownerDocument._codepages.__tagnames__[this.tag];
}
}
});
}
}
exports.Element = Element;
Element.prototype = {
get tagName() {
var ns = this.namespaceName;
ns = ns ? ns + ':' : '';
return ns + this.localTagName;
},
getAttributes: function () {
var attributes = [];
for (var name in this._attrs) {
var pieces = this._attrs[name];
var data = name.split(':');
attributes.push({
name: name,
namespace: data[0],
localName: data[1],
value: this._getAttribute(pieces)
});
}
return attributes;
},
getAttribute: function (attr) {
if (typeof attr === 'number')
attr = this.ownerDocument._codepages.__attrdata__[attr].name;
else if (!(attr in this._attrs) && this.namespace !== null && attr.indexOf(':') === -1)
attr = this.namespaceName + ':' + attr;
return this._getAttribute(this._attrs[attr]);
},
_getAttribute: function (pieces) {
var strValue = '';
var array = [];
for (var i = 0; i < pieces.length; i++) {
var hunk = pieces[i];
if (hunk instanceof Extension) {
if (strValue) {
array.push(strValue);
strValue = '';
}
array.push(hunk);
} else if (typeof hunk === 'number') {
strValue += this.ownerDocument._codepages.__attrdata__[hunk].data || '';
} else {
strValue += hunk;
}
}
if (strValue)
array.push(strValue);
return array.length === 1 ? array[0] : array;
},
_addAttribute: function (attr) {
if (typeof attr === 'string') {
if (attr in this._attrs)
throw new ParseError('attribute ' + attr + ' is repeated');
return this._attrs[attr] = [];
} else {
var namespace = attr >> 8;
var localAttr = attr & 255;
var localName = this.ownerDocument._codepages.__attrdata__[localAttr].name;
var nsName = this.ownerDocument._codepages.__nsnames__[namespace];
var name = nsName + ':' + localName;
if (name in this._attrs)
throw new ParseError('attribute ' + name + ' is repeated');
return this._attrs[name] = [attr];
}
}
};
function EndTag(ownerDocument) {
this.ownerDocument = ownerDocument;
}
exports.EndTag = EndTag;
EndTag.prototype = {
get type() {
return 'ETAG';
}
};
function Text(ownerDocument, textContent) {
this.ownerDocument = ownerDocument;
this.textContent = textContent;
}
exports.Text = Text;
Text.prototype = {
get type() {
return 'TEXT';
}
};
function Extension(ownerDocument, subtype, index, value) {
this.ownerDocument = ownerDocument;
this.subtype = subtype;
this.index = index;
this.value = value;
}
exports.Extension = Extension;
Extension.prototype = {
get type() {
return 'EXT';
}
};
function ProcessingInstruction(ownerDocument) {
this.ownerDocument = ownerDocument;
}
exports.ProcessingInstruction = ProcessingInstruction;
ProcessingInstruction.prototype = {
get type() {
return 'PI';
},
get target() {
if (typeof this.targetID === 'string')
return this.targetID;
else
return this.ownerDocument._codepages.__attrdata__[this.targetID].name;
},
_setTarget: function (target) {
this.targetID = target;
if (typeof target === 'string')
return this._data = [];
else
return this._data = [target];
},
_getAttribute: Element.prototype._getAttribute,
get data() {
return this._getAttribute(this._data);
}
};
function Opaque(ownerDocument, data) {
this.ownerDocument = ownerDocument;
this.data = data;
}
exports.Opaque = Opaque;
Opaque.prototype = {
get type() {
return 'OPAQUE';
}
};
function Reader(data, codepages) {
this._data = data instanceof Writer ? data.bytes : data;
this._codepages = codepages;
this.rewind();
}
exports.Reader = Reader;
Reader.prototype = {
_get_uint8: function () {
if (this._index === this._data.length)
throw EndOfData;
return this._data[this._index++];
},
_get_mb_uint32: function () {
var b;
var result = 0;
do {
b = this._get_uint8();
result = result * 128 + (b & 127);
} while (b & 128);
return result;
},
_get_slice: function (length) {
var start = this._index;
this._index += length;
return this._data.subarray(start, this._index);
},
_get_c_string: function () {
var start = this._index;
while (this._get_uint8());
return this._data.subarray(start, this._index - 1);
},
rewind: function () {
this._index = 0;
var v = this._get_uint8();
this.version = ((v & 240) + 1).toString() + '.' + (v & 15).toString();
this.pid = this._get_mb_uint32();
this.charset = mib2str[this._get_mb_uint32()] || 'unknown';
this._decoder = new TextDecoder(this.charset);
var tbl_len = this._get_mb_uint32();
this.strings = new StringTable(this._get_slice(tbl_len), this._decoder);
this.document = this._getDocument();
},
_getDocument: function () {
var States = {
BODY: 0,
ATTRIBUTES: 1,
ATTRIBUTE_PI: 2
};
var state = States.BODY;
var currentNode;
var currentAttr;
var codepage = 0;
var depth = 0;
var foundRoot = false;
var doc = [];
var appendString = function (s) {
if (state === States.BODY) {
if (!currentNode)
currentNode = new Text(this, s);
else
currentNode.textContent += s;
} else {
currentAttr.push(s);
}
}.bind(this);
try {
while (true) {
var tok = this._get_uint8();
if (tok === Tokens.SWITCH_PAGE) {
codepage = this._get_uint8();
if (!(codepage in this._codepages.__nsnames__))
throw new ParseError('unknown codepage ' + codepage);
} else if (tok === Tokens.END) {
if (state === States.BODY && depth-- > 0) {
if (currentNode) {
doc.push(currentNode);
currentNode = null;
}
doc.push(new EndTag(this));
} else if (state === States.ATTRIBUTES || state === States.ATTRIBUTE_PI) {
state = States.BODY;
doc.push(currentNode);
currentNode = null;
currentAttr = null;
} else {
throw new ParseError('unexpected END token');
}
} else if (tok === Tokens.ENTITY) {
if (state === States.BODY && depth === 0)
throw new ParseError('unexpected ENTITY token');
var e = this._get_mb_uint32();
appendString('&#' + e + ';');
} else if (tok === Tokens.STR_I) {
if (state === States.BODY && depth === 0)
throw new ParseError('unexpected STR_I token');
appendString(this._decoder.decode(this._get_c_string()));
} else if (tok === Tokens.PI) {
if (state !== States.BODY)
throw new ParseError('unexpected PI token');
state = States.ATTRIBUTE_PI;
if (currentNode)
doc.push(currentNode);
currentNode = new ProcessingInstruction(this);
} else if (tok === Tokens.STR_T) {
if (state === States.BODY && depth === 0)
throw new ParseError('unexpected STR_T token');
var r = this._get_mb_uint32();
appendString(this.strings.get(r));
} else if (tok === Tokens.OPAQUE) {
if (state !== States.BODY)
throw new ParseError('unexpected OPAQUE token');
var len = this._get_mb_uint32();
var data = this._get_slice(len);
if (currentNode) {
doc.push(currentNode);
currentNode = null;
}
doc.push(new Opaque(this, data));
} else if ((tok & 64 || tok & 128) && (tok & 63) < 3) {
var hi = tok & 192;
var lo = tok & 63;
var subtype;
var value;
if (hi === Tokens.EXT_I_0) {
subtype = 'string';
value = this._decoder.decode(this._get_c_string());
} else if (hi === Tokens.EXT_T_0) {
subtype = 'integer';
value = this._get_mb_uint32();
} else {
subtype = 'byte';
value = null;
}
var ext = new Extension(this, subtype, lo, value);
if (state === States.BODY) {
if (currentNode) {
doc.push(currentNode);
currentNode = null;
}
doc.push(ext);
} else {
currentAttr.push(ext);
}
} else if (state === States.BODY) {
if (depth === 0) {
if (foundRoot)
throw new ParseError('multiple root nodes found');
foundRoot = true;
}
var tag = (codepage << 8) + (tok & 63);
if ((tok & 63) === Tokens.LITERAL) {
var r = this._get_mb_uint32();
tag = this.strings.get(r);
}
if (currentNode)
doc.push(currentNode);
currentNode = new Element(this, tok & 64 ? 'STAG' : 'TAG', tag);
if (tok & 64)
depth++;
if (tok & 128) {
state = States.ATTRIBUTES;
} else {
state = States.BODY;
doc.push(currentNode);
currentNode = null;
}
} else {
var attr = (codepage << 8) + tok;
if (!(tok & 128)) {
if (tok === Tokens.LITERAL) {
var r = this._get_mb_uint32();
attr = this.strings.get(r);
}
if (state === States.ATTRIBUTE_PI) {
if (currentAttr)
throw new ParseError('unexpected attribute in PI');
currentAttr = currentNode._setTarget(attr);
} else {
currentAttr = currentNode._addAttribute(attr);
}
} else {
currentAttr.push(attr);
}
}
}
} catch (e) {
if (e !== EndOfData)
throw e;
}
return doc;
},
dump: function (indentation, header) {
var result = '';
if (indentation === undefined)
indentation = 2;
var indent = function (level) {
return new Array(level * indentation + 1).join(' ');
};
var tagstack = [];
if (header) {
result += 'Version: ' + this.version + '\n';
result += 'Public ID: ' + this.pid + '\n';
result += 'Charset: ' + this.charset + '\n';
result += 'String table:\n "' + this.strings.strings.join('"\n "') + '"\n\n';
}
var newline = false;
var doc = this.document;
var doclen = doc.length;
for (var iNode = 0; iNode < doclen; iNode++) {
var node = doc[iNode];
if (node.type === 'TAG' || node.type === 'STAG') {
result += indent(tagstack.length) + '<' + node.tagName;
var attributes = node.getAttributes();
for (var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
result += ' ' + attr.name + '="' + attr.value + '"';
}
if (node.type === 'STAG') {
tagstack.push(node.tagName);
result += '>\n';
} else
result += '/>\n';
} else if (node.type === 'ETAG') {
var tag = tagstack.pop();
result += indent(tagstack.length) + '</' + tag + '>\n';
} else if (node.type === 'TEXT') {
result += indent(tagstack.length) + node.textContent + '\n';
} else if (node.type === 'PI') {
result += indent(tagstack.length) + '<?' + node.target;
if (node.data)
result += ' ' + node.data;
result += '?>\n';
} else if (node.type === 'OPAQUE') {
result += indent(tagstack.length) + '<![CDATA[' + node.data + ']]>\n';
} else {
throw new Error('Unknown node type "' + node.type + '"');
}
}
return result;
}
};
function Writer(version, pid, charset, strings, dataType) {
if (dataType === 'blob')
this._blobs = [];
else
this._blobs = null;
this.dataType = dataType || 'arraybuffer';
this._rawbuf = new ArrayBuffer(1024);
this._buffer = new Uint8Array(this._rawbuf);
this._pos = 0;
this._codepage = 0;
this._tagStack = [];
this._rootTagValue = null;
var infos = version.split('.').map(function (x) {
return parseInt(x);
});
var major = infos[0], minor = infos[1];
var v = (major - 1 << 4) + minor;
var charsetNum = charset;
if (typeof charset === 'string') {
charsetNum = str2mib[charset];
if (charsetNum === undefined)
throw new Error('unknown charset ' + charset);
}
var encoder = this._encoder = new TextEncoder(charset);
this._write(v);
this._write(pid);
this._write(charsetNum);
if (strings) {
var bytes = strings.map(function (s) {
return encoder.encode(s);
});
var len = bytes.reduce(function (x, y) {
return x + y.length + 1;
}, 0);
this._write_mb_uint32(len);
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i];
this._write_bytes(b);
this._write(0);
}
} else {
this._write(0);
}
}
exports.Writer = Writer;
Writer.Attribute = function (name, value) {
this.isValue = typeof name === 'number' && name & 128;
if (this.isValue && value !== undefined)
throw new Error('Can\'t specify a value for attribute value constants');
this.name = name;
this.value = value;
};
Writer.StringTableRef = function (index) {
this.index = index;
};
Writer.Entity = function (code) {
this.code = code;
};
Writer.Extension = function (subtype, index, data) {
var validTypes = {
'string': {
value: Tokens.EXT_I_0,
validator: function (data) {
return typeof data === 'string';
}
},
'integer': {
value: Tokens.EXT_T_0,
validator: function (data) {
return typeof data === 'number';
}
},
'byte': {
value: Tokens.EXT_0,
validator: function (data) {
return data === null || data === undefined;
}
}
};
var info = validTypes[subtype];
if (!info)
throw new Error('Invalid WBXML Extension type');
if (!info.validator(data))
throw new Error('Data for WBXML Extension does not match type');
if (index !== 0 && index !== 1 && index !== 2)
throw new Error('Invalid WBXML Extension index');
this.subtype = info.value;
this.index = index;
this.data = data;
};
Writer.a = function (name, val) {
return new Writer.Attribute(name, val);
};
Writer.str_t = function (index) {
return new Writer.StringTableRef(index);
};
Writer.ent = function (code) {
return new Writer.Entity(code);
};
Writer.ext = function (subtype, index, data) {
return new Writer.Extension(subtype, index, data);
};
Writer.prototype = {
_write: function (tok) {
if (this._pos === this._buffer.length - 1) {
this._rawbuf = new ArrayBuffer(this._rawbuf.byteLength * 2);
var buffer = new Uint8Array(this._rawbuf);
for (var i = 0; i < this._buffer.length; i++)
buffer[i] = this._buffer[i];
this._buffer = buffer;
}
this._buffer[this._pos++] = tok;
},
_write_mb_uint32: function (value) {
var bytes = [];
bytes.push(value % 128);
while (value >= 128) {
value >>= 7;
bytes.push(128 + value % 128);
}
for (var i = bytes.length - 1; i >= 0; i--)
this._write(bytes[i]);
},
_write_bytes: function (bytes) {
for (var i = 0; i < bytes.length; i++)
this._write(bytes[i]);
},
_write_str: function (str) {
this._write_bytes(this._encoder.encode(str));
},
_setCodepage: function (codepage) {
if (this._codepage !== codepage) {
this._write(Tokens.SWITCH_PAGE);
this._write(codepage);
this._codepage = codepage;
}
},
_writeTag: function (tag, stag, attrs) {
if (tag === undefined)
throw new Error('unknown tag');
var flags = 0;
if (stag)
flags += 64;
if (attrs.length)
flags += 128;
if (tag instanceof Writer.StringTableRef) {
this._write(Tokens.LITERAL + flags);
this._write_mb_uint32(tag.index);
} else {
this._setCodepage(tag >> 8);
this._write((tag & 255) + flags);
if (!this._rootTagValue)
this._rootTagValue = tag;
}
if (attrs.length) {
for (var i = 0; i < attrs.length; i++) {
var attr = attrs[i];
this._writeAttr(attr);
}
this._write(Tokens.END);
}
},
_writeAttr: function (attr) {
if (!(attr instanceof Writer.Attribute))
throw new Error('Expected an Attribute object');
if (attr.isValue)
throw new Error('Can\'t use attribute value constants here');
if (attr.name instanceof Writer.StringTableRef) {
this._write(Tokens.LITERAL);
this._write(attr.name.index);
} else {
this._setCodepage(attr.name >> 8);
this._write(attr.name & 255);
}
this._writeText(attr.value, true);
},
_writeText: function (value, inAttr) {
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
var piece = value[i];
this._writeText(piece, inAttr);
}
} else if (value instanceof Writer.StringTableRef) {
this._write(Tokens.STR_T);
this._write_mb_uint32(value.index);
} else if (value instanceof Writer.Entity) {
this._write(Tokens.ENTITY);
this._write_mb_uint32(value.code);
} else if (value instanceof Writer.Extension) {
this._write(value.subtype + value.index);
if (value.subtype === Tokens.EXT_I_0) {
this._write_str(value.data);
this._write(0);
} else if (value.subtype === Tokens.EXT_T_0) {
this._write_mb_uint32(value.data);
}
} else if (value instanceof Writer.Attribute) {
if (!value.isValue)
throw new Error('Unexpected Attribute object');
if (!inAttr)
throw new Error('Can\'t use attribute value constants outside of ' + 'attributes');
this._setCodepage(value.name >> 8);
this._write(value.name & 255);
} else if (value !== null && value !== undefined) {
this._write(Tokens.STR_I);
this._write_str(value.toString());
this._write(0);
}
},
tag: function (tag) {
var tail = arguments.length > 1 ? arguments[arguments.length - 1] : null;
if (tail === null || tail instanceof Writer.Attribute) {
var rest = Array.prototype.slice.call(arguments, 1);
this._writeTag(tag, false, rest);
return this;
} else {
var head = Array.prototype.slice.call(arguments, 0, -1);
return this.stag.apply(this, head).text(tail).etag();
}
},
stag: function (tag) {
var rest = Array.prototype.slice.call(arguments, 1);
this._writeTag(tag, true, rest);
this._tagStack.push(tag);
return this;
},
etag: function (tag) {
if (this._tagStack.length === 0)
throw new Error('Spurious etag() call!');
var expectedTag = this._tagStack.pop();
if (tag !== undefined && tag !== expectedTag)
throw new Error('Closed the wrong tag');
this._write(Tokens.END);
return this;
},
text: function (value) {
this._writeText(value);
return this;
},
pi: function (target, data) {
this._write(Tokens.PI);
this._writeAttr(Writer.a(target, data));
this._write(Tokens.END);
return this;
},
ext: function (subtype, index, data) {
return this.text(Writer.ext(subtype, index, data));
},
opaque: function (data) {
this._write(Tokens.OPAQUE);
if (data instanceof Blob) {
if (!this._blobs)
throw new Error('Writer not opened in blob mode');
this._write_mb_uint32(data.size);
this._blobs.push(this.bytes);
this._blobs.push(data);
this._rawbuf = new ArrayBuffer(1024);
this._buffer = new Uint8Array(this._rawbuf);
this._pos = 0;
} else if (typeof data === 'string') {
this._write_mb_uint32(data.length);
this._write_str(data);
} else {
this._write_mb_uint32(data.length);
for (var i = 0; i < data.length; i++)
this._write(data[i]);
}
return this;
},
get buffer() {
return this._rawbuf.slice(0, this._pos);
},
get bytes() {
return new Uint8Array(this._rawbuf, 0, this._pos);
},
get blob() {
if (!this._blobs)
throw new Error('No blobs!');
var useBlobs = this._blobs;
if (this._pos)
useBlobs = useBlobs.concat([this.bytes]);
var superBlob = new Blob(useBlobs);
return superBlob;
},
get rootTag() {
return this._rootTagValue;
}
};
function EventParser() {
this.listeners = [];
this.onerror = function (e) {
throw e;
};
}
exports.EventParser = EventParser;
EventParser.prototype = {
addEventListener: function (path, callback) {
this.listeners.push({
path: path,
callback: callback
});
},
_pathMatches: function (a, b) {
return a.length === b.length && a.every(function (val, i) {
if (b[i] === '*')
return true;
else if (Array.isArray(b[i])) {
return b[i].indexOf(val) !== -1;
} else
return val === b[i];
});
},
run: function (reader) {
var fullPath = [];
var recPath = [];
var recording = 0;
var doc = reader.document;
var doclen = doc.length;
var listeners = this.listeners, iListener, listener;
for (var iNode = 0; iNode < doclen; iNode++) {
var node = doc[iNode];
if (node.type === 'TAG') {
fullPath.push(node.tag);
for (iListener = 0; iListener < listeners.length; iListener++) {
listener = listeners[iListener];
if (this._pathMatches(fullPath, listener.path)) {
node.children = [];
try {
listener.callback(node);
} catch (e) {
if (this.onerror)
this.onerror(e);
}
}
}
fullPath.pop();
} else if (node.type === 'STAG') {
fullPath.push(node.tag);
for (iListener = 0; iListener < listeners.length; iListener++) {
listener = listeners[iListener];
if (this._pathMatches(fullPath, listener.path)) {
recording++;
}
}
} else if (node.type === 'ETAG') {
for (iListener = 0; iListener < listeners.length; iListener++) {
listener = listeners[iListener];
if (this._pathMatches(fullPath, listener.path)) {
recording--;
try {
listener.callback(recPath[recPath.length - 1]);
} catch (e) {
if (this.onerror)
this.onerror(e);
}
}
}
fullPath.pop();
}
if (recording) {
if (node.type === 'STAG') {
node.type = 'TAG';
node.children = [];
if (recPath.length)
recPath[recPath.length - 1].children.push(node);
recPath.push(node);
} else if (node.type === 'ETAG') {
recPath.pop();
} else {
node.children = [];
recPath[recPath.length - 1].children.push(node);
}
}
}
}
};
return exports;
}));

View file

@ -0,0 +1,8 @@
var jsdom = require('jsdom');
module.exports = require('./lib/bleach.js');
module.exports.documentConstructor = jsdom.jsdom;
module.exports._preCleanNodeHack = function (node, html) {
if (node.innerHTML === '' && html.match(/<!--/)) {
node.innerHTML = html + '-->';
}
};

View file

@ -0,0 +1,115 @@
define(['require'], function (require) {
var slice = Array.prototype.slice;
co['default'] = co.co = co;
co.wrap = function (fn) {
createPromise.__generatorFunction__ = fn;
return createPromise;
function createPromise() {
return co.call(this, fn.apply(this, arguments));
}
};
function co(gen) {
var ctx = this;
if (typeof gen === 'function')
gen = gen.call(this);
return new Promise(function (resolve, reject) {
onFulfilled();
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
}
function onRejected(err) {
var ret;
try {
ret = gen.throw(err);
} catch (e) {
return reject(e);
}
next(ret);
}
function next(ret) {
if (ret.done)
return resolve(ret.value);
var value = toPromise.call(ctx, ret.value);
if (value && isPromise(value))
return value.then(onFulfilled, onRejected);
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"'));
}
});
}
function toPromise(obj) {
if (!obj)
return obj;
if (isPromise(obj))
return obj;
if (isGeneratorFunction(obj) || isGenerator(obj))
return co.call(this, obj);
if ('function' == typeof obj)
return thunkToPromise.call(this, obj);
if (Array.isArray(obj))
return arrayToPromise.call(this, obj);
if (isObject(obj))
return objectToPromise.call(this, obj);
return obj;
}
function thunkToPromise(fn) {
var ctx = this;
return new Promise(function (resolve, reject) {
fn.call(ctx, function (err, res) {
if (err)
return reject(err);
if (arguments.length > 2)
res = slice.call(arguments, 1);
resolve(res);
});
});
}
function arrayToPromise(obj) {
return Promise.all(obj.map(toPromise, this));
}
function objectToPromise(obj) {
var results = new obj.constructor();
var keys = Object.keys(obj);
var promises = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var promise = toPromise.call(this, obj[key]);
if (promise && isPromise(promise))
defer(promise, key);
else
results[key] = obj[key];
}
return Promise.all(promises).then(function () {
return results;
});
function defer(promise, key) {
results[key] = undefined;
promises.push(promise.then(function (res) {
results[key] = res;
}));
}
}
function isPromise(obj) {
return 'function' == typeof obj.then;
}
function isGenerator(obj) {
return 'function' == typeof obj.next && 'function' == typeof obj.throw;
}
function isGeneratorFunction(obj) {
var constructor = obj.constructor;
if (!constructor)
return false;
if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName)
return true;
return isGenerator(constructor.prototype);
}
function isObject(val) {
return Object == val.constructor;
}
return co;
});

View file

@ -0,0 +1,419 @@
(function (root, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define([
'mimefuncs',
'mimetypes',
'punycode',
'addressparser'
], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require('mimefuncs'), require('mimetypes'), require('punycode'), require('wo-addressparser'));
} else {
root.mailbuild = factory(mimefuncs, mimetypes, punycode, addressparser);
}
}(this, function (mimefuncs, mimetypes, punycode, addressparser) {
'use strict';
function MimeNode(contentType, options) {
this.nodeCounter = 0;
options = options || {};
this.baseBoundary = options.baseBoundary || Date.now().toString() + Math.random();
this.date = new Date();
this.rootNode = options.rootNode || this;
if (options.filename) {
this.filename = options.filename;
if (!contentType) {
contentType = mimetypes.detectMimeType(this.filename.split('.').pop());
}
}
this.parentNode = options.parentNode;
this._nodeId = ++this.rootNode.nodeCounter;
this._childNodes = [];
this._headers = [];
if (contentType) {
this.setHeader('content-type', contentType);
}
}
MimeNode.prototype.createChild = function (contentType, options) {
if (!options && typeof contentType === 'object') {
options = contentType;
contentType = undefined;
}
var node = new MimeNode(contentType, options);
this.appendChild(node);
return node;
};
MimeNode.prototype.appendChild = function (childNode) {
if (childNode.rootNode !== this.rootNode) {
childNode.rootNode = this.rootNode;
childNode._nodeId = ++this.rootNode.nodeCounter;
}
childNode.parentNode = this;
this._childNodes.push(childNode);
return childNode;
};
MimeNode.prototype.replace = function (node) {
if (node === this) {
return this;
}
this.parentNode._childNodes.forEach(function (childNode, i) {
if (childNode === this) {
node.rootNode = this.rootNode;
node.parentNode = this.parentNode;
node._nodeId = this._nodeId;
this.rootNode = this;
this.parentNode = undefined;
node.parentNode._childNodes[i] = node;
}
}.bind(this));
return node;
};
MimeNode.prototype.remove = function () {
if (!this.parentNode) {
return this;
}
for (var i = this.parentNode._childNodes.length - 1; i >= 0; i--) {
if (this.parentNode._childNodes[i] === this) {
this.parentNode._childNodes.splice(i, 1);
this.parentNode = undefined;
this.rootNode = this;
return this;
}
}
};
MimeNode.prototype.setHeader = function (key, value) {
var added = false, headerValue;
if (!value && key && typeof key === 'object') {
if (key.key && key.value) {
this.setHeader(key.key, key.value);
} else if (Array.isArray(key)) {
key.forEach(function (i) {
this.setHeader(i.key, i.value);
}.bind(this));
} else {
Object.keys(key).forEach(function (i) {
this.setHeader(i, key[i]);
}.bind(this));
}
return this;
}
key = this._normalizeHeaderKey(key);
headerValue = {
key: key,
value: value
};
for (var i = 0, len = this._headers.length; i < len; i++) {
if (this._headers[i].key === key) {
if (!added) {
this._headers[i] = headerValue;
added = true;
} else {
this._headers.splice(i, 1);
i--;
len--;
}
}
}
if (!added) {
this._headers.push(headerValue);
}
return this;
};
MimeNode.prototype.addHeader = function (key, value) {
if (!value && key && typeof key === 'object') {
if (key.key && key.value) {
this.addHeader(key.key, key.value);
} else if (Array.isArray(key)) {
key.forEach(function (i) {
this.addHeader(i.key, i.value);
}.bind(this));
} else {
Object.keys(key).forEach(function (i) {
this.addHeader(i, key[i]);
}.bind(this));
}
return this;
}
this._headers.push({
key: this._normalizeHeaderKey(key),
value: value
});
return this;
};
MimeNode.prototype.getHeader = function (key) {
key = this._normalizeHeaderKey(key);
for (var i = 0, len = this._headers.length; i < len; i++) {
if (this._headers[i].key === key) {
return this._headers[i].value;
}
}
};
MimeNode.prototype.setContent = function (content) {
this.content = content;
return this;
};
MimeNode.prototype.build = function () {
var lines = [], contentType = (this.getHeader('Content-Type') || '').toString().toLowerCase().trim(), transferEncoding, flowed;
if (this.content) {
transferEncoding = (this.getHeader('Content-Transfer-Encoding') || '').toString().toLowerCase().trim();
if (!transferEncoding || [
'base64',
'quoted-printable'
].indexOf(transferEncoding) < 0) {
if (/^text\//i.test(contentType)) {
if (this._isPlainText(this.content)) {
if (/^.{77,}/m.test(this.content)) {
flowed = true;
}
transferEncoding = '7bit';
} else {
transferEncoding = 'quoted-printable';
}
} else if (!/^multipart\//i.test(contentType)) {
transferEncoding = transferEncoding || 'base64';
}
}
if (transferEncoding) {
this.setHeader('Content-Transfer-Encoding', transferEncoding);
}
}
if (this.filename && !this.getHeader('Content-Disposition')) {
this.setHeader('Content-Disposition', 'attachment');
}
this._headers.forEach(function (header) {
var key = header.key, value = header.value, structured;
switch (header.key) {
case 'Content-Disposition':
structured = mimefuncs.parseHeaderValue(value);
if (this.filename) {
structured.params.filename = this.filename;
}
value = this._buildHeaderValue(structured);
break;
case 'Content-Type':
structured = mimefuncs.parseHeaderValue(value);
this._handleContentType(structured);
if (flowed) {
structured.params.format = 'flowed';
}
if (String(structured.params.format).toLowerCase().trim() === 'flowed') {
flowed = true;
}
if (structured.value.match(/^text\//) && typeof this.content === 'string' && /[\u0080-\uFFFF]/.test(this.content)) {
structured.params.charset = 'utf-8';
}
value = this._buildHeaderValue(structured);
break;
case 'Bcc':
return;
}
value = this._encodeHeaderValue(key, value);
if (!(value || '').toString().trim()) {
return;
}
lines.push(mimefuncs.foldLines(key + ': ' + value, 76));
}.bind(this));
if (this.rootNode === this) {
if (!this.getHeader('Date')) {
lines.push('Date: ' + this.date.toUTCString().replace(/GMT/, '+0000'));
}
if (!this.getHeader('Message-Id')) {
lines.push('Message-Id: <' + [
0,
0,
0
].reduce(function (prev) {
return prev + '-' + Math.floor((1 + Math.random()) * 4294967296).toString(16).substring(1);
}, Date.now()) + '@' + (this.getEnvelope().from || 'localhost').split('@').pop() + '>');
}
if (!this.getHeader('MIME-Version')) {
lines.push('MIME-Version: 1.0');
}
}
lines.push('');
if (this.content) {
switch (transferEncoding) {
case 'quoted-printable':
lines.push(mimefuncs.quotedPrintableEncode(this.content));
break;
case 'base64':
lines.push(mimefuncs.base64Encode(this.content, typeof this.content === 'object' && 'binary' || false));
break;
default:
if (flowed) {
lines.push(mimefuncs.foldLines(this.content.replace(/\r?\n/g, '\r\n').replace(/^( |From|>)/gim, ' $1'), 76, true));
} else {
lines.push(this.content.replace(/\r?\n/g, '\r\n'));
}
}
if (this.multipart) {
lines.push('');
}
}
if (this.multipart) {
this._childNodes.forEach(function (node) {
lines.push('--' + this.boundary);
lines.push(node.build());
}.bind(this));
lines.push('--' + this.boundary + '--');
lines.push('');
}
return lines.join('\r\n');
};
MimeNode.prototype.getEnvelope = function () {
var envelope = {
from: false,
to: []
};
this._headers.forEach(function (header) {
var list = [];
if (header.key === 'From' || !envelope.from && [
'Reply-To',
'Sender'
].indexOf(header.key) >= 0) {
this._convertAddresses(this._parseAddresses(header.value), list);
if (list.length && list[0]) {
envelope.from = list[0];
}
} else if ([
'To',
'Cc',
'Bcc'
].indexOf(header.key) >= 0) {
this._convertAddresses(this._parseAddresses(header.value), envelope.to);
}
}.bind(this));
return envelope;
};
MimeNode.prototype._parseAddresses = function (addresses) {
return [].concat.apply([], [].concat(addresses).map(function (address) {
if (address && address.address) {
address = this._convertAddresses(address);
}
return addressparser.parse(address);
}.bind(this)));
};
MimeNode.prototype._normalizeHeaderKey = function (key) {
return (key || '').toString().replace(/\r?\n|\r/g, ' ').trim().toLowerCase().replace(/^MIME\b|^[a-z]|\-[a-z]/gi, function (c) {
return c.toUpperCase();
});
};
MimeNode.prototype._buildHeaderValue = function (structured) {
var paramsArray = [];
Object.keys(structured.params || {}).forEach(function (param) {
if (param === 'filename') {
mimefuncs.continuationEncode(param, structured.params[param], 50).forEach(function (encodedParam) {
paramsArray.push(encodedParam.key + '=' + encodedParam.value);
});
} else {
paramsArray.push(param + '=' + this._escapeHeaderArgument(structured.params[param]));
}
}.bind(this));
return structured.value + (paramsArray.length ? '; ' + paramsArray.join('; ') : '');
};
MimeNode.prototype._escapeHeaderArgument = function (value) {
if (value.match(/[\s'"\\;\/=]|^\-/g)) {
return '"' + value.replace(/(["\\])/g, '\\$1') + '"';
} else {
return value;
}
};
MimeNode.prototype._handleContentType = function (structured) {
this.contentType = structured.value.trim().toLowerCase();
this.multipart = this.contentType.split('/').reduce(function (prev, value) {
return prev === 'multipart' ? value : false;
});
if (this.multipart) {
this.boundary = structured.params.boundary = structured.params.boundary || this.boundary || this._generateBoundary();
} else {
this.boundary = false;
}
};
MimeNode.prototype._generateBoundary = function () {
return '----sinikael-?=_' + this._nodeId + '-' + this.rootNode.baseBoundary;
};
MimeNode.prototype._encodeHeaderValue = function (key, value) {
key = this._normalizeHeaderKey(key);
switch (key) {
case 'From':
case 'Sender':
case 'To':
case 'Cc':
case 'Bcc':
case 'Reply-To':
return this._convertAddresses(this._parseAddresses(value));
case 'Message-Id':
case 'In-Reply-To':
case 'Content-Id':
value = (value || '').toString().replace(/\r?\n|\r/g, ' ');
if (value.charAt(0) !== '<') {
value = '<' + value;
}
if (value.charAt(value.length - 1) !== '>') {
value = value + '>';
}
return value;
case 'References':
value = [].concat.apply([], [].concat(value || '').map(function (elm) {
elm = (elm || '').toString().replace(/\r?\n|\r/g, ' ').trim();
return elm.replace(/<[^>]*>/g, function (str) {
return str.replace(/\s/g, '');
}).split(/\s+/);
})).map(function (elm) {
if (elm.charAt(0) !== '<') {
elm = '<' + elm;
}
if (elm.charAt(elm.length - 1) !== '>') {
elm = elm + '>';
}
return elm;
});
return value.join(' ').trim();
default:
value = (value || '').toString().replace(/\r?\n|\r/g, ' ');
return mimefuncs.mimeWordsEncode(value, 'Q', 52);
}
};
MimeNode.prototype._convertAddresses = function (addresses, uniqueList) {
var values = [];
uniqueList = uniqueList || [];
[].concat(addresses || []).forEach(function (address) {
if (address.address) {
address.address = address.address.replace(/^.*?(?=\@)/, function (user) {
return mimefuncs.mimeWordsEncode(user, 'Q', 52);
}).replace(/@.+$/, function (domain) {
return '@' + punycode.toASCII(domain.substr(1));
});
if (!address.name) {
values.push(address.address);
} else if (address.name) {
values.push(this._encodeAddressName(address.name) + ' <' + address.address + '>');
}
if (uniqueList.indexOf(address.address) < 0) {
uniqueList.push(address.address);
}
} else if (address.group) {
values.push(this._encodeAddressName(address.name) + ':' + (address.group.length ? this._convertAddresses(address.group, uniqueList) : '').trim() + ';');
}
}.bind(this));
return values.join(', ');
};
MimeNode.prototype._encodeAddressName = function (name) {
if (!/^[\w ']*$/.test(name)) {
if (/^[\x20-\x7e]*$/.test(name)) {
return '"' + name.replace(/([\\"])/g, '\\$1') + '"';
} else {
return mimefuncs.mimeWordEncode(name, 'Q', 52);
}
}
return name;
};
MimeNode.prototype._isPlainText = function (value) {
if (typeof value !== 'string' || /[\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]/.test(value)) {
return false;
} else {
return true;
}
};
return MimeNode;
}));

View file

@ -0,0 +1,217 @@
;
(function (root) {
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
var punycode, maxInt = 2147483647, base = 36, tMin = 1, tMax = 26, skew = 38, damp = 700, initialBias = 72, initialN = 128, delimiter = '-', regexPunycode = /^xn--/, regexNonASCII = /[^ -~]/, regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
}, baseMinusTMin = base - tMin, floor = Math.floor, stringFromCharCode = String.fromCharCode, key;
function error(type) {
throw RangeError(errors[type]);
}
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
function ucs2decode(string) {
var output = [], counter = 0, length = string.length, value, extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 55296 && value <= 56319 && counter < length) {
extra = string.charCodeAt(counter++);
if ((extra & 64512) == 56320) {
output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
} else {
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
function ucs2encode(array) {
return map(array, function (value) {
var output = '';
if (value > 65535) {
value -= 65536;
output += stringFromCharCode(value >>> 10 & 1023 | 55296);
value = 56320 | value & 1023;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
function digitToBasic(digit, flag) {
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
function decode(input) {
var output = [], inputLength = input.length, out, i = 0, n = initialN, bias = initialBias, basic, j, index, oldi, w, k, digit, t, baseMinusT;
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
if (input.charCodeAt(j) >= 128) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
for (index = basic > 0 ? basic + 1 : 0; index < inputLength;) {
for (oldi = i, w = 1, k = base;; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
function encode(input) {
var n, delta, handledCPCount, basicLength, bias, j, m, q, k, t, currentValue, output = [], inputLength, handledCPCountPlusOne, baseMinusT, qMinusT;
input = ucs2decode(input);
inputLength = input.length;
n = initialN;
delta = 0;
bias = initialBias;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 128) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
if (basicLength) {
output.push(delimiter);
}
while (handledCPCount < inputLength) {
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
for (q = delta, k = base;; k += base) {
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)));
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
function toUnicode(domain) {
return mapDomain(domain, function (string) {
return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
});
}
function toASCII(domain) {
return mapDomain(domain, function (string) {
return regexNonASCII.test(string) ? 'xn--' + encode(string) : string;
});
}
punycode = {
'version': '1.2.4',
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
define('punycode', [], function () {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) {
freeModule.exports = punycode;
} else {
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else {
root.punycode = punycode;
}
}(this));

View file

@ -0,0 +1,3 @@
define(['./utf7'], function (utf7) {
return utf7;
});

View file

@ -0,0 +1,27 @@
define([
'browserbox',
'logic',
'./client',
'../syncbase',
'exports'
], function (BrowserBox, logic, imapclient, syncbase, exports) {
exports.probeAccount = function (credentials, connInfo) {
var scope = logic.scope('ImapProber');
logic(scope, 'connecting', { connInfo: connInfo });
var conn;
return imapclient.createImapConnection(credentials, connInfo, function onCredentialsUpdated() {
logic(scope, 'credentials-updated');
}).then(function (newConn) {
conn = newConn;
logic(scope, 'success');
return { conn: conn };
}).catch(function (err) {
err = imapclient.normalizeImapError(conn, err);
logic(scope, 'error', { error: err });
if (conn) {
conn.close();
}
throw err;
});
};
});

View file

@ -0,0 +1,45 @@
define([], function () {
function BodyFetcher(connection, parserClass, list) {
this.connection = connection;
this.parserClass = parserClass;
this.list = list;
this.pending = list.length;
this.onparsed = null;
this.onend = null;
list.forEach(this._fetch, this);
}
BodyFetcher.prototype = {
_fetch: function (request) {
this.connection.listMessages(request.uid, ['BODY.PEEK[' + (request.partInfo.partID || '1') + ']' + (request.bytes ? '<' + request.bytes[0] + '.' + request.bytes[1] + '>' : '')], { byUid: true }, function (err, messages) {
if (err) {
this._resolve(err, request, null);
} else {
var parser = new this.parserClass(request.partInfo);
var msg = messages[0];
var body = null;
for (var key in msg) {
if (/^body/.test(key)) {
body = msg[key];
break;
}
}
if (!body) {
this.resolve('no body', request);
} else {
parser.parse(body);
this._resolve(null, request, parser.complete());
}
}
}.bind(this));
},
_resolve: function (err, req, result) {
if (this.onparsed) {
this.onparsed(err, req, result);
}
if (!--this.pending && this.onend) {
this.onend();
}
}
};
return { BodyFetcher: BodyFetcher };
});

View file

@ -0,0 +1,29 @@
define(['./textparser'], function ($textparser) {
var TextParser = $textparser.TextParser;
function bufferAppend(buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
}
;
function SnippetParser(partDef) {
TextParser.apply(this, arguments);
}
SnippetParser.prototype = {
parse: function (buffer) {
if (!this._buffer) {
this._buffer = buffer;
} else {
this._buffer = bufferAppend(this._buffer, buffer);
}
TextParser.prototype.parse.apply(this, arguments);
},
complete: function () {
var content = TextParser.prototype.complete.apply(this, arguments);
content.buffer = this._buffer;
return content;
}
};
return { SnippetParser: SnippetParser };
});

View file

@ -0,0 +1,122 @@
define([
'../imapchew',
'../../allback',
'exports'
], function ($imapchew, allback, exports) {
var INITIAL_FETCH_PARAMS = [
'BODYSTRUCTURE',
'INTERNALDATE',
'FLAGS',
'BODY.PEEK[HEADER.FIELDS (FROM TO CC BCC SUBJECT REPLY-TO MESSAGE-ID REFERENCES)]'
];
var FLAG_FETCH_PARAMS = ['FLAGS'];
var SNIPPET_BYTES = 256;
var KNOWN_HEADERS_AGGR_COST = 20, KNOWN_HEADERS_PER_COST = 1, NEW_HEADERS_AGGR_COST = 20, NEW_HEADERS_PER_COST = 5, NEW_BODIES_PER_COST = 30;
function Sync(options) {
this.storage = options.storage;
this.connection = options.connection;
this.knownHeaders = options.knownHeaders || [];
this.knownUIDs = options.knownUIDs || [];
this.newUIDs = options.newUIDs || [];
this._progress = options.initialProgress || 0.25;
this._progressCost = (this.knownUIDs.length ? KNOWN_HEADERS_AGGR_COST : 0) + KNOWN_HEADERS_PER_COST * this.knownUIDs.length + (this.newUIDs.length ? NEW_HEADERS_AGGR_COST : 0) + NEW_HEADERS_PER_COST * this.newUIDs.length;
this.onprogress = null;
this.oncomplete = null;
this._beginSync();
}
Sync.prototype = {
_updateProgress: function (newProgress) {
this._progress += newProgress;
if (this.onprogress) {
this.onprogress(0.25 + 0.75 * (this._progress / this._progressCost));
}
},
_beginSync: function () {
var latch = allback.latch();
if (this.newUIDs.length) {
this._handleNewUids(latch.defer('new'));
}
if (this.knownUIDs.length) {
this._handleKnownUids(latch.defer('known'));
}
latch.then(function () {
if (!this.oncomplete) {
return;
}
this.oncomplete(this.newUIDs.length, this.knownUIDs.length);
}.bind(this));
},
_handleNewUids: function (callback) {
var pendingSnippets = [];
var self = this;
this.connection.listMessages(this.newUIDs, INITIAL_FETCH_PARAMS, { byUid: true }, function (err, messages) {
if (err) {
console.warn('New UIDs fetch error, ideally harmless:', err);
callback();
return;
}
var latch = allback.latch();
messages.forEach(function (msg) {
var recentIdx = msg.flags.indexOf('\\Recent');
if (recentIdx !== -1) {
msg.flags.splice(recentIdx, 1);
}
try {
var chewRep = $imapchew.chewHeaderAndBodyStructure(msg, self.storage.folderId, self.storage._issueNewHeaderId());
chewRep.header.bytesToDownloadForBodyDisplay = $imapchew.calculateBytesToDownloadForImapBodyDisplay(chewRep.bodyInfo);
pendingSnippets.push(chewRep);
self.storage.addMessageHeader(chewRep.header, chewRep.bodyInfo, latch.defer());
self.storage.addMessageBody(chewRep.header, chewRep.bodyInfo, latch.defer());
} catch (ex) {
console.warn('message problem, skipping message', ex, '\n', ex.stack);
}
}.bind(this));
latch.then(callback);
}.bind(this));
},
_handleKnownUids: function (callback) {
var self = this;
this.connection.listMessages(self.knownUIDs, FLAG_FETCH_PARAMS, { byUid: true }, function (err, messages) {
if (err) {
console.warn('Known UIDs fetch error, ideally harmless:', err);
callback();
return;
}
var latch = allback.latch();
messages.forEach(function (msg, i) {
console.log('FETCHED', i, 'known id', self.knownHeaders[i].id, 'known srvid', self.knownHeaders[i].srvid, 'actual id', msg.uid);
var recentIdx = msg.flags.indexOf('\\Recent');
if (recentIdx !== -1) {
msg.flags.splice(recentIdx, 1);
}
if (self.knownHeaders[i].srvid !== msg.uid) {
i = self.knownUIDs.indexOf(msg.uid);
if (i === -1) {
console.warn('Server fetch reports unexpected message:', msg.uid);
return;
}
}
var header = self.knownHeaders[i];
var sortedExistingFlags = header.flags.slice();
sortedExistingFlags.sort();
msg.flags.sort();
if (header.flags.indexOf('\\Seen') === -1 && msg.flags.indexOf('\\Seen') !== -1) {
self.storage.folderMeta.unreadCount--;
} else if (header.flags.indexOf('\\Seen') !== -1 && msg.flags.indexOf('\\Seen') === -1) {
self.storage.folderMeta.unreadCount++;
}
if (header.flags.toString() !== msg.flags.toString()) {
console.warn(' FLAGS: "' + header.flags.toString() + '" VS "' + msg.flags.toString() + '"');
header.flags = msg.flags;
self.storage.updateMessageHeader(header.date, header.id, true, header, null, latch.defer());
} else {
self.storage.unchangedMessageHeader(header);
}
});
self._updateProgress(KNOWN_HEADERS_AGGR_COST + KNOWN_HEADERS_PER_COST * self.knownUIDs.length);
latch.then(callback);
}.bind(this));
}
};
exports.Sync = Sync;
});

View file

@ -0,0 +1,41 @@
define([
'mimeparser',
'mimefuncs',
'exports'
], function (MimeParser, mimefuncs, exports) {
function TextParser(partDef) {
this._partDef = partDef;
var parser = this._parser = new MimeParser();
this._totalBytes = 0;
var charsetPart = '', formatPart = '';
if (partDef.params && partDef.params.charset) {
charsetPart = '; charset="' + partDef.params.charset.toLowerCase() + '"';
}
if (partDef.params && partDef.params.format) {
formatPart = '; format="' + partDef.params.format.toLowerCase() + '"';
}
parser.write('Content-Type: ' + partDef.type.toLowerCase() + '/' + partDef.subtype.toLowerCase() + charsetPart + formatPart + '\r\n');
if (partDef.encoding) {
parser.write('Content-Transfer-Encoding: ' + partDef.encoding + '\r\n');
}
parser.write('\r\n');
if (partDef.pendingBuffer) {
this.parse(partDef.pendingBuffer);
}
}
TextParser.prototype = {
parse: function (buffer) {
this._totalBytes += buffer.length;
this._parser.write(buffer);
},
complete: function () {
this._parser.end();
var str = mimefuncs.charset.decode(this._parser.node.content, 'utf-8');
return {
bytesFetched: this._totalBytes,
text: str
};
}
};
exports.TextParser = TextParser;
});

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,99 @@
define([
'./pop3',
'../syncbase',
'logic',
'../errorutils',
'exports'
], function (pop3, syncbase, logic, errorutils, exports) {
var scope = logic.scope('Pop3Prober');
exports.probeAccount = function (credentials, connInfo) {
var opts = {
host: connInfo.hostname,
port: connInfo.port,
crypto: connInfo.crypto,
username: credentials.username,
password: credentials.password,
connTimeout: syncbase.CONNECT_TIMEOUT_MS
};
logic(scope, 'connecting', { connInfo: connInfo });
var resolve, reject;
var promise = new Promise(function (_resolve, _reject) {
resolve = _resolve;
reject = _reject;
});
var conn = new pop3.Pop3Client(opts, function (err) {
if (err) {
reject(err);
return;
}
conn.protocol.sendRequest('UIDL', ['1'], false, function (err, rsp) {
if (rsp) {
conn.protocol.sendRequest('TOP', [
'1',
'0'
], true, function (err, rsp) {
if (rsp) {
resolve(conn);
} else if (err.err) {
logic(scope, 'server-not-great', { why: 'no TOP' });
reject('pop-server-not-great');
} else {
reject(rsp.err);
}
});
} else {
conn.protocol.sendRequest('UIDL', [], true, function (err, rsp) {
if (rsp) {
resolve(conn);
} else if (err.err) {
logic(scope, 'server-not-great', { why: 'no UIDL' });
reject('pop-server-not-great');
} else {
reject(rsp.err);
}
});
}
});
});
return promise.then(function (conn) {
logic(scope, 'success');
return {
conn: conn,
timezoneOffset: null
};
}).catch(function (err) {
err = normalizePop3Error(err);
logic(scope, 'error', { error: err });
if (conn) {
conn.close();
}
return Promise.reject(err);
});
};
var GMAIL_POP_DISABLED_RE = /\[SYS\/PERM\] Your account is not enabled for POP/;
var GMAIL_DOMAIN_DISABLED_RE = /\[SYS\/PERM\] POP access is disabled for your domain\./;
function analyzePop3LibraryError(err) {
if (!err || !err.name) {
return null;
}
if (err.name === 'bad-user-or-pass' && err.message && GMAIL_POP_DISABLED_RE.test(err.message)) {
return 'pop3-disabled';
} else if (err.name === 'bad-user-or-pass' && err.message && GMAIL_DOMAIN_DISABLED_RE.test(err.message)) {
return 'pop3-disabled';
} else if (err.name === 'unresponsive-server' && err.exception && err.exception.name && /security/i.test(err.exception.name)) {
return 'bad-security';
} else if ((err.name === 'unresponsive-server' || err.name === 'bad-user-or-pass') && err.message && /\[(LOGIN-DELAY|SYS|IN-USE)/i.test(err.message)) {
return 'server-maintenance';
} else {
return err.name;
}
}
var normalizePop3Error = exports.normalizePop3Error = function (err) {
var reportAs = analyzePop3LibraryError(err) || errorutils.analyzeException(err) || 'unknown';
logic(scope, 'normalized-error', {
error: err,
reportAs: reportAs
});
return reportAs;
};
});

View file

@ -0,0 +1,15 @@
(function () {
function setZeroTimeout(fn) {
setTimeout(fn);
}
window.setZeroTimeout = setZeroTimeout;
window.process = {
immediate: false,
nextTick: function (cb) {
if (this.immediate)
cb();
else
window.setZeroTimeout(cb);
}
};
}());

View file

@ -0,0 +1,52 @@
define([
'logic',
'./client',
'exports'
], function (logic, client, exports) {
var scope = logic.scope('SmtpProber');
exports.probeAccount = function (credentials, connInfo) {
logic(scope, 'connecting', {
_credentials: credentials,
connInfo: connInfo
});
var conn;
return client.createSmtpConnection(credentials, connInfo, function onCredentialsUpdated() {
logic(scope, 'credentials-updated');
}).then(function (newConn) {
conn = newConn;
return verifyAddress(conn, connInfo.emailAddress);
}).then(function () {
logic(scope, 'success');
conn.close();
return conn;
}).catch(function (err) {
var errorString = client.analyzeSmtpError(conn, err, false);
if (conn) {
conn.close();
}
logic(scope, 'error', {
error: errorString,
connInfo: connInfo
});
throw errorString;
});
};
function verifyAddress(conn, emailAddress) {
logic(scope, 'checking-address-validity', {
ns: 'SmtpProber',
_address: emailAddress
});
return new Promise(function (resolve, reject) {
conn.useEnvelope({
from: emailAddress,
to: [emailAddress]
});
conn.onready = function () {
resolve();
};
conn.onerror = function (err) {
reject(err);
};
});
}
});

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
(function () {
function setZeroTimeout(fn) {
setTimeout(fn);
}
window.setZeroTimeout = setZeroTimeout;
}());

View file

@ -0,0 +1,166 @@
define([
'./main-router',
'./configparser-main',
'./cronsync-main',
'./devicestorage-main',
'./maildb-main',
'./net-main',
'../mailapi',
'exports'
], function ($router, $configparser, $cronsync, $devicestorage, $maildb, $net, $mailapi, exports) {
var realisticBridge = {
name: 'bridge',
sendMessage: null,
process: function (uid, cmd, args) {
bouncedBridge.sendMessage(uid, cmd, args);
}
};
var bouncedBridge = {
name: 'bounced-bridge',
sendMessage: null,
process: function (uid, cmd, args) {
realisticBridge.sendMessage(uid, cmd, args);
}
};
$router.register(realisticBridge);
$router.register(bouncedBridge);
var gMailAPI = null;
var testHelper = {
name: 'testhelper',
sendMessage: null,
process: function (uid, cmd, args) {
if (cmd === 'create-mailapi') {
gMailAPI = new $mailapi.MailAPI();
gMailAPI.__bridgeSend = function (msg) {
mainBridge.sendMessage(null, null, msg);
};
} else if (cmd === 'runWithBody') {
try {
var func;
eval('func = ' + args.func + ';');
gMailAPI._getBodyForMessage({
id: args.headerId,
date: args.headerDate
}, null, function (body) {
console.log('got body, invoking func!');
try {
func(args.arg, body, function (results) {
testHelper.sendMessage(uid, cmd, [results]);
body.die();
});
} catch (ex) {
console.error('problem in runWithBody func', ex, '\n', ex.stack);
}
});
} catch (ex) {
console.error('problem with runWithBody', ex, '\n', ex.stack);
}
} else if (cmd === 'checkDatabaseDoesNotContain') {
var tablesAndKeyPrefixes = args;
var idb = $maildb._debugDB._db, desiredStores = [], i, checkArgs;
for (i = 0; i < tablesAndKeyPrefixes.length; i++) {
checkArgs = tablesAndKeyPrefixes[i];
desiredStores.push(checkArgs.table);
}
var trans = idb.transaction(desiredStores, 'readonly');
var results = [];
var sendResults = function () {
testHelper.sendMessage(uid, 'checkDatabaseDoesNotContain', [results]);
};
var waitCount = tablesAndKeyPrefixes.length;
tablesAndKeyPrefixes.forEach(function (checkArgs) {
var store = trans.objectStore(checkArgs.table), range = IDBKeyRange.bound(checkArgs.prefix, checkArgs.prefix + '\uFFF0', false, false), req = store.get(range);
req.onerror = function (event) {
results.push({ errCode: event.target.errorCode });
if (--waitCount === 0)
sendResults();
};
req.onsuccess = function () {
results.push({
errCode: null,
table: checkArgs.table,
prefix: checkArgs.prefix,
hasResult: req.result !== undefined
});
if (--waitCount === 0)
sendResults();
};
});
} else if (cmd === 'startFakeServer') {
}
}
};
$router.register(testHelper);
var mainBridge = {
name: 'main-bridge',
sendMessage: null,
process: function (uid, cmd, args) {
if (gMailAPI)
gMailAPI.__bridgeReceive(args);
}
};
$router.register(mainBridge);
var deviceStorageTestHelper = {
name: 'th_devicestorage',
sendMessage: null,
process: function (uid, cmd, args) {
if (cmd === 'attach') {
this._storage = navigator.getDeviceStorage(args);
this._storage.addEventListener('change', this._bound_onChange);
this.sendMessage(null, 'attached', null);
} else if (cmd === 'detach') {
var detachCount = 1, self = this;
function nextDetach(path, result) {
if (path) {
console.log('devicestorage:', path, result);
}
if (--detachCount > 0) {
return;
}
console.log('devicestorage: detach cleanup completed');
self._storage.removeEventListener('change', self._bound_onChange);
self._storage = null;
self.sendMessage(null, 'detached', null);
}
args.nuke.forEach(function (path) {
detachCount++;
var req = self._storage.delete(path);
req.onsuccess = nextDetach.bind(null, path, 'success');
req.onerror = nextDetach.bind(null, path, 'error');
});
nextDetach();
} else if (cmd === 'get') {
var req = this._storage.get(args.path);
req.onsuccess = function () {
this.sendMessage(null, 'got', {
id: args.id,
error: null,
blob: req.result
});
}.bind(this);
req.onerror = function () {
this.sendMessage(null, 'got', {
id: args.id,
error: '' + req.error,
blob: null
});
}.bind(this);
}
},
_storage: null,
_bound_onChange: null,
_onChange: function (event) {
this.sendMessage(null, 'change', {
reason: event.reason,
path: event.path
});
}
};
deviceStorageTestHelper._bound_onChange = deviceStorageTestHelper._onChange.bind(deviceStorageTestHelper);
$router.register(deviceStorageTestHelper);
$router.register($configparser);
$router.register($cronsync);
$router.register($devicestorage);
$router.register($maildb);
$router.register($net);
});