Version in base suite: 4.11-1
Base version: eas4tbsync_4.11-1
Target version: eas4tbsync_4.17-1~deb13u1
Base file: /srv/ftp-master.debian.org/ftp/pool/main/e/eas4tbsync/eas4tbsync_4.11-1.dsc
Target file: /srv/ftp-master.debian.org/policy/pool/main/e/eas4tbsync/eas4tbsync_4.17-1~deb13u1.dsc
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/screenshots/AddEASAccount.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/screenshots/autodiscover.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/screenshots/install.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/screenshots/options.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/cape.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/catman.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/discon.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/help.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/old2_sync16.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/old2_sync16_r.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/old_sync16.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/settings.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/slider-off.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/slider-on.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/sync.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/syncsmall.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/t3_sync16.png |binary
/srv/release.debian.org/tmp/3hr8AaymMg/eas4tbsync-4.17/unused/icons/t3_sync16_r.png |binary
eas4tbsync-4.17/.github/issue_template.md | 16
eas4tbsync-4.17/CONTRIBUTORS.md | 39
eas4tbsync-4.17/LICENSE | 746 +-
eas4tbsync-4.17/Makebeta | 34
eas4tbsync-4.17/Makefile | 25
eas4tbsync-4.17/Makefile.bat | 9
eas4tbsync-4.17/README.md | 46
eas4tbsync-4.17/_locales/Readme.txt | 16
eas4tbsync-4.17/_locales/bg/messages.json | 1132 +--
eas4tbsync-4.17/_locales/cs/messages.json | 1132 +--
eas4tbsync-4.17/_locales/de/messages.json | 1132 +--
eas4tbsync-4.17/_locales/en-US/messages.json | 1132 +--
eas4tbsync-4.17/_locales/es/messages.json | 1132 +--
eas4tbsync-4.17/_locales/fr/messages.json | 1132 +--
eas4tbsync-4.17/_locales/gl/messages.json | 1132 +--
eas4tbsync-4.17/_locales/hu/messages.json | 1132 +--
eas4tbsync-4.17/_locales/it/messages.json | 1132 +--
eas4tbsync-4.17/_locales/ja/messages.json | 1132 +--
eas4tbsync-4.17/_locales/pl/messages.json | 1132 +--
eas4tbsync-4.17/_locales/pt_BR/messages.json | 1132 +--
eas4tbsync-4.17/_locales/ro/messages.json | 1132 +--
eas4tbsync-4.17/_locales/ru/messages.json | 1132 +--
eas4tbsync-4.17/api/EAS4TbSync/implementation.js | 74
eas4tbsync-4.17/api/EAS4TbSync/schema.json | 13
eas4tbsync-4.17/api/LegacyHelper/README.md | 50
eas4tbsync-4.17/api/LegacyHelper/implementation.js | 118
eas4tbsync-4.17/api/LegacyHelper/schema.json | 42
eas4tbsync-4.17/background.js | 11
eas4tbsync-4.17/beta-release-channel-update.json | 13
eas4tbsync-4.17/content/api/BootstrapLoader/CHANGELOG.md | 75
eas4tbsync-4.17/content/api/BootstrapLoader/README.md | 1
eas4tbsync-4.17/content/api/BootstrapLoader/implementation.js | 187
eas4tbsync-4.17/content/api/BootstrapLoader/schema.json | 61
eas4tbsync-4.17/content/bootstrap.js | 53
eas4tbsync-4.17/content/includes/calendarsync.js | 852 +-
eas4tbsync-4.17/content/includes/contactsync.js | 1109 +--
eas4tbsync-4.17/content/includes/network.js | 3150 +++++-----
eas4tbsync-4.17/content/includes/sync.js | 3015 ++++-----
eas4tbsync-4.17/content/includes/tasksync.js | 429 -
eas4tbsync-4.17/content/includes/tools.js | 1083 +--
eas4tbsync-4.17/content/includes/wbxmltools.js | 1766 ++---
eas4tbsync-4.17/content/includes/xmltools.js | 322 -
eas4tbsync-4.17/content/locales.js | 15
eas4tbsync-4.17/content/manager/createAccount.js | 517 -
eas4tbsync-4.17/content/manager/createAccount.xhtml | 194
eas4tbsync-4.17/content/manager/editAccountOverlay.js | 112
eas4tbsync-4.17/content/manager/editAccountOverlay.xhtml | 308
eas4tbsync-4.17/content/provider.js | 1477 ++--
eas4tbsync-4.17/content/skin/365.svg | 22
eas4tbsync-4.17/content/skin/fieldset.css | 12
eas4tbsync-4.17/content/timezonedata/Aliases.csv | 230
eas4tbsync-4.17/content/timezonedata/README | 8
eas4tbsync-4.17/content/timezonedata/WindowsTimezone.csv | 1028 +--
eas4tbsync-4.17/crowdin.yml | 5
eas4tbsync-4.17/debian/changelog | 28
eas4tbsync-4.17/debian/control | 8
eas4tbsync-4.17/debian/copyright | 4
eas4tbsync-4.17/debian/dpb.conf | 18
eas4tbsync-4.17/debian/gbp.conf | 7
eas4tbsync-4.17/debian/watch | 6
eas4tbsync-4.17/manifest.json | 79
79 files changed, 16654 insertions(+), 16627 deletions(-)
diff -Nru eas4tbsync-4.11/.github/issue_template.md eas4tbsync-4.17/.github/issue_template.md
--- eas4tbsync-4.11/.github/issue_template.md 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/.github/issue_template.md 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-## Your environment
-
-TbSync version:
-EAS-4-TbSync version:
-Thunderbird version:
-
-## Expected behavior
-...
-
-## Actual behavior
-...
-
-## Steps to reproduce
-...
-
-To help resolving your issue, enable debug logging (TbSync Account Manager -> Help) and send me the debug.log via e-mail (use the title of your issue as subject of the email).
diff -Nru eas4tbsync-4.11/CONTRIBUTORS.md eas4tbsync-4.17/CONTRIBUTORS.md
--- eas4tbsync-4.11/CONTRIBUTORS.md 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/CONTRIBUTORS.md 2025-07-28 17:36:48.000000000 +0000
@@ -1,19 +1,20 @@
-## Creator
-* John Bieling
-
-## Contributors
-* Chris Allan (recurring events)
-* John Bieling
-* Emil Ljungdahl
-* Mark Nethersole (initial implementation of contact sync)
-* Dzamo Norton
-* Puran2
-* Tijuca
-
-## Translators
-* John Bieling (de, en-US)
-* Wanderlei Hüttel (pt-BR)
-* Alessandro Menti (it)
-* Óvári (hu)
-* Alexey Sinitsyn (ru)
-* Daniel Wróblewski (pl)
+## Creator
+* John Bieling
+
+## Contributors
+* Chris Allan (recurring events)
+* John Bieling
+* Emil Ljungdahl
+* Mark Nethersole (initial implementation of contact sync)
+* Dzamo Norton
+* Puran2
+* Tijuca
+* Kabe2007
+
+## Translators
+* John Bieling (de, en-US)
+* Wanderlei Hüttel (pt-BR)
+* Alessandro Menti (it)
+* Óvári (hu)
+* Alexey Sinitsyn (ru)
+* Daniel Wróblewski (pl)
diff -Nru eas4tbsync-4.11/LICENSE eas4tbsync-4.17/LICENSE
--- eas4tbsync-4.11/LICENSE 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/LICENSE 2019-05-17 21:11:12.000000000 +0000
@@ -1,373 +1,373 @@
-Mozilla Public License Version 2.0
-==================================
-
-1. Definitions
---------------
-
-1.1. "Contributor"
- means each individual or legal entity that creates, contributes to
- the creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
- means the combination of the Contributions of others (if any) used
- by a Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
- means Source Code Form to which the initial Contributor has attached
- the notice in Exhibit A, the Executable Form of such Source Code
- Form, and Modifications of such Source Code Form, in each case
- including portions thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- (a) that the initial Contributor has attached the notice described
- in Exhibit B to the Covered Software; or
-
- (b) that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the
- terms of a Secondary License.
-
-1.6. "Executable Form"
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
- means a work that combines Covered Software with other material, in
- a separate file or files, that is not Covered Software.
-
-1.8. "License"
- means this document.
-
-1.9. "Licensable"
- means having the right to grant, to the maximum extent possible,
- whether at the time of the initial grant or subsequently, any and
- all of the rights conveyed by this License.
-
-1.10. "Modifications"
- means any of the following:
-
- (a) any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered
- Software; or
-
- (b) any new file in Source Code Form that contains any Covered
- Software.
-
-1.11. "Patent Claims" of a Contributor
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the
- License, by the making, using, selling, offering for sale, having
- made, import, or transfer of either its Contributions or its
- Contributor Version.
-
-1.12. "Secondary License"
- means either the GNU General Public License, Version 2.0, the GNU
- Lesser General Public License, Version 2.1, the GNU Affero General
- Public License, Version 3.0, or any later versions of those
- licenses.
-
-1.13. "Source Code Form"
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that
- controls, is controlled by, or is under common control with You. For
- purposes of this definition, "control" means (a) the power, direct
- or indirect, to cause the direction or management of such entity,
- whether by contract or otherwise, or (b) ownership of more than
- fifty percent (50%) of the outstanding shares or beneficial
- ownership of such entity.
-
-2. License Grants and Conditions
---------------------------------
-
-2.1. Grants
-
-Each Contributor hereby grants You a world-wide, royalty-free,
-non-exclusive license:
-
-(a) under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
-(b) under Patent Claims of such Contributor to make, use, sell, offer
- for sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-The licenses granted in Section 2.1 with respect to any Contribution
-become effective for each Contribution on the date the Contributor first
-distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-The licenses granted in this Section 2 are the only rights granted under
-this License. No additional rights or licenses will be implied from the
-distribution or licensing of Covered Software under this License.
-Notwithstanding Section 2.1(b) above, no patent license is granted by a
-Contributor:
-
-(a) for any code that a Contributor has removed from Covered Software;
- or
-
-(b) for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
-(c) under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
-This License does not grant any rights in the trademarks, service marks,
-or logos of any Contributor (except as may be necessary to comply with
-the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-No Contributor makes additional grants as a result of Your choice to
-distribute the Covered Software under a subsequent version of this
-License (see Section 10.2) or under the terms of a Secondary License (if
-permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-Each Contributor represents that the Contributor believes its
-Contributions are its original creation(s) or it has sufficient rights
-to grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-This License is not intended to limit any rights You have under
-applicable copyright doctrines of fair use, fair dealing, or other
-equivalents.
-
-2.7. Conditions
-
-Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-in Section 2.1.
-
-3. Responsibilities
--------------------
-
-3.1. Distribution of Source Form
-
-All distribution of Covered Software in Source Code Form, including any
-Modifications that You create or to which You contribute, must be under
-the terms of this License. You must inform recipients that the Source
-Code Form of the Covered Software is governed by the terms of this
-License, and how they can obtain a copy of this License. You may not
-attempt to alter or restrict the recipients' rights in the Source Code
-Form.
-
-3.2. Distribution of Executable Form
-
-If You distribute Covered Software in Executable Form then:
-
-(a) such Covered Software must also be made available in Source Code
- Form, as described in Section 3.1, and You must inform recipients of
- the Executable Form how they can obtain a copy of such Source Code
- Form by reasonable means in a timely manner, at a charge no more
- than the cost of distribution to the recipient; and
-
-(b) You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter
- the recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-You may create and distribute a Larger Work under terms of Your choice,
-provided that You also comply with the requirements of this License for
-the Covered Software. If the Larger Work is a combination of Covered
-Software with a work governed by one or more Secondary Licenses, and the
-Covered Software is not Incompatible With Secondary Licenses, this
-License permits You to additionally distribute such Covered Software
-under the terms of such Secondary License(s), so that the recipient of
-the Larger Work may, at their option, further distribute the Covered
-Software under the terms of either this License or such Secondary
-License(s).
-
-3.4. Notices
-
-You may not remove or alter the substance of any license notices
-(including copyright notices, patent notices, disclaimers of warranty,
-or limitations of liability) contained within the Source Code Form of
-the Covered Software, except that You may alter any license notices to
-the extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-You may choose to offer, and to charge a fee for, warranty, support,
-indemnity or liability obligations to one or more recipients of Covered
-Software. However, You may do so only on Your own behalf, and not on
-behalf of any Contributor. You must make it absolutely clear that any
-such warranty, support, indemnity, or liability obligation is offered by
-You alone, and You hereby agree to indemnify every Contributor for any
-liability incurred by such Contributor as a result of warranty, support,
-indemnity or liability terms You offer. You may include additional
-disclaimers of warranty and limitations of liability specific to any
-jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
----------------------------------------------------
-
-If it is impossible for You to comply with any of the terms of this
-License with respect to some or all of the Covered Software due to
-statute, judicial order, or regulation then You must: (a) comply with
-the terms of this License to the maximum extent possible; and (b)
-describe the limitations and the code they affect. Such description must
-be placed in a text file included with all distributions of the Covered
-Software under this License. Except to the extent prohibited by statute
-or regulation, such description must be sufficiently detailed for a
-recipient of ordinary skill to be able to understand it.
-
-5. Termination
---------------
-
-5.1. The rights granted under this License will terminate automatically
-if You fail to comply with any of its terms. However, if You become
-compliant, then the rights granted under this License from a particular
-Contributor are reinstated (a) provisionally, unless and until such
-Contributor explicitly and finally terminates Your grants, and (b) on an
-ongoing basis, if such Contributor fails to notify You of the
-non-compliance by some reasonable means prior to 60 days after You have
-come back into compliance. Moreover, Your grants from a particular
-Contributor are reinstated on an ongoing basis if such Contributor
-notifies You of the non-compliance by some reasonable means, this is the
-first time You have received notice of non-compliance with this License
-from such Contributor, and You become compliant prior to 30 days after
-Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-infringement claim (excluding declaratory judgment actions,
-counter-claims, and cross-claims) alleging that a Contributor Version
-directly or indirectly infringes any patent, then the rights granted to
-You by any and all Contributors for the Covered Software under Section
-2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-end user license agreements (excluding distributors and resellers) which
-have been validly granted by You or Your distributors under this License
-prior to termination shall survive termination.
-
-************************************************************************
-* *
-* 6. Disclaimer of Warranty *
-* ------------------------- *
-* *
-* Covered Software is provided under this License on an "as is" *
-* basis, without warranty of any kind, either expressed, implied, or *
-* statutory, including, without limitation, warranties that the *
-* Covered Software is free of defects, merchantable, fit for a *
-* particular purpose or non-infringing. The entire risk as to the *
-* quality and performance of the Covered Software is with You. *
-* Should any Covered Software prove defective in any respect, You *
-* (not any Contributor) assume the cost of any necessary servicing, *
-* repair, or correction. This disclaimer of warranty constitutes an *
-* essential part of this License. No use of any Covered Software is *
-* authorized under this License except under this disclaimer. *
-* *
-************************************************************************
-
-************************************************************************
-* *
-* 7. Limitation of Liability *
-* -------------------------- *
-* *
-* Under no circumstances and under no legal theory, whether tort *
-* (including negligence), contract, or otherwise, shall any *
-* Contributor, or anyone who distributes Covered Software as *
-* permitted above, be liable to You for any direct, indirect, *
-* special, incidental, or consequential damages of any character *
-* including, without limitation, damages for lost profits, loss of *
-* goodwill, work stoppage, computer failure or malfunction, or any *
-* and all other commercial damages or losses, even if such party *
-* shall have been informed of the possibility of such damages. This *
-* limitation of liability shall not apply to liability for death or *
-* personal injury resulting from such party's negligence to the *
-* extent applicable law prohibits such limitation. Some *
-* jurisdictions do not allow the exclusion or limitation of *
-* incidental or consequential damages, so this exclusion and *
-* limitation may not apply to You. *
-* *
-************************************************************************
-
-8. Litigation
--------------
-
-Any litigation relating to this License may be brought only in the
-courts of a jurisdiction where the defendant maintains its principal
-place of business and such litigation shall be governed by laws of that
-jurisdiction, without reference to its conflict-of-law provisions.
-Nothing in this Section shall prevent a party's ability to bring
-cross-claims or counter-claims.
-
-9. Miscellaneous
-----------------
-
-This License represents the complete agreement concerning the subject
-matter hereof. If any provision of this License is held to be
-unenforceable, such provision shall be reformed only to the extent
-necessary to make it enforceable. Any law or regulation which provides
-that the language of a contract shall be construed against the drafter
-shall not be used to construe this License against a Contributor.
-
-10. Versions of the License
----------------------------
-
-10.1. New Versions
-
-Mozilla Foundation is the license steward. Except as provided in Section
-10.3, no one other than the license steward has the right to modify or
-publish new versions of this License. Each version will be given a
-distinguishing version number.
-
-10.2. Effect of New Versions
-
-You may distribute the Covered Software under the terms of the version
-of the License under which You originally received the Covered Software,
-or under the terms of any subsequent version published by the license
-steward.
-
-10.3. Modified Versions
-
-If you create software not governed by this License, and you want to
-create a new license for such software, you may create and use a
-modified version of this License if you rename the license and remove
-any references to the name of the license steward (except to note that
-such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-Licenses
-
-If You choose to distribute Source Code Form that is Incompatible With
-Secondary Licenses under the terms of this version of the License, the
-notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
--------------------------------------------
-
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular
-file, then You may include the notice in a location (such as a LICENSE
-file in a relevant directory) where a recipient would be likely to look
-for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
----------------------------------------------------------
-
- This Source Code Form is "Incompatible With Secondary Licenses", as
- defined by the Mozilla Public License, v. 2.0.
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff -Nru eas4tbsync-4.11/Makebeta eas4tbsync-4.17/Makebeta
--- eas4tbsync-4.11/Makebeta 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/Makebeta 1970-01-01 00:00:00.000000000 +0000
@@ -1,34 +0,0 @@
-#!/bin/bash
-# This file is part of EAS-4-TbSync.
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# $1 link to base web server : https://tbsync.jobisoft.de/beta
-# $2 local path of base web server : /var/www/jobisoft.de/tbsync/beta
-# $3 name of XPI : EAS-4-TbSync.xpi
-
-git clean -df
-git checkout -- .
-git pull
-
-version=$(cat manifest.json | jq -r .version)
-updatefile=update-eas.json
-
-sed -i "s/%VERSION%/$version/g" "beta-release-channel-update.json"
-sed -i "s|%LINK%|$1/$3|g" "beta-release-channel-update.json"
-sed -i "s/static getApiVersion() { return \"/static getApiVersion() { return \"Beta /g" "content/provider.js"
-
-echo "Releasing version $version via beta release channel (will include updateURL)"
-sed -i "s|\"name\": \"__MSG_extensionName__\",|\"name\": \"EAS for TbSync [Beta Release Channel]\",|g" "manifest.json"
-sed -i "s|\"gecko\": {|\"gecko\": {\n \"update_url\": \"$1/$updatefile\",|g" "manifest.json"
-
-cp beta-release-channel-update.json $2/$updatefile
-
-rm -f $3
-rm -f $3.tar.gz
-zip -r $3 content _locales manifest.json background.js LICENSE CONTRIBUTORS.md
-tar cfvz $3.tar.gz content _locales manifest.json background.js LICENSE CONTRIBUTORS.md
-cp $3 $2/$3
-cp $3.tar.gz $2/$3.tar.gz
diff -Nru eas4tbsync-4.11/Makefile eas4tbsync-4.17/Makefile
--- eas4tbsync-4.11/Makefile 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-# This file is part of EAS-4-TbSync.
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-PACKAGE_NAME=EAS-4-TbSync
-
-ARCHIVE_NAME=$(PACKAGE_NAME).xpi
-
-PACKAGE_FILES= \
- content \
- _locales \
- manifest.json \
- CONTRIBUTORS.md \
- LICENSE README.md \
- background.js
-
-all: clean $(PACKAGE_FILES)
- zip -r $(ARCHIVE_NAME) $(PACKAGE_FILES)
-
-clean:
- rm -f $(ARCHIVE_NAME)
-
-.PHONY: clean
diff -Nru eas4tbsync-4.11/Makefile.bat eas4tbsync-4.17/Makefile.bat
--- eas4tbsync-4.11/Makefile.bat 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/Makefile.bat 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-@echo off
-REM This file is part of EAS-4-TbSync.
-REM
-REM This Source Code Form is subject to the terms of the Mozilla Public
-REM License, v. 2.0. If a copy of the MPL was not distributed with this
-REM file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-del EAS-4-TbSync.xpi
-"C:\Program Files\7-Zip\7zG.exe" a -tzip EAS-4-TbSync.xpi content _locales manifest.json CONTRIBUTORS.md LICENSE README.md background.js
diff -Nru eas4tbsync-4.11/README.md eas4tbsync-4.17/README.md
--- eas4tbsync-4.11/README.md 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/README.md 2019-11-30 12:30:50.000000000 +0000
@@ -1,23 +1,23 @@
-# EAS-4-TbSync
-
-This provider add-on adds Exchange ActiveSync (EAS v2.5 & v14.0) synchronization capabilities to [TbSync](https://github.com/jobisoft/TbSync/).
-
-More information can be found in the [wiki](https://github.com/jobisoft/EAS-4-TbSync/wiki/About:-Provider-for-Exchange-ActiveSync) of this repository
-
-## Want to add or fix a localization?
-To help translating this project, please visit [crowdin.com](https://crowdin.com/profile/jobisoft), where the localizations are managed. If you want to add a new language, just contact me and I will set it up.
-
-
-## External data sources
-
-* TbSync uses a [timezone mapping](https://github.com/mj1856/TimeZoneConverter/blob/master/src/TimeZoneConverter/Data/Mapping.csv.gz) provided by [Matt Johnson](https://github.com/mj1856)
-
-
-## Icon sources and attributions
-
-#### CC0 Public Domain
-* [365_*.png] by [Microsoft / Wikimedia](https://commons.wikimedia.org/w/index.php?curid=21546299), converted from [SVG to PNG](https://ezgif.com/svg-to-png)
-
-#### CC-BY 3.0
-* [eas*.png] by [FatCow Web Hosting](https://www.iconfinder.com/icons/64484/exchange_ms_icon)
-* [exchange_300.png] derived from [Microsoft Exchange Icon #270871](https://icon-library.net/icon/microsoft-exchange-icon-10.html), [resized](www.simpleimageresizer.com/)
+# EAS-4-TbSync
+
+This provider add-on adds Exchange ActiveSync (EAS v2.5 & v14.0) synchronization capabilities to [TbSync](https://github.com/jobisoft/TbSync/).
+
+More information can be found in the [wiki](https://github.com/jobisoft/EAS-4-TbSync/wiki/About:-Provider-for-Exchange-ActiveSync) of this repository
+
+## Want to add or fix a localization?
+To help translating this project, please visit [crowdin.com](https://crowdin.com/profile/jobisoft), where the localizations are managed. If you want to add a new language, just contact me and I will set it up.
+
+
+## External data sources
+
+* TbSync uses a [timezone mapping](https://github.com/mj1856/TimeZoneConverter/blob/master/src/TimeZoneConverter/Data/Mapping.csv.gz) provided by [Matt Johnson](https://github.com/mj1856)
+
+
+## Icon sources and attributions
+
+#### CC0 Public Domain
+* [365_*.png] by [Microsoft / Wikimedia](https://commons.wikimedia.org/w/index.php?curid=21546299), converted from [SVG to PNG](https://ezgif.com/svg-to-png)
+
+#### CC-BY 3.0
+* [eas*.png] by [FatCow Web Hosting](https://www.iconfinder.com/icons/64484/exchange_ms_icon)
+* [exchange_300.png] derived from [Microsoft Exchange Icon #270871](https://icon-library.net/icon/microsoft-exchange-icon-10.html), [resized](www.simpleimageresizer.com/)
diff -Nru eas4tbsync-4.11/_locales/Readme.txt eas4tbsync-4.17/_locales/Readme.txt
--- eas4tbsync-4.11/_locales/Readme.txt 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/Readme.txt 2019-09-30 15:35:10.000000000 +0000
@@ -1,8 +1,8 @@
-Want to add or fix a localization?
-
-To help translating this project, please visit
-
- https://crowdin.com/profile/jobisoft
-
-where the localizations are managed. If you want to add
-a new language, just contact me and I will set it up.
+Want to add or fix a localization?
+
+To help translating this project, please visit
+
+ https://crowdin.com/profile/jobisoft
+
+where the localizations are managed. If you want to add
+a new language, just contact me and I will set it up.
diff -Nru eas4tbsync-4.11/_locales/bg/messages.json eas4tbsync-4.17/_locales/bg/messages.json
--- eas4tbsync-4.11/_locales/bg/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/bg/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Anniversary:"
- },
- "abCard.AssistantName": {
- "message": "Assistant:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Assistant Phone:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Work Alternative Phone:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Work Fax:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Car Phone:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Work Main Phone:"
- },
- "abCard.Email3Address": {
- "message": "Alternative Email:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Home Alternative Phone:"
- },
- "abCard.ManagerName": {
- "message": "Manager:"
- },
- "abCard.MiddleName": {
- "message": "Middle name:"
- },
- "abCard.OtherAddress": {
- "message": "Address:"
- },
- "abCard.OtherCity": {
- "message": "City:"
- },
- "abCard.OtherCountry": {
- "message": "Country:"
- },
- "abCard.OtherState": {
- "message": "State:"
- },
- "abCard.OtherZip": {
- "message": "ZIP Code:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radio Phone:"
- },
- "abCard.Spouse": {
- "message": "Spouse:"
- },
- "abCard.header.eas": {
- "message": "Other Fields (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Additional home numbers:"
- },
- "abCard.header.messaging": {
- "message": "Messaging:"
- },
- "abCard.header.otheraddress": {
- "message": "Other Address (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Additional numbers:"
- },
- "abCard.header.people": {
- "message": "People:"
- },
- "abCard.header.worknumbers": {
- "message": "Additional work numbers:"
- },
- "acl.readonly": {
- "message": "Read-only server access (revert local changes)"
- },
- "acl.readwrite": {
- "message": "Read from and write to server"
- },
- "add.description": {
- "message": "Please select one of the available server configuration options and enter the requested details. "
- },
- "add.name": {
- "message": "Account name:"
- },
- "add.ok": {
- "message": "Add account"
- },
- "add.password": {
- "message": "Password:"
- },
- "add.server": {
- "message": "Server configuration:"
- },
- "add.shortdescription": {
- "message": "Account information"
- },
- "add.title": {
- "message": "Adding an Exchange ActiveSync account to TbSync"
- },
- "add.url": {
- "message": "Server address:"
- },
- "add.urldescription": {
- "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "User name (email address):"
- },
- "autocomplete.serverdirectory": {
- "message": "global server directory"
- },
- "autodiscover.Failed": {
- "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "Autodiscover needs a valid email address as user name."
- },
- "autodiscover.Ok": {
- "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
- },
- "autodiscover.Querying": {
- "message": "Searching for settings…"
- },
- "config.auto": {
- "message": "ActiveSync server configuration (Autodiscover)"
- },
- "config.custom": {
- "message": "ActiveSync server configuration"
- },
- "deletefolder.confirm": {
- "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
- },
- "deletefolder.menuentry": {
- "message": "Permanently purge folder “##replace.1##” from trash"
- },
- "deletefolder.notallowed": {
- "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
- },
- "extensionDescription": {
- "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
- },
- "extensionName": {
- "message": "Provider for Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Account settings"
- },
- "manager.tabs.outOfOffice": {
- "message": "Auto responder"
- },
- "manager.tabs.syncsettings": {
- "message": "Options"
- },
- "newaccount.add_auto": {
- "message": "Autodiscover settings and add account"
- },
- "newaccount.add_custom": {
- "message": "Add account"
- },
- "pref.AccountName": {
- "message": "Description"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync version"
- },
- "pref.DeviceId": {
- "message": "ActiveSync device ID"
- },
- "pref.ServerName": {
- "message": "Server address"
- },
- "pref.ServerNameDescription": {
- "message": "e.g. mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Show folders found in trash"
- },
- "pref.UserName": {
- "message": "User name"
- },
- "pref.UserNameDescription": {
- "message": "User name is usually the email address of your account."
- },
- "pref.autodetect": {
- "message": "best available"
- },
- "pref.birthday": {
- "message": "Send birthday information"
- },
- "pref.calendaroptions": {
- "message": "Calendar options"
- },
- "pref.contactoptions": {
- "message": "Contact options"
- },
- "pref.displayoverride": {
- "message": "Override Display Name with “First Name” + “Second Name”"
- },
- "pref.generaloptions": {
- "message": "General options"
- },
- "pref.provision": {
- "message": "Enforce provisioning (required by Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Comma"
- },
- "pref.seperator.description": {
- "message": "Separator for multiline address field."
- },
- "pref.seperator.linebreak": {
- "message": "Line break"
- },
- "pref.synclimit.1month": {
- "message": "from 4 weeks ago"
- },
- "pref.synclimit.2weeks": {
- "message": "from 2 weeks ago"
- },
- "pref.synclimit.3month": {
- "message": "from 3 months ago"
- },
- "pref.synclimit.6month": {
- "message": "from 6 months ago"
- },
- "pref.synclimit.all": {
- "message": "everything"
- },
- "pref.synclimit.description": {
- "message": "Synchronization period: "
- },
- "pref.usehttps": {
- "message": "Use secure connection (connect via https)"
- },
- "recyclebin": {
- "message": "Trash"
- },
- "servertype.auto": {
- "message": "Automatic configuration"
- },
- "servertype.custom": {
- "message": "Custom configuration"
- },
- "servertype.description.auto": {
- "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
- },
- "servertype.description.custom": {
- "message": "Setup your account by manually providing the address of the server you want to connect."
- },
- "servertype.description.office365": {
- "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Double click to unlock all predefined server settings."
- },
- "status.401": {
- "message": "Could not authenticate, check username and password (HTTP Error 401)."
- },
- "status.403": {
- "message": "Server rejected connection (forbidden) (HTTP Error 403)."
- },
- "status.404": {
- "message": "User not found (HTTP Error 404)."
- },
- "status.449": {
- "message": "Server requests provisioning (HTTP Error 449)."
- },
- "status.500": {
- "message": "Unknown Server Error (HTTP Error 500)."
- },
- "status.503": {
- "message": "Service unavailable (HTTP Error 503)."
- },
- "status.BadItemSkipped": {
- "message": "Bad Item Skipped: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Cannot delete a system folder (status 3)"
- },
- "status.FolderDelete.4": {
- "message": "Folder does not exist (status 4), resyncing"
- },
- "status.FolderDelete.6": {
- "message": "Command could not be completed, an error occurred on the server (status 6)"
- },
- "status.FolderDelete.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.FolderSync.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.InvalidServerOptions": {
- "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "The EAS Server rejected the last request."
- },
- "status.ServerRejectedSomeItems": {
- "message": "The EAS server did not accept ##replace.1## elements."
- },
- "status.Sync.12": {
- "message": "Folder hierarchy changed (status 12), resyncing"
- },
- "status.Sync.3": {
- "message": "Invalid synchronization key (status 3), resyncing"
- },
- "status.Sync.4": {
- "message": "Malformed request (status 4)"
- },
- "status.Sync.5": {
- "message": "Temporary server issues or invalid item (status 5)"
- },
- "status.Sync.6": {
- "message": "Invalid item (status 6)"
- },
- "status.Sync.8": {
- "message": "Object not found (status 8)"
- },
- "status.aborted": {
- "message": "Not synchronized"
- },
- "status.disabled": {
- "message": "Disabled"
- },
- "status.empty-response": {
- "message": "Server sends unexpected empty response."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Forbidden calendar item in a task folder (please resort)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Forbidden task item in a calendar folder (please resort)"
- },
- "status.global.101": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
- },
- "status.global.102": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
- },
- "status.global.103": {
- "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
- },
- "status.global.110": {
- "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
- },
- "status.global.clientdenied": {
- "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
- },
- "status.httperror": {
- "message": "Communication error (HTTP status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Invalid server response (junk)."
- },
- "status.malformed-xml": {
- "message": "Could not parse XML. Check event log for details."
- },
- "status.modified": {
- "message": "Local modifications"
- },
- "status.network": {
- "message": "Could not connect to server (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Could not connect to server."
- },
- "status.nosupportedeasversion": {
- "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
- },
- "status.notargets": {
- "message": "Aborting Sync, because sync targets could not be created."
- },
- "status.notsupportedeasversion": {
- "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Account needs to be synchronized, at least one item is out of sync."
- },
- "status.nouserhost": {
- "message": "Missing username and/or server. Please provide those values."
- },
- "status.pending": {
- "message": "Waiting to be synchronized"
- },
- "status.policy.2": {
- "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.3": {
- "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.4": {
- "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.5": {
- "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
- },
- "status.provision": {
- "message": "Provisioning failed with status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Response from the server contains no data."
- },
- "status.resync-loop": {
- "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
- },
- "status.security": {
- "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Not yet supported, skipped"
- },
- "status.syncing": {
- "message": "Synchronizing"
- },
- "status.timeout": {
- "message": "Communication timeout."
- },
- "status.wbxml-parse-error": {
- "message": "Server sends unreadable response."
- },
- "status.wbxmlerror": {
- "message": "Sync failed. Server responded with status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
- },
- "syncstate.accountdone": {
- "message": "Finished account"
- },
- "syncstate.done": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Processing updated server settings"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Folder deleted"
- },
- "syncstate.eval.response.estimate": {
- "message": "Processing change estimate"
- },
- "syncstate.eval.response.folders": {
- "message": "Processing folder list update"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Processing acknowledgment of local changes"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Processing acknowledgment of local deletes"
- },
- "syncstate.eval.response.options": {
- "message": "Processing server options"
- },
- "syncstate.eval.response.provision": {
- "message": "Processing provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Processing remote changes"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Reverting local changes"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.eval.response.synckey": {
- "message": "Processing SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Requesting updated server settings"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparing to delete folder"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Requesting change estimate"
- },
- "syncstate.prepare.request.folders": {
- "message": "Sending folder list update"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Sending local changes"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Sending local deletes"
- },
- "syncstate.prepare.request.options": {
- "message": "Requesting server options"
- },
- "syncstate.prepare.request.provision": {
- "message": "Requesting provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Requesting remote changes"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Collecting local changes"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Requesting SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Waiting for updated server settings"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Waiting for folder to be deleted"
- },
- "syncstate.send.request.estimate": {
- "message": "Waiting for change estimate"
- },
- "syncstate.send.request.folders": {
- "message": "Waiting for folder list update"
- },
- "syncstate.send.request.localchanges": {
- "message": "Waiting for acknowledgment of local changes"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Waiting for acknowledgment of local deletes"
- },
- "syncstate.send.request.options": {
- "message": "Waiting for server options"
- },
- "syncstate.send.request.provision": {
- "message": "Waiting for provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Waiting for remote changes"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Waiting for most recent versions"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.send.request.synckey": {
- "message": "Waiting for SyncKey"
- },
- "syncstate.syncing": {
- "message": "Initialize synchronization"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Anniversary:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistant:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Assistant Phone:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Work Alternative Phone:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Work Fax:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Car Phone:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Work Main Phone:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternative Email:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Home Alternative Phone:"
+ },
+ "abCard.ManagerName": {
+ "message": "Manager:"
+ },
+ "abCard.MiddleName": {
+ "message": "Middle name:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Address:"
+ },
+ "abCard.OtherCity": {
+ "message": "City:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Country:"
+ },
+ "abCard.OtherState": {
+ "message": "State:"
+ },
+ "abCard.OtherZip": {
+ "message": "ZIP Code:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radio Phone:"
+ },
+ "abCard.Spouse": {
+ "message": "Spouse:"
+ },
+ "abCard.header.eas": {
+ "message": "Other Fields (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Additional home numbers:"
+ },
+ "abCard.header.messaging": {
+ "message": "Messaging:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Other Address (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Additional numbers:"
+ },
+ "abCard.header.people": {
+ "message": "People:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Additional work numbers:"
+ },
+ "acl.readonly": {
+ "message": "Read-only server access (revert local changes)"
+ },
+ "acl.readwrite": {
+ "message": "Read from and write to server"
+ },
+ "add.description": {
+ "message": "Please select one of the available server configuration options and enter the requested details. "
+ },
+ "add.name": {
+ "message": "Account name:"
+ },
+ "add.ok": {
+ "message": "Add account"
+ },
+ "add.password": {
+ "message": "Password:"
+ },
+ "add.server": {
+ "message": "Server configuration:"
+ },
+ "add.shortdescription": {
+ "message": "Account information"
+ },
+ "add.title": {
+ "message": "Adding an Exchange ActiveSync account to TbSync"
+ },
+ "add.url": {
+ "message": "Server address:"
+ },
+ "add.urldescription": {
+ "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "User name (email address):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "global server directory"
+ },
+ "autodiscover.Failed": {
+ "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Autodiscover needs a valid email address as user name."
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
+ },
+ "autodiscover.Querying": {
+ "message": "Searching for settings…"
+ },
+ "config.auto": {
+ "message": "ActiveSync server configuration (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "ActiveSync server configuration"
+ },
+ "deletefolder.confirm": {
+ "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Permanently purge folder “##replace.1##” from trash"
+ },
+ "deletefolder.notallowed": {
+ "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
+ },
+ "extensionDescription": {
+ "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
+ },
+ "extensionName": {
+ "message": "Provider for Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Account settings"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Auto responder"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Options"
+ },
+ "newaccount.add_auto": {
+ "message": "Autodiscover settings and add account"
+ },
+ "newaccount.add_custom": {
+ "message": "Add account"
+ },
+ "pref.AccountName": {
+ "message": "Description"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync version"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync device ID"
+ },
+ "pref.ServerName": {
+ "message": "Server address"
+ },
+ "pref.ServerNameDescription": {
+ "message": "e.g. mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Show folders found in trash"
+ },
+ "pref.UserName": {
+ "message": "User name"
+ },
+ "pref.UserNameDescription": {
+ "message": "User name is usually the email address of your account."
+ },
+ "pref.autodetect": {
+ "message": "best available"
+ },
+ "pref.birthday": {
+ "message": "Send birthday information"
+ },
+ "pref.calendaroptions": {
+ "message": "Calendar options"
+ },
+ "pref.contactoptions": {
+ "message": "Contact options"
+ },
+ "pref.displayoverride": {
+ "message": "Override Display Name with “First Name” + “Second Name”"
+ },
+ "pref.generaloptions": {
+ "message": "General options"
+ },
+ "pref.provision": {
+ "message": "Enforce provisioning (required by Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Comma"
+ },
+ "pref.seperator.description": {
+ "message": "Separator for multiline address field."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Line break"
+ },
+ "pref.synclimit.1month": {
+ "message": "from 4 weeks ago"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "from 2 weeks ago"
+ },
+ "pref.synclimit.3month": {
+ "message": "from 3 months ago"
+ },
+ "pref.synclimit.6month": {
+ "message": "from 6 months ago"
+ },
+ "pref.synclimit.all": {
+ "message": "everything"
+ },
+ "pref.synclimit.description": {
+ "message": "Synchronization period: "
+ },
+ "pref.usehttps": {
+ "message": "Use secure connection (connect via https)"
+ },
+ "recyclebin": {
+ "message": "Trash"
+ },
+ "servertype.auto": {
+ "message": "Automatic configuration"
+ },
+ "servertype.custom": {
+ "message": "Custom configuration"
+ },
+ "servertype.description.auto": {
+ "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
+ },
+ "servertype.description.custom": {
+ "message": "Setup your account by manually providing the address of the server you want to connect."
+ },
+ "servertype.description.office365": {
+ "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Double click to unlock all predefined server settings."
+ },
+ "status.401": {
+ "message": "Could not authenticate, check username and password (HTTP Error 401)."
+ },
+ "status.403": {
+ "message": "Server rejected connection (forbidden) (HTTP Error 403)."
+ },
+ "status.404": {
+ "message": "User not found (HTTP Error 404)."
+ },
+ "status.449": {
+ "message": "Server requests provisioning (HTTP Error 449)."
+ },
+ "status.500": {
+ "message": "Unknown Server Error (HTTP Error 500)."
+ },
+ "status.503": {
+ "message": "Service unavailable (HTTP Error 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Bad Item Skipped: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Cannot delete a system folder (status 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Folder does not exist (status 4), resyncing"
+ },
+ "status.FolderDelete.6": {
+ "message": "Command could not be completed, an error occurred on the server (status 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.FolderSync.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.InvalidServerOptions": {
+ "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "The EAS Server rejected the last request."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "The EAS server did not accept ##replace.1## elements."
+ },
+ "status.Sync.12": {
+ "message": "Folder hierarchy changed (status 12), resyncing"
+ },
+ "status.Sync.3": {
+ "message": "Invalid synchronization key (status 3), resyncing"
+ },
+ "status.Sync.4": {
+ "message": "Malformed request (status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Temporary server issues or invalid item (status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Invalid item (status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Object not found (status 8)"
+ },
+ "status.aborted": {
+ "message": "Not synchronized"
+ },
+ "status.disabled": {
+ "message": "Disabled"
+ },
+ "status.empty-response": {
+ "message": "Server sends unexpected empty response."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Forbidden calendar item in a task folder (please resort)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Forbidden task item in a calendar folder (please resort)"
+ },
+ "status.global.101": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
+ },
+ "status.global.102": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
+ },
+ "status.global.103": {
+ "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
+ },
+ "status.global.110": {
+ "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
+ },
+ "status.httperror": {
+ "message": "Communication error (HTTP status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Invalid server response (junk)."
+ },
+ "status.malformed-xml": {
+ "message": "Could not parse XML. Check event log for details."
+ },
+ "status.modified": {
+ "message": "Local modifications"
+ },
+ "status.network": {
+ "message": "Could not connect to server (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Could not connect to server."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
+ },
+ "status.notargets": {
+ "message": "Aborting Sync, because sync targets could not be created."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Account needs to be synchronized, at least one item is out of sync."
+ },
+ "status.nouserhost": {
+ "message": "Missing username and/or server. Please provide those values."
+ },
+ "status.pending": {
+ "message": "Waiting to be synchronized"
+ },
+ "status.policy.2": {
+ "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.3": {
+ "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.4": {
+ "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.5": {
+ "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.provision": {
+ "message": "Provisioning failed with status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Response from the server contains no data."
+ },
+ "status.resync-loop": {
+ "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
+ },
+ "status.security": {
+ "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Not yet supported, skipped"
+ },
+ "status.syncing": {
+ "message": "Synchronizing"
+ },
+ "status.timeout": {
+ "message": "Communication timeout."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Server sends unreadable response."
+ },
+ "status.wbxmlerror": {
+ "message": "Sync failed. Server responded with status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
+ },
+ "syncstate.accountdone": {
+ "message": "Finished account"
+ },
+ "syncstate.done": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Processing updated server settings"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Folder deleted"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Processing change estimate"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Processing folder list update"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Processing acknowledgment of local changes"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Processing acknowledgment of local deletes"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Processing server options"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Processing provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Processing remote changes"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Reverting local changes"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Processing SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Requesting updated server settings"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparing to delete folder"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Requesting change estimate"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Sending folder list update"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Sending local changes"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Sending local deletes"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Requesting server options"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Requesting provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Requesting remote changes"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Collecting local changes"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Requesting SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Waiting for updated server settings"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Waiting for folder to be deleted"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Waiting for change estimate"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Waiting for folder list update"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Waiting for acknowledgment of local changes"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Waiting for acknowledgment of local deletes"
+ },
+ "syncstate.send.request.options": {
+ "message": "Waiting for server options"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Waiting for provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Waiting for remote changes"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Waiting for most recent versions"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Waiting for SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Initialize synchronization"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/cs/messages.json eas4tbsync-4.17/_locales/cs/messages.json
--- eas4tbsync-4.11/_locales/cs/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/cs/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Výročí:"
- },
- "abCard.AssistantName": {
- "message": "Asistent:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Telefon asistenta:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Alternativní telefon do práce:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax do práce:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Telefon do auta:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Hlavní pracovní telefon:"
- },
- "abCard.Email3Address": {
- "message": "Alternativní e-mail:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Alternativní telefon domů:"
- },
- "abCard.ManagerName": {
- "message": "Manažer:"
- },
- "abCard.MiddleName": {
- "message": "Prostřední jméno:"
- },
- "abCard.OtherAddress": {
- "message": "Adresa:"
- },
- "abCard.OtherCity": {
- "message": "Město:"
- },
- "abCard.OtherCountry": {
- "message": "Země:"
- },
- "abCard.OtherState": {
- "message": "Stát:"
- },
- "abCard.OtherZip": {
- "message": "PSČ:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radiotelefon:"
- },
- "abCard.Spouse": {
- "message": "Manžel(ka):"
- },
- "abCard.header.eas": {
- "message": "Další údaje (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Další čísla domů:"
- },
- "abCard.header.messaging": {
- "message": "Zprávy:"
- },
- "abCard.header.otheraddress": {
- "message": "Další adresa (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Další čísla:"
- },
- "abCard.header.people": {
- "message": "Lidé:"
- },
- "abCard.header.worknumbers": {
- "message": "Další čísla do práce:"
- },
- "acl.readonly": {
- "message": "Přistup na server pouze pro čtení (odstranit místní změny)"
- },
- "acl.readwrite": {
- "message": "Přístup na server pro čtení i zápis"
- },
- "add.description": {
- "message": "Vyberte prosím jednu z dostupných možností konfigurace serveru a zadejte požadované podrobnosti. "
- },
- "add.name": {
- "message": "Název účtu:"
- },
- "add.ok": {
- "message": "Přidat účet"
- },
- "add.password": {
- "message": "Heslo:"
- },
- "add.server": {
- "message": "Nastavení serveru:"
- },
- "add.shortdescription": {
- "message": "Informace o účtu"
- },
- "add.title": {
- "message": "Přidání nového účtu Exchange ActiveSync do TbSync"
- },
- "add.url": {
- "message": "Adresa serveru:"
- },
- "add.urldescription": {
- "message": "Mělo by stačit zadat pouze adresu serveru (např. mail.mujmail.cz). Nicméně můžete zadat i celou URL (např. https://mail.mujmail.cz/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Uživatelské jméno (e-mailová adresa):"
- },
- "autocomplete.serverdirectory": {
- "message": "globální adresář serveru"
- },
- "autodiscover.Failed": {
- "message": "Automatické nastavení pro uživatele <##user##> selhalo. Buď nejsou zadané přihlašovací údaje správné, nebo má váš poskytovatel ActiveSync dočasný problém, anebo nepodporuje automatické nastavení."
- },
- "autodiscover.NeedEmail": {
- "message": "Funkce automatického nastavení Autodiscover vyžaduje zadání platné e-mailové adresy jako uživatelského jména."
- },
- "autodiscover.Ok": {
- "message": "Automatické nastavení bylo úspěšně dokončeno. Nyní si můžete projít volitelné nastavení a vytvořit synchronizační připojení."
- },
- "autodiscover.Querying": {
- "message": "Hledám nastavení…"
- },
- "config.auto": {
- "message": "Konfigurace serveru ActiveSync (Autodiscover)"
- },
- "config.custom": {
- "message": "Konfigurace serveru ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "Opravdu chcete z koše TRVALE vymazat složku “##replace.1##”?"
- },
- "deletefolder.menuentry": {
- "message": "Trvale z koše vymazat složku “##replace.1##”"
- },
- "deletefolder.notallowed": {
- "message": "Prosím, odhlašte odběr složky “##replace.1##“ předtím, než se ji pokusíte odstranit z koše."
- },
- "extensionDescription": {
- "message": "Přidává do TbSync podporu synchronizace pro účty Exchange ActiveSync (kontakty, úkoly a kalendáře)."
- },
- "extensionName": {
- "message": "Modul poskytovatele pro Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Nastavení účtu"
- },
- "manager.tabs.outOfOffice": {
- "message": "Automatická odpověď"
- },
- "manager.tabs.syncsettings": {
- "message": "Volby"
- },
- "newaccount.add_auto": {
- "message": "Vyhledat nastavení a přidat účet"
- },
- "newaccount.add_custom": {
- "message": "Přidat účet"
- },
- "pref.AccountName": {
- "message": "Pojmenování"
- },
- "pref.ActiveSyncVersion": {
- "message": "Verze ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID zařízení ActiveSync"
- },
- "pref.ServerName": {
- "message": "Adresa serveru"
- },
- "pref.ServerNameDescription": {
- "message": "např. mail.mujmail.cz"
- },
- "pref.ShowTrashedFolders": {
- "message": "Zobrazit složky nalezené v koši"
- },
- "pref.UserName": {
- "message": "Uživatelské jméno"
- },
- "pref.UserNameDescription": {
- "message": "Uživatelské jméno je obvykle e-mailová adresa vašeho účtu."
- },
- "pref.autodetect": {
- "message": "nejlepší možná"
- },
- "pref.birthday": {
- "message": "Odeslat informace o narozeninách"
- },
- "pref.calendaroptions": {
- "message": "Nastavení kalendáře"
- },
- "pref.contactoptions": {
- "message": "Kontakty"
- },
- "pref.displayoverride": {
- "message": "Vynutit zobrazování jména jako “křestní” + “příjmení”"
- },
- "pref.generaloptions": {
- "message": "Obecné"
- },
- "pref.provision": {
- "message": "Vynutit provisioning (vyžaduje Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Čárka"
- },
- "pref.seperator.description": {
- "message": "Oddělovač pro víceřádkové pole adres."
- },
- "pref.seperator.linebreak": {
- "message": "Nový řádek"
- },
- "pref.synclimit.1month": {
- "message": "poslední 4 týdny"
- },
- "pref.synclimit.2weeks": {
- "message": "poslední 2 týdny"
- },
- "pref.synclimit.3month": {
- "message": "poslední 3 měsíce"
- },
- "pref.synclimit.6month": {
- "message": "posledních 6 měsíců"
- },
- "pref.synclimit.all": {
- "message": "vše"
- },
- "pref.synclimit.description": {
- "message": "Období pro synchronizaci: "
- },
- "pref.usehttps": {
- "message": "Použít zabezpečené připojení (přes https)"
- },
- "recyclebin": {
- "message": "Koš"
- },
- "servertype.auto": {
- "message": "Automatické nastavení pomocí ActiveSync Autodiscover"
- },
- "servertype.custom": {
- "message": "Ruční nastavení"
- },
- "servertype.description.auto": {
- "message": "Pro nastavení většiny ActiveSync serverů stačí zadat pouze e-mailovou adresu."
- },
- "servertype.description.custom": {
- "message": "Nastavte si účet pomocí ručního zadání adresy serveru."
- },
- "servertype.description.office365": {
- "message": "Účty Office 365 používají moderní proces ověřování s názvem OAuth 2.0, který také podporuje vícefaktorové ověřování (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Dvojklikem odemknete všechna předdefinovaná nastavení serveru."
- },
- "status.401": {
- "message": "Chyba ověření, zkontrolujte uživatelské jméno a heslo (HTTP chyba 401)."
- },
- "status.403": {
- "message": "Server odmítl spojení (HTTP chyba 403)."
- },
- "status.404": {
- "message": "Uživatel nebyl nalezen (HTTP chyba 404)."
- },
- "status.449": {
- "message": "Server si vyžádal provisioning (HTTP chyba 449)."
- },
- "status.500": {
- "message": "Neznámá chyba serveru (HTTP chyba 500)."
- },
- "status.503": {
- "message": "Služba není dostupná (HTTP chyba 503)."
- },
- "status.BadItemSkipped": {
- "message": "Vynechána chybná položka: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Systémovou složku nelze odstranit (status 3)"
- },
- "status.FolderDelete.4": {
- "message": "Složka neexistuje (status 4), opětovně synchronizuji"
- },
- "status.FolderDelete.6": {
- "message": "Příkaz nemohl být dokončen, došlo k chybě na serveru (status 6)"
- },
- "status.FolderDelete.9": {
- "message": "Neplatný synchronizační klíč (status 9), opětovně synchronizuji"
- },
- "status.FolderSync.9": {
- "message": "Neplatný synchronizační klíč (status 9), opětovně synchronizuji"
- },
- "status.InvalidServerOptions": {
- "message": "Server neposkytuje informaci o podporovaných verzích ActiveSync. Je pro tohoto uživatele nebo tohoto klienta (TbSync) EAS blokován? Můžete zkusit nastavit verzi ActiveSync ručně."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "EAS Server poslední požadavek odmítl."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Server EAS nepřijal ##replace.1## položek."
- },
- "status.Sync.12": {
- "message": "Změnila se struktura složky (status 12), opětovně synchronizuji"
- },
- "status.Sync.3": {
- "message": "Neplatný synchronizační klíč (status 3), opětovně synchronizuji"
- },
- "status.Sync.4": {
- "message": "Chybný požadavek (status 4)"
- },
- "status.Sync.5": {
- "message": "Dočasné potíže na serveru nebo neplatná položka (status 5)"
- },
- "status.Sync.6": {
- "message": "Neplatná položka (status 6)"
- },
- "status.Sync.8": {
- "message": "Objekt nebyl nalezen (status 8)"
- },
- "status.aborted": {
- "message": "Není synchronizováno"
- },
- "status.disabled": {
- "message": "Zakázáno"
- },
- "status.empty-response": {
- "message": "Server zaslal odpověď bez obsahu."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "V seznamu úkolů máte uložený záznam, který má patřit do kalendáře (prosím, přesuňte jej)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "V kalendáři máte uložený záznam, který má patřit mezi úkoly (prosím, přesuňte jej)"
- },
- "status.global.101": {
- "message": "Požadavek obsahuje WBXML, ale nemohl být dekódován do XML (EAS chyba 101)."
- },
- "status.global.102": {
- "message": "Požadavek obsahuje WBXML, ale nemohl být dekódován do XML (EAS chyba 102)."
- },
- "status.global.103": {
- "message": "Poskytnuté XML data neodpovídají požadavkům protokolu (EAS chyba 103)."
- },
- "status.global.110": {
- "message": "Server nahlásil interní chybu, automatická synchronizace byla pozastavena na 30 minut (EAS chyba 110)."
- },
- "status.global.clientdenied": {
- "message": "EAS server nahlásil <##replace.2##> (status ##replace.1##) a nepovolil pro TbSync přístup k účtu."
- },
- "status.httperror": {
- "message": "Chyba komunikace (HTTP status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Neplatná odpověď serveru."
- },
- "status.malformed-xml": {
- "message": "Nelze zpracovat XML. Podrobnosti naleznete v protokolu událostí."
- },
- "status.modified": {
- "message": "Místní změny"
- },
- "status.network": {
- "message": "Nelze se připojit k serveru (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Nelze se připojit k serveru."
- },
- "status.nosupportedeasversion": {
- "message": "Server nepodporuje ActiveSync v2.5 nebo v14.0 (pouze ##replace.1##). TbSync nepodporuje tento typ ActiveSync serveru."
- },
- "status.notargets": {
- "message": "Synchronizace byla přerušena, protože nebylo možné vytvořit cíle pro synchronizaci."
- },
- "status.notsupportedeasversion": {
- "message": "Server nepodporuje vybranou verzi ActiveSync v##replace.1## (pouze ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Účet musí být synchronizován, alespoň jedna položka není synchronizována."
- },
- "status.nouserhost": {
- "message": "Uživatel a/nebo server nebyl zadán. Prosím, doplňte chybějící hodnoty."
- },
- "status.pending": {
- "message": "Čeká se na synchronizaci"
- },
- "status.policy.2": {
- "message": "Chybí zásady pro tohoto klienta. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
- },
- "status.policy.3": {
- "message": "Neznámá hodnota PolicyType. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
- },
- "status.policy.4": {
- "message": "Data zásad na serveru jsou porušená. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
- },
- "status.policy.5": {
- "message": "Klient přijal špatný klíč zásad. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
- },
- "status.provision": {
- "message": "Provisioning skončil chybou <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Odpověď serveru neobsahovala data."
- },
- "status.resync-loop": {
- "message": "Nastala chyba, kterou není možné napravit pouze opětovnou synchronizací. Prosím, zakažte tento účet a zkuste to znovu. (Chyba: zacyklená synchronizace)"
- },
- "status.security": {
- "message": "Nelze navázat zabezpečené spojení. Používáte samopodepsaný nebo jinak nedůvěryhodný certifikát, aniž byste jej importovali do Thunderbirdu? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Ještě není podporováno, přeskočeno"
- },
- "status.syncing": {
- "message": "Probíhá synchronizace"
- },
- "status.timeout": {
- "message": "Časový limit komunikace vypršel."
- },
- "status.wbxml-parse-error": {
- "message": "Odpověď serveru byla nečitelná."
- },
- "status.wbxmlerror": {
- "message": "Chyba synchronizace. Server hlásí status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Porušení protokolu ActiveSync: Vyžadované pole <##replace.1##> v odpovědi serveru chybí."
- },
- "syncstate.accountdone": {
- "message": "Synchronizace účtu dokončena"
- },
- "syncstate.done": {
- "message": "Příprava další položky na synchronizaci"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Zpracovávám aktualizované nastavení serveru"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Složka smazána"
- },
- "syncstate.eval.response.estimate": {
- "message": "Zpracovávám změnu odhadu"
- },
- "syncstate.eval.response.folders": {
- "message": "Zpracovávám aktualizaci seznamu složek"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Zpracovávám potvrzení místních změn"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Zpracovávám potvrzení místních výmazů"
- },
- "syncstate.eval.response.options": {
- "message": "Zpracovávám možnosti serveru"
- },
- "syncstate.eval.response.provision": {
- "message": "Zpracovávám provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Zpracovávám změny ze serveru"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Vracím zpět místní změny"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Odesílám informace o zařízení"
- },
- "syncstate.eval.response.synckey": {
- "message": "Zpracovávám SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Žádám o aktualizované nastavení serveru"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Připravuji vymazání složky"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Žádám o změnu odhadu"
- },
- "syncstate.prepare.request.folders": {
- "message": "Odesílám aktualizaci seznamu složek"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Odesílám místní změny"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Odesílám místní výmazy"
- },
- "syncstate.prepare.request.options": {
- "message": "Posílám požadavek na zaslání možností serveru"
- },
- "syncstate.prepare.request.provision": {
- "message": "Žádám o provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Žádám o změny na serveru"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Shromažďuji místní změny"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Odesílám informace o zařízení"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Žádám o SyncKey"
- },
- "syncstate.preparing": {
- "message": "Příprava další položky na synchronizaci"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Čekám na aktualizované nastavení serveru"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Čekám na vymazání složky"
- },
- "syncstate.send.request.estimate": {
- "message": "Čekám na změnu odhadu"
- },
- "syncstate.send.request.folders": {
- "message": "Čekám na aktualizaci seznamu složek"
- },
- "syncstate.send.request.localchanges": {
- "message": "Čekám na potvrzení místních změn"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Čekám na potvrzení místních výmazů"
- },
- "syncstate.send.request.options": {
- "message": "Čekám na možnosti serveru"
- },
- "syncstate.send.request.provision": {
- "message": "Čekám na provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Čekám na změny ze serveru"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Čekám na nejnovější verze"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Odesílám informace o zařízení"
- },
- "syncstate.send.request.synckey": {
- "message": "Čekám na SyncKey"
- },
- "syncstate.syncing": {
- "message": "Inicializuji synchronizaci"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Výročí:"
+ },
+ "abCard.AssistantName": {
+ "message": "Asistent:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Telefon asistenta:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Alternativní telefon do práce:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax do práce:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Telefon do auta:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Hlavní pracovní telefon:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternativní e-mail:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Alternativní telefon domů:"
+ },
+ "abCard.ManagerName": {
+ "message": "Manažer:"
+ },
+ "abCard.MiddleName": {
+ "message": "Prostřední jméno:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Adresa:"
+ },
+ "abCard.OtherCity": {
+ "message": "Město:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Země:"
+ },
+ "abCard.OtherState": {
+ "message": "Stát:"
+ },
+ "abCard.OtherZip": {
+ "message": "PSČ:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radiotelefon:"
+ },
+ "abCard.Spouse": {
+ "message": "Manžel(ka):"
+ },
+ "abCard.header.eas": {
+ "message": "Další údaje (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Další čísla domů:"
+ },
+ "abCard.header.messaging": {
+ "message": "Zprávy:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Další adresa (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Další čísla:"
+ },
+ "abCard.header.people": {
+ "message": "Lidé:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Další čísla do práce:"
+ },
+ "acl.readonly": {
+ "message": "Přistup na server pouze pro čtení (odstranit místní změny)"
+ },
+ "acl.readwrite": {
+ "message": "Přístup na server pro čtení i zápis"
+ },
+ "add.description": {
+ "message": "Vyberte prosím jednu z dostupných možností konfigurace serveru a zadejte požadované podrobnosti. "
+ },
+ "add.name": {
+ "message": "Název účtu:"
+ },
+ "add.ok": {
+ "message": "Přidat účet"
+ },
+ "add.password": {
+ "message": "Heslo:"
+ },
+ "add.server": {
+ "message": "Nastavení serveru:"
+ },
+ "add.shortdescription": {
+ "message": "Informace o účtu"
+ },
+ "add.title": {
+ "message": "Přidání nového účtu Exchange ActiveSync do TbSync"
+ },
+ "add.url": {
+ "message": "Adresa serveru:"
+ },
+ "add.urldescription": {
+ "message": "Mělo by stačit zadat pouze adresu serveru (např. mail.mujmail.cz). Nicméně můžete zadat i celou URL (např. https://mail.mujmail.cz/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Uživatelské jméno (e-mailová adresa):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "globální adresář serveru"
+ },
+ "autodiscover.Failed": {
+ "message": "Automatické nastavení pro uživatele <##user##> selhalo. Buď nejsou zadané přihlašovací údaje správné, nebo má váš poskytovatel ActiveSync dočasný problém, anebo nepodporuje automatické nastavení."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Funkce automatického nastavení Autodiscover vyžaduje zadání platné e-mailové adresy jako uživatelského jména."
+ },
+ "autodiscover.Ok": {
+ "message": "Automatické nastavení bylo úspěšně dokončeno. Nyní si můžete projít volitelné nastavení a vytvořit synchronizační připojení."
+ },
+ "autodiscover.Querying": {
+ "message": "Hledám nastavení…"
+ },
+ "config.auto": {
+ "message": "Konfigurace serveru ActiveSync (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "Konfigurace serveru ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "Opravdu chcete z koše TRVALE vymazat složku “##replace.1##”?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Trvale z koše vymazat složku “##replace.1##”"
+ },
+ "deletefolder.notallowed": {
+ "message": "Prosím, odhlašte odběr složky “##replace.1##“ předtím, než se ji pokusíte odstranit z koše."
+ },
+ "extensionDescription": {
+ "message": "Přidává do TbSync podporu synchronizace pro účty Exchange ActiveSync (kontakty, úkoly a kalendáře)."
+ },
+ "extensionName": {
+ "message": "Modul poskytovatele pro Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Nastavení účtu"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Automatická odpověď"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Volby"
+ },
+ "newaccount.add_auto": {
+ "message": "Vyhledat nastavení a přidat účet"
+ },
+ "newaccount.add_custom": {
+ "message": "Přidat účet"
+ },
+ "pref.AccountName": {
+ "message": "Pojmenování"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Verze ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID zařízení ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Adresa serveru"
+ },
+ "pref.ServerNameDescription": {
+ "message": "např. mail.mujmail.cz"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Zobrazit složky nalezené v koši"
+ },
+ "pref.UserName": {
+ "message": "Uživatelské jméno"
+ },
+ "pref.UserNameDescription": {
+ "message": "Uživatelské jméno je obvykle e-mailová adresa vašeho účtu."
+ },
+ "pref.autodetect": {
+ "message": "nejlepší možná"
+ },
+ "pref.birthday": {
+ "message": "Odeslat informace o narozeninách"
+ },
+ "pref.calendaroptions": {
+ "message": "Nastavení kalendáře"
+ },
+ "pref.contactoptions": {
+ "message": "Kontakty"
+ },
+ "pref.displayoverride": {
+ "message": "Vynutit zobrazování jména jako “křestní” + “příjmení”"
+ },
+ "pref.generaloptions": {
+ "message": "Obecné"
+ },
+ "pref.provision": {
+ "message": "Vynutit provisioning (vyžaduje Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Čárka"
+ },
+ "pref.seperator.description": {
+ "message": "Oddělovač pro víceřádkové pole adres."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Nový řádek"
+ },
+ "pref.synclimit.1month": {
+ "message": "poslední 4 týdny"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "poslední 2 týdny"
+ },
+ "pref.synclimit.3month": {
+ "message": "poslední 3 měsíce"
+ },
+ "pref.synclimit.6month": {
+ "message": "posledních 6 měsíců"
+ },
+ "pref.synclimit.all": {
+ "message": "vše"
+ },
+ "pref.synclimit.description": {
+ "message": "Období pro synchronizaci: "
+ },
+ "pref.usehttps": {
+ "message": "Použít zabezpečené připojení (přes https)"
+ },
+ "recyclebin": {
+ "message": "Koš"
+ },
+ "servertype.auto": {
+ "message": "Automatické nastavení pomocí ActiveSync Autodiscover"
+ },
+ "servertype.custom": {
+ "message": "Ruční nastavení"
+ },
+ "servertype.description.auto": {
+ "message": "Pro nastavení většiny ActiveSync serverů stačí zadat pouze e-mailovou adresu."
+ },
+ "servertype.description.custom": {
+ "message": "Nastavte si účet pomocí ručního zadání adresy serveru."
+ },
+ "servertype.description.office365": {
+ "message": "Účty Office 365 používají moderní proces ověřování s názvem OAuth 2.0, který také podporuje vícefaktorové ověřování (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Dvojklikem odemknete všechna předdefinovaná nastavení serveru."
+ },
+ "status.401": {
+ "message": "Chyba ověření, zkontrolujte uživatelské jméno a heslo (HTTP chyba 401)."
+ },
+ "status.403": {
+ "message": "Server odmítl spojení (HTTP chyba 403)."
+ },
+ "status.404": {
+ "message": "Uživatel nebyl nalezen (HTTP chyba 404)."
+ },
+ "status.449": {
+ "message": "Server si vyžádal provisioning (HTTP chyba 449)."
+ },
+ "status.500": {
+ "message": "Neznámá chyba serveru (HTTP chyba 500)."
+ },
+ "status.503": {
+ "message": "Služba není dostupná (HTTP chyba 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Vynechána chybná položka: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Systémovou složku nelze odstranit (status 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Složka neexistuje (status 4), opětovně synchronizuji"
+ },
+ "status.FolderDelete.6": {
+ "message": "Příkaz nemohl být dokončen, došlo k chybě na serveru (status 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Neplatný synchronizační klíč (status 9), opětovně synchronizuji"
+ },
+ "status.FolderSync.9": {
+ "message": "Neplatný synchronizační klíč (status 9), opětovně synchronizuji"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Server neposkytuje informaci o podporovaných verzích ActiveSync. Je pro tohoto uživatele nebo tohoto klienta (TbSync) EAS blokován? Můžete zkusit nastavit verzi ActiveSync ručně."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "EAS Server poslední požadavek odmítl."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Server EAS nepřijal ##replace.1## položek."
+ },
+ "status.Sync.12": {
+ "message": "Změnila se struktura složky (status 12), opětovně synchronizuji"
+ },
+ "status.Sync.3": {
+ "message": "Neplatný synchronizační klíč (status 3), opětovně synchronizuji"
+ },
+ "status.Sync.4": {
+ "message": "Chybný požadavek (status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Dočasné potíže na serveru nebo neplatná položka (status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Neplatná položka (status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Objekt nebyl nalezen (status 8)"
+ },
+ "status.aborted": {
+ "message": "Není synchronizováno"
+ },
+ "status.disabled": {
+ "message": "Zakázáno"
+ },
+ "status.empty-response": {
+ "message": "Server zaslal odpověď bez obsahu."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "V seznamu úkolů máte uložený záznam, který má patřit do kalendáře (prosím, přesuňte jej)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "V kalendáři máte uložený záznam, který má patřit mezi úkoly (prosím, přesuňte jej)"
+ },
+ "status.global.101": {
+ "message": "Požadavek obsahuje WBXML, ale nemohl být dekódován do XML (EAS chyba 101)."
+ },
+ "status.global.102": {
+ "message": "Požadavek obsahuje WBXML, ale nemohl být dekódován do XML (EAS chyba 102)."
+ },
+ "status.global.103": {
+ "message": "Poskytnuté XML data neodpovídají požadavkům protokolu (EAS chyba 103)."
+ },
+ "status.global.110": {
+ "message": "Server nahlásil interní chybu, automatická synchronizace byla pozastavena na 30 minut (EAS chyba 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "EAS server nahlásil <##replace.2##> (status ##replace.1##) a nepovolil pro TbSync přístup k účtu."
+ },
+ "status.httperror": {
+ "message": "Chyba komunikace (HTTP status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Neplatná odpověď serveru."
+ },
+ "status.malformed-xml": {
+ "message": "Nelze zpracovat XML. Podrobnosti naleznete v protokolu událostí."
+ },
+ "status.modified": {
+ "message": "Místní změny"
+ },
+ "status.network": {
+ "message": "Nelze se připojit k serveru (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Nelze se připojit k serveru."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Server nepodporuje ActiveSync v2.5 nebo v14.0 (pouze ##replace.1##). TbSync nepodporuje tento typ ActiveSync serveru."
+ },
+ "status.notargets": {
+ "message": "Synchronizace byla přerušena, protože nebylo možné vytvořit cíle pro synchronizaci."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Server nepodporuje vybranou verzi ActiveSync v##replace.1## (pouze ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Účet musí být synchronizován, alespoň jedna položka není synchronizována."
+ },
+ "status.nouserhost": {
+ "message": "Uživatel a/nebo server nebyl zadán. Prosím, doplňte chybějící hodnoty."
+ },
+ "status.pending": {
+ "message": "Čeká se na synchronizaci"
+ },
+ "status.policy.2": {
+ "message": "Chybí zásady pro tohoto klienta. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
+ },
+ "status.policy.3": {
+ "message": "Neznámá hodnota PolicyType. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
+ },
+ "status.policy.4": {
+ "message": "Data zásad na serveru jsou porušená. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
+ },
+ "status.policy.5": {
+ "message": "Klient přijal špatný klíč zásad. Kontaktujte administrátora nebo zakažte provisioning pro tento účet."
+ },
+ "status.provision": {
+ "message": "Provisioning skončil chybou <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Odpověď serveru neobsahovala data."
+ },
+ "status.resync-loop": {
+ "message": "Nastala chyba, kterou není možné napravit pouze opětovnou synchronizací. Prosím, zakažte tento účet a zkuste to znovu. (Chyba: zacyklená synchronizace)"
+ },
+ "status.security": {
+ "message": "Nelze navázat zabezpečené spojení. Používáte samopodepsaný nebo jinak nedůvěryhodný certifikát, aniž byste jej importovali do Thunderbirdu? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Ještě není podporováno, přeskočeno"
+ },
+ "status.syncing": {
+ "message": "Probíhá synchronizace"
+ },
+ "status.timeout": {
+ "message": "Časový limit komunikace vypršel."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Odpověď serveru byla nečitelná."
+ },
+ "status.wbxmlerror": {
+ "message": "Chyba synchronizace. Server hlásí status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Porušení protokolu ActiveSync: Vyžadované pole <##replace.1##> v odpovědi serveru chybí."
+ },
+ "syncstate.accountdone": {
+ "message": "Synchronizace účtu dokončena"
+ },
+ "syncstate.done": {
+ "message": "Příprava další položky na synchronizaci"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Zpracovávám aktualizované nastavení serveru"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Složka smazána"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Zpracovávám změnu odhadu"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Zpracovávám aktualizaci seznamu složek"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Zpracovávám potvrzení místních změn"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Zpracovávám potvrzení místních výmazů"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Zpracovávám možnosti serveru"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Zpracovávám provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Zpracovávám změny ze serveru"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Vracím zpět místní změny"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Odesílám informace o zařízení"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Zpracovávám SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Žádám o aktualizované nastavení serveru"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Připravuji vymazání složky"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Žádám o změnu odhadu"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Odesílám aktualizaci seznamu složek"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Odesílám místní změny"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Odesílám místní výmazy"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Posílám požadavek na zaslání možností serveru"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Žádám o provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Žádám o změny na serveru"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Shromažďuji místní změny"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Odesílám informace o zařízení"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Žádám o SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Příprava další položky na synchronizaci"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Čekám na aktualizované nastavení serveru"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Čekám na vymazání složky"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Čekám na změnu odhadu"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Čekám na aktualizaci seznamu složek"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Čekám na potvrzení místních změn"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Čekám na potvrzení místních výmazů"
+ },
+ "syncstate.send.request.options": {
+ "message": "Čekám na možnosti serveru"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Čekám na provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Čekám na změny ze serveru"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Čekám na nejnovější verze"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Odesílám informace o zařízení"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Čekám na SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Inicializuji synchronizaci"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/de/messages.json eas4tbsync-4.17/_locales/de/messages.json
--- eas4tbsync-4.11/_locales/de/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/de/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Jubiläum:"
- },
- "abCard.AssistantName": {
- "message": "Assistent:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Assistententelefon:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Telefon 2 Arbeit:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax Arbeit:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Telefon Auto:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Haupttelefon Arbeit:"
- },
- "abCard.Email3Address": {
- "message": "Alternative E-Mail:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Telefon 2 zu Hause:"
- },
- "abCard.ManagerName": {
- "message": "Manager:"
- },
- "abCard.MiddleName": {
- "message": "Zweiter Vorname:"
- },
- "abCard.OtherAddress": {
- "message": "Adresse:"
- },
- "abCard.OtherCity": {
- "message": "Stadt:"
- },
- "abCard.OtherCountry": {
- "message": "Land:"
- },
- "abCard.OtherState": {
- "message": "Bundesland:"
- },
- "abCard.OtherZip": {
- "message": "Postleitzahl:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Funktelefon:"
- },
- "abCard.Spouse": {
- "message": "Ehepartner:"
- },
- "abCard.header.eas": {
- "message": "Weitere Felder (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Zusätzliche Nummern zu Hause:"
- },
- "abCard.header.messaging": {
- "message": "Nachrichten:"
- },
- "abCard.header.otheraddress": {
- "message": "Weitere Adresse (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Zusätzliche Nummern:"
- },
- "abCard.header.people": {
- "message": "Personen:"
- },
- "abCard.header.worknumbers": {
- "message": "Zusätzliche Nummern Arbeit:"
- },
- "acl.readonly": {
- "message": "Serverzugriff nur lesend (verwerfe lokale Änderungen)"
- },
- "acl.readwrite": {
- "message": "Serverzugriff lesend und schreibend"
- },
- "add.description": {
- "message": "Bitte wählen Sie eine der verfügbaren Server-Konfigurationen aus und geben Sie die angeforderten Details ein. "
- },
- "add.name": {
- "message": "Kontoname:"
- },
- "add.ok": {
- "message": "Konto hinzufügen"
- },
- "add.password": {
- "message": "Passwort:"
- },
- "add.server": {
- "message": "Server Konfiguration:"
- },
- "add.shortdescription": {
- "message": "Kontoinformationen"
- },
- "add.title": {
- "message": "Exchange ActiveSync Konto hinzufügen"
- },
- "add.url": {
- "message": "Server Adresse:"
- },
- "add.urldescription": {
- "message": "Meist reicht die Angabe der einfachen Serveradresse (z.B.: mail.meinserver.de), alternativ kann aber auch die komplette URL angegeben werden (z.B.: https://mail.meinserver.de/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Benutzername (E-Mail Adresse):"
- },
- "autocomplete.serverdirectory": {
- "message": "Globales Serververzeichnis"
- },
- "autodiscover.Failed": {
- "message": "Autodiscover für den Benutzer <##user##> war nicht erfolgreich. Entweder war das Passwort nicht korrekt, Ihr ActiveSync Server hat ein temporäres Problem oder unterstützt kein Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "Autodiscover benötigt eine gültige E-Mail Adresse als Benutzername."
- },
- "autodiscover.Ok": {
- "message": "Autodiscover war erfolgreich, Sie können nun die optionalen Einstellungen überprüfen und die Synchronisationsverbindung aktivieren."
- },
- "autodiscover.Querying": {
- "message": "Einstellungen werden gesucht ..."
- },
- "config.auto": {
- "message": "ActiveSync Server Konfiguration (Autodiscover)"
- },
- "config.custom": {
- "message": "ActiveSync Server Konfiguration"
- },
- "deletefolder.confirm": {
- "message": "Möchten Sie den Ordner '##replace.1##' wirklich ENDGÜLTIG aus dem Papierkorb ENTFERNEN?"
- },
- "deletefolder.menuentry": {
- "message": "Den Ordner '##replace.1##' endgültig aus dem Papierkorb entfernen"
- },
- "deletefolder.notallowed": {
- "message": "Bitte beenden Sie zunächst das Abonement des Ordner '##replace.1##', bevor Sie diesen aus dem Papierkorb entfernen."
- },
- "extensionDescription": {
- "message": "Erweitert TbSync und erlaubt die Synchronisation von Exchange ActiveSync Konten (Kontakte, Aufgaben und Kalender)."
- },
- "extensionName": {
- "message": "Provider für Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Kontoeinstellungen"
- },
- "manager.tabs.outOfOffice": {
- "message": "Autoresponder"
- },
- "manager.tabs.syncsettings": {
- "message": "Optionen"
- },
- "newaccount.add_auto": {
- "message": "Einstellungen suchen und Konto hinzufügen"
- },
- "newaccount.add_custom": {
- "message": "Konto hinzufügen"
- },
- "pref.AccountName": {
- "message": "Kontoname"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync Version"
- },
- "pref.DeviceId": {
- "message": "ActiveSync Geräte ID"
- },
- "pref.ServerName": {
- "message": "Server Adresse"
- },
- "pref.ServerNameDescription": {
- "message": "z.B. mail.meinserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Im Papierkorb gefundene Ordner anzeigen"
- },
- "pref.UserName": {
- "message": "Benutzername"
- },
- "pref.UserNameDescription": {
- "message": "Der Benutzername ist meistens die E-Mail Adresse Ihres Kontos."
- },
- "pref.autodetect": {
- "message": "bestmöglich"
- },
- "pref.birthday": {
- "message": "Sende Geburtstagsinformation"
- },
- "pref.calendaroptions": {
- "message": "Kalender Optionen"
- },
- "pref.contactoptions": {
- "message": "Kontakt Optionen"
- },
- "pref.displayoverride": {
- "message": "Überschreibe Anzeigename mit 'Vorname' + 'Nachname'"
- },
- "pref.generaloptions": {
- "message": "Allgemeine Optionen"
- },
- "pref.provision": {
- "message": "Provisionierung erzwingen (wird von Kerio benötigt)"
- },
- "pref.seperator.comma": {
- "message": "Komma"
- },
- "pref.seperator.description": {
- "message": "Separator für mehrzeilige Adressfelder: "
- },
- "pref.seperator.linebreak": {
- "message": "Zeilenumbruch"
- },
- "pref.synclimit.1month": {
- "message": "ab vor 4 Wochen"
- },
- "pref.synclimit.2weeks": {
- "message": "ab vor 2 Wochen"
- },
- "pref.synclimit.3month": {
- "message": "ab vor 3 Monaten"
- },
- "pref.synclimit.6month": {
- "message": "ab vor 6 Monaten"
- },
- "pref.synclimit.all": {
- "message": "alles"
- },
- "pref.synclimit.description": {
- "message": "Synchronisationszeitraum: "
- },
- "pref.usehttps": {
- "message": "Sichere Verbindungen verwenden (via https://)"
- },
- "recyclebin": {
- "message": "Papierkorb"
- },
- "servertype.auto": {
- "message": "Automatische Konfiguration"
- },
- "servertype.custom": {
- "message": "Benutzerspezifische Konfiguration"
- },
- "servertype.description.auto": {
- "message": "Die Konfiguration vieler ActiveSync Server kann allein durch die Angabe Ihrer E-Mail-Adresse erfolgen."
- },
- "servertype.description.custom": {
- "message": "Richten Sie Ihr Konto ein, indem Sie die Adresse des Servers angeben, mit dem Sie sich verbinden möchten."
- },
- "servertype.description.office365": {
- "message": "Konten, die mit Office 365 verbunden sind, verwenden den modernen OAuth 2.0 Authentifizierungsprozess, der auch Multi-Factor-Authentication (MFA) unterstützt."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Doppelklick um die vordefinierten Servereinstellungen zu entsperren."
- },
- "status.401": {
- "message": "Authentifizierung fehlgeschlagen, überprüfen Sie den Benutzernamen und das Passwort."
- },
- "status.403": {
- "message": "Verbindung vom Server abgelehnt (nicht erlaubt)."
- },
- "status.404": {
- "message": "Unbekanner Benutzer (HTTP Fehler 404)."
- },
- "status.449": {
- "message": "Server erwartet Provisionierung."
- },
- "status.500": {
- "message": "Unbekannter Server Fehler (HTTP Fehler 500)."
- },
- "status.503": {
- "message": "Service nicht erreichbar."
- },
- "status.BadItemSkipped": {
- "message": "Ein Element wurde nicht synchronisiert: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Systemordner können nicht gelöscht werden."
- },
- "status.FolderDelete.4": {
- "message": "Ordner existiert nicht, es wird neu synchronisiert"
- },
- "status.FolderDelete.6": {
- "message": "Das Kommando konnte nicht abgeschlossen werden, auf dem Server ist ein Fehler aufgetreten."
- },
- "status.FolderDelete.9": {
- "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
- },
- "status.FolderSync.9": {
- "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
- },
- "status.InvalidServerOptions": {
- "message": "Der Server sendet keine Informationen zu den unterstützten ActiveSync Versionen. Ist EAS für diesen Benutzer bzw. für dieses Programm (TbSync) freigeschaltet? Sie können versuchen, die ActiveSync Version manuell festzulegen."
- },
- "status.OK": {
- "message": "Ok"
- },
- "status.ServerRejectedRequest": {
- "message": "Der EAS Server hat die letzte Anforderung zurückgewiesen."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Der EAS Server hat ##replace.1## Elemente nicht akzeptiert."
- },
- "status.Sync.12": {
- "message": "Ordnerhierarchie hat sich geändert, es wird neu synchronisiert"
- },
- "status.Sync.3": {
- "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
- },
- "status.Sync.4": {
- "message": "Fehlerhafte Anfrage (Status 4)"
- },
- "status.Sync.5": {
- "message": "Temporäres Serverproblem oder ungültiges Element (Status 5)"
- },
- "status.Sync.6": {
- "message": "Ungültiges Element (Status 6)"
- },
- "status.Sync.8": {
- "message": "Objekt nicht gefunden (Status 8)"
- },
- "status.aborted": {
- "message": "Nicht synchronisiert"
- },
- "status.disabled": {
- "message": "Konto ist deaktiviert, Synchronisation ist ausgeschaltet."
- },
- "status.empty-response": {
- "message": "Server sendet unerwartete leere Antwort."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Unerlaubtes Kalender-Element in einem Aufgaben-Objekt (bitte umsortieren)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Unerlaubtes Aufgaben-Element in einem Kalender-Objekt (bitte umsortieren)"
- },
- "status.global.101": {
- "message": "Das WBXML der Anfrage konnte nicht in gültiges XML dekodiert werden (EAS Fehler 101)."
- },
- "status.global.102": {
- "message": "Das WBXML der Anfrage konnte nicht in gültiges XML dekodiert werden (EAS Fehler 102)."
- },
- "status.global.103": {
- "message": "Das XML der Anfrage entspricht nicht den Protokollanforderungen (EAS Fehler 103)."
- },
- "status.global.110": {
- "message": "Der Server meldet einen internen Fehler und es soll nicht unmittelbar ein erneuter Verbindungsaufbau durchgeführt werden. Die automatische periodische Synchronisation wird für 30 Minuten ausgesetzt (EAS Fehler 110)."
- },
- "status.global.clientdenied": {
- "message": "Der EAS Server antwortet mit <##replace.2##> (status ##replace.1##) und verweigert TbSync den Zugriff auf Ihr Konto."
- },
- "status.httperror": {
- "message": "Kommunikationsfehler (HTTP Status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Ungültige Serverantwort."
- },
- "status.malformed-xml": {
- "message": "Antwort enthält fehlerhaftes XML, Sync angebrochen. Prüfen Sie bitte das Ereignisprotokoll für weitere Details."
- },
- "status.modified": {
- "message": "Lokale Änderungen"
- },
- "status.network": {
- "message": "Verbindung zum Server fehlgeschlagen (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Verbindung zum Server fehlgeschlagen."
- },
- "status.nosupportedeasversion": {
- "message": "Der Server unterstützt kein ActiveSync v2.5 oder v14.0 (nur ##replace.1##). TbSync kann nicht mit diesem Server arbeiten."
- },
- "status.notargets": {
- "message": "Synchronisation abgebrochen da die Elemente zum Synchronisieren nicht erstellt werden konnten."
- },
- "status.notsupportedeasversion": {
- "message": "Der Server unterstützt nicht die ausgewählte ActiveSync Version v##replace.1## (nur ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Konto muss synchronisiert werden."
- },
- "status.nouserhost": {
- "message": "Angabe des Benutzernamens und/oder des Servers fehlt. Bitte die korrekten Informationen eintragen."
- },
- "status.pending": {
- "message": "Warten auf Synchronisation"
- },
- "status.policy.2": {
- "message": "Es gibt keine Regel (policy) für diesen Klient. Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
- },
- "status.policy.3": {
- "message": "Unbekannter Wert für den Regeltyp (policy type). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
- },
- "status.policy.4": {
- "message": "Die Daten für die Regeln auf dem Server sind beschädigt (möglicherweise manipuliert). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
- },
- "status.policy.5": {
- "message": "Der Klient bestätigt einen falschen Richtlinienschlüssel (policy key). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
- },
- "status.provision": {
- "message": "Provisionierung fehlerhaft mit folgendem Status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Antwort vom Server enthält keine Daten."
- },
- "status.resync-loop": {
- "message": "Es ist ein Fehler aufgetreten, der nicht durch wiederholtes Synchronisieren des Kontos behoben werden konnte. Bitte deaktivieren sie das Konto und wiederholen den Vorgang. (Fehler: Synchronisationsschleife)"
- },
- "status.security": {
- "message": "Fehler beim Aufbau einer sicherern Verbindung. Benutzen Sie eventuell ein selbst signiertes Zertifikat oder ein andersartiges nicht vertrauenswürdiges Zertifikat welches nicht in Thunderbird importiert ist? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Nicht unterstützt"
- },
- "status.syncing": {
- "message": "Synchronisierung"
- },
- "status.timeout": {
- "message": "Kommunikations-Timeout."
- },
- "status.wbxml-parse-error": {
- "message": "Server sendet nicht lesbare Antwort."
- },
- "status.wbxmlerror": {
- "message": "Synchronisation fehlgeschlagen. Der Server antwortete mit dem Status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Verletzung des ActiveSync Protokolls: Notwendiges Feld <##replace.1##> ist nicht in der Serverantwort enthalten."
- },
- "syncstate.accountdone": {
- "message": "Kontosynchronisation abgeschlossen"
- },
- "syncstate.done": {
- "message": "Bereite das nächste Element für die Synchronisation vor"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Verarbeite aktualisierte Servereinstellungen"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Ordner erfolgreich gelöscht"
- },
- "syncstate.eval.response.estimate": {
- "message": "Verarbeite geschätzte Änderungen"
- },
- "syncstate.eval.response.folders": {
- "message": "Verarbeite aktualisierte Ordnerliste"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Verarbeite Bestätigung der lokalen Änderungen"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Verarbeite Bestätigung lokal gelöschten Elemente"
- },
- "syncstate.eval.response.options": {
- "message": "Verarbeite aktualisierte Serveroptionen"
- },
- "syncstate.eval.response.provision": {
- "message": "Verarbeite Provisionierung"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Verarbeite aktualisierte Elemente"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Lokale Änderungen werden verworfen"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Sende Geräteinformationen"
- },
- "syncstate.eval.response.synckey": {
- "message": "Verarbeite Synchronisationsschlüssel"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Sende Anfrage bzgl. aktualisierter Servereinstellungen"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Löschen des Ordners wird vorbereitet"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Sende Anfrage bzgl. geschätzter Änderungen"
- },
- "syncstate.prepare.request.folders": {
- "message": "Sende Anfrage bzgl. aktualisierter Ordnerliste"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Sende lokale Änderungen"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Sende die lokal gelöschten Elemente"
- },
- "syncstate.prepare.request.options": {
- "message": "Sende Anfrage bzgl. aktualisierter Serveroptionen"
- },
- "syncstate.prepare.request.provision": {
- "message": "Sende Anfrage bzgl. Provisionierung"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Sende Anfrage bzgl. Änderungen"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Prüfe lokale Änderungen"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Sende Geräteinformationen"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Sende Anfrage bzgl. Synchronisationsschlüssel"
- },
- "syncstate.preparing": {
- "message": "Bereite das nächste Element für die Synchronisation vor"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Warte auf aktualisierte Servereinstellungen"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Ordner wird gelöscht"
- },
- "syncstate.send.request.estimate": {
- "message": "Warte auf geschätzte Änderungen"
- },
- "syncstate.send.request.folders": {
- "message": "Warte auf aktualisierte Ordnerliste"
- },
- "syncstate.send.request.localchanges": {
- "message": "Warte auf Bestätigung der lokalen Änderungen"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Warte auf Bestätigung lokal gelöschten Elemente"
- },
- "syncstate.send.request.options": {
- "message": "Warte auf aktualisierte Serveroptionen"
- },
- "syncstate.send.request.provision": {
- "message": "Warte auf Provisionierung"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Warte auf aktualisierte Elemente"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Warte auf aktuelle Versionen"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Sende Geräteinformationen"
- },
- "syncstate.send.request.synckey": {
- "message": "Warte auf Synchronisationsschlüssel"
- },
- "syncstate.syncing": {
- "message": "Initiiere Synchronisation"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Jubiläum:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistent:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Assistententelefon:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Telefon 2 Arbeit:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax Arbeit:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Telefon Auto:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Haupttelefon Arbeit:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternative E-Mail:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Telefon 2 zu Hause:"
+ },
+ "abCard.ManagerName": {
+ "message": "Manager:"
+ },
+ "abCard.MiddleName": {
+ "message": "Zweiter Vorname:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Adresse:"
+ },
+ "abCard.OtherCity": {
+ "message": "Stadt:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Land:"
+ },
+ "abCard.OtherState": {
+ "message": "Bundesland:"
+ },
+ "abCard.OtherZip": {
+ "message": "Postleitzahl:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Funktelefon:"
+ },
+ "abCard.Spouse": {
+ "message": "Ehepartner:"
+ },
+ "abCard.header.eas": {
+ "message": "Weitere Felder (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Zusätzliche Nummern zu Hause:"
+ },
+ "abCard.header.messaging": {
+ "message": "Nachrichten:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Weitere Adresse (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Zusätzliche Nummern:"
+ },
+ "abCard.header.people": {
+ "message": "Personen:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Zusätzliche Nummern Arbeit:"
+ },
+ "acl.readonly": {
+ "message": "Serverzugriff nur lesend (verwerfe lokale Änderungen)"
+ },
+ "acl.readwrite": {
+ "message": "Serverzugriff lesend und schreibend"
+ },
+ "add.description": {
+ "message": "Bitte wählen Sie eine der verfügbaren Server-Konfigurationen aus und geben Sie die angeforderten Details ein. "
+ },
+ "add.name": {
+ "message": "Kontoname:"
+ },
+ "add.ok": {
+ "message": "Konto hinzufügen"
+ },
+ "add.password": {
+ "message": "Passwort:"
+ },
+ "add.server": {
+ "message": "Server Konfiguration:"
+ },
+ "add.shortdescription": {
+ "message": "Kontoinformationen"
+ },
+ "add.title": {
+ "message": "Exchange ActiveSync Konto hinzufügen"
+ },
+ "add.url": {
+ "message": "Server Adresse:"
+ },
+ "add.urldescription": {
+ "message": "Meist reicht die Angabe der einfachen Serveradresse (z.B.: mail.meinserver.de), alternativ kann aber auch die komplette URL angegeben werden (z.B.: https://mail.meinserver.de/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Benutzername (E-Mail Adresse):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "Globales Serververzeichnis"
+ },
+ "autodiscover.Failed": {
+ "message": "Autodiscover für den Benutzer <##user##> war nicht erfolgreich. Entweder war das Passwort nicht korrekt, Ihr ActiveSync Server hat ein temporäres Problem oder unterstützt kein Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Autodiscover benötigt eine gültige E-Mail Adresse als Benutzername."
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover war erfolgreich, Sie können nun die optionalen Einstellungen überprüfen und die Synchronisationsverbindung aktivieren."
+ },
+ "autodiscover.Querying": {
+ "message": "Einstellungen werden gesucht ..."
+ },
+ "config.auto": {
+ "message": "ActiveSync Server Konfiguration (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "ActiveSync Server Konfiguration"
+ },
+ "deletefolder.confirm": {
+ "message": "Möchten Sie den Ordner '##replace.1##' wirklich ENDGÜLTIG aus dem Papierkorb ENTFERNEN?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Den Ordner '##replace.1##' endgültig aus dem Papierkorb entfernen"
+ },
+ "deletefolder.notallowed": {
+ "message": "Bitte beenden Sie zunächst das Abonement des Ordner '##replace.1##', bevor Sie diesen aus dem Papierkorb entfernen."
+ },
+ "extensionDescription": {
+ "message": "Erweitert TbSync und erlaubt die Synchronisation von Exchange ActiveSync Konten (Kontakte, Aufgaben und Kalender)."
+ },
+ "extensionName": {
+ "message": "Provider für Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Kontoeinstellungen"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Autoresponder"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Optionen"
+ },
+ "newaccount.add_auto": {
+ "message": "Einstellungen suchen und Konto hinzufügen"
+ },
+ "newaccount.add_custom": {
+ "message": "Konto hinzufügen"
+ },
+ "pref.AccountName": {
+ "message": "Kontoname"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync Version"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync Geräte ID"
+ },
+ "pref.ServerName": {
+ "message": "Server Adresse"
+ },
+ "pref.ServerNameDescription": {
+ "message": "z.B. mail.meinserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Im Papierkorb gefundene Ordner anzeigen"
+ },
+ "pref.UserName": {
+ "message": "Benutzername"
+ },
+ "pref.UserNameDescription": {
+ "message": "Der Benutzername ist meistens die E-Mail Adresse Ihres Kontos."
+ },
+ "pref.autodetect": {
+ "message": "bestmöglich"
+ },
+ "pref.birthday": {
+ "message": "Sende Geburtstagsinformation"
+ },
+ "pref.calendaroptions": {
+ "message": "Kalender Optionen"
+ },
+ "pref.contactoptions": {
+ "message": "Kontakt Optionen"
+ },
+ "pref.displayoverride": {
+ "message": "Überschreibe Anzeigename mit 'Vorname' + 'Nachname'"
+ },
+ "pref.generaloptions": {
+ "message": "Allgemeine Optionen"
+ },
+ "pref.provision": {
+ "message": "Provisionierung erzwingen (wird von Kerio benötigt)"
+ },
+ "pref.seperator.comma": {
+ "message": "Komma"
+ },
+ "pref.seperator.description": {
+ "message": "Separator für mehrzeilige Adressfelder: "
+ },
+ "pref.seperator.linebreak": {
+ "message": "Zeilenumbruch"
+ },
+ "pref.synclimit.1month": {
+ "message": "ab vor 4 Wochen"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "ab vor 2 Wochen"
+ },
+ "pref.synclimit.3month": {
+ "message": "ab vor 3 Monaten"
+ },
+ "pref.synclimit.6month": {
+ "message": "ab vor 6 Monaten"
+ },
+ "pref.synclimit.all": {
+ "message": "alles"
+ },
+ "pref.synclimit.description": {
+ "message": "Synchronisationszeitraum: "
+ },
+ "pref.usehttps": {
+ "message": "Sichere Verbindungen verwenden (via https://)"
+ },
+ "recyclebin": {
+ "message": "Papierkorb"
+ },
+ "servertype.auto": {
+ "message": "Automatische Konfiguration"
+ },
+ "servertype.custom": {
+ "message": "Benutzerspezifische Konfiguration"
+ },
+ "servertype.description.auto": {
+ "message": "Die Konfiguration vieler ActiveSync Server kann allein durch die Angabe Ihrer E-Mail-Adresse erfolgen."
+ },
+ "servertype.description.custom": {
+ "message": "Richten Sie Ihr Konto ein, indem Sie die Adresse des Servers angeben, mit dem Sie sich verbinden möchten."
+ },
+ "servertype.description.office365": {
+ "message": "Konten, die mit Office 365 verbunden sind, verwenden den modernen OAuth 2.0 Authentifizierungsprozess, der auch Multi-Factor-Authentication (MFA) unterstützt."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Doppelklick um die vordefinierten Servereinstellungen zu entsperren."
+ },
+ "status.401": {
+ "message": "Authentifizierung fehlgeschlagen, überprüfen Sie den Benutzernamen und das Passwort."
+ },
+ "status.403": {
+ "message": "Verbindung vom Server abgelehnt (nicht erlaubt)."
+ },
+ "status.404": {
+ "message": "Unbekanner Benutzer (HTTP Fehler 404)."
+ },
+ "status.449": {
+ "message": "Server erwartet Provisionierung."
+ },
+ "status.500": {
+ "message": "Unbekannter Server Fehler (HTTP Fehler 500)."
+ },
+ "status.503": {
+ "message": "Service nicht erreichbar."
+ },
+ "status.BadItemSkipped": {
+ "message": "Ein Element wurde nicht synchronisiert: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Systemordner können nicht gelöscht werden."
+ },
+ "status.FolderDelete.4": {
+ "message": "Ordner existiert nicht, es wird neu synchronisiert"
+ },
+ "status.FolderDelete.6": {
+ "message": "Das Kommando konnte nicht abgeschlossen werden, auf dem Server ist ein Fehler aufgetreten."
+ },
+ "status.FolderDelete.9": {
+ "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
+ },
+ "status.FolderSync.9": {
+ "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Der Server sendet keine Informationen zu den unterstützten ActiveSync Versionen. Ist EAS für diesen Benutzer bzw. für dieses Programm (TbSync) freigeschaltet? Sie können versuchen, die ActiveSync Version manuell festzulegen."
+ },
+ "status.OK": {
+ "message": "Ok"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Der EAS Server hat die letzte Anforderung zurückgewiesen."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Der EAS Server hat ##replace.1## Elemente nicht akzeptiert."
+ },
+ "status.Sync.12": {
+ "message": "Ordnerhierarchie hat sich geändert, es wird neu synchronisiert"
+ },
+ "status.Sync.3": {
+ "message": "Ungültiger Synchronisationsschlüssel, es wird neu synchronisiert"
+ },
+ "status.Sync.4": {
+ "message": "Fehlerhafte Anfrage (Status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Temporäres Serverproblem oder ungültiges Element (Status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Ungültiges Element (Status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Objekt nicht gefunden (Status 8)"
+ },
+ "status.aborted": {
+ "message": "Nicht synchronisiert"
+ },
+ "status.disabled": {
+ "message": "Konto ist deaktiviert, Synchronisation ist ausgeschaltet."
+ },
+ "status.empty-response": {
+ "message": "Server sendet unerwartete leere Antwort."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Unerlaubtes Kalender-Element in einem Aufgaben-Objekt (bitte umsortieren)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Unerlaubtes Aufgaben-Element in einem Kalender-Objekt (bitte umsortieren)"
+ },
+ "status.global.101": {
+ "message": "Das WBXML der Anfrage konnte nicht in gültiges XML dekodiert werden (EAS Fehler 101)."
+ },
+ "status.global.102": {
+ "message": "Das WBXML der Anfrage konnte nicht in gültiges XML dekodiert werden (EAS Fehler 102)."
+ },
+ "status.global.103": {
+ "message": "Das XML der Anfrage entspricht nicht den Protokollanforderungen (EAS Fehler 103)."
+ },
+ "status.global.110": {
+ "message": "Der Server meldet einen internen Fehler und es soll nicht unmittelbar ein erneuter Verbindungsaufbau durchgeführt werden. Die automatische periodische Synchronisation wird für 30 Minuten ausgesetzt (EAS Fehler 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "Der EAS Server antwortet mit <##replace.2##> (status ##replace.1##) und verweigert TbSync den Zugriff auf Ihr Konto."
+ },
+ "status.httperror": {
+ "message": "Kommunikationsfehler (HTTP Status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Ungültige Serverantwort."
+ },
+ "status.malformed-xml": {
+ "message": "Antwort enthält fehlerhaftes XML, Sync angebrochen. Prüfen Sie bitte das Ereignisprotokoll für weitere Details."
+ },
+ "status.modified": {
+ "message": "Lokale Änderungen"
+ },
+ "status.network": {
+ "message": "Verbindung zum Server fehlgeschlagen (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Verbindung zum Server fehlgeschlagen."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Der Server unterstützt kein ActiveSync v2.5 oder v14.0 (nur ##replace.1##). TbSync kann nicht mit diesem Server arbeiten."
+ },
+ "status.notargets": {
+ "message": "Synchronisation abgebrochen da die Elemente zum Synchronisieren nicht erstellt werden konnten."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Der Server unterstützt nicht die ausgewählte ActiveSync Version v##replace.1## (nur ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Konto muss synchronisiert werden."
+ },
+ "status.nouserhost": {
+ "message": "Angabe des Benutzernamens und/oder des Servers fehlt. Bitte die korrekten Informationen eintragen."
+ },
+ "status.pending": {
+ "message": "Warten auf Synchronisation"
+ },
+ "status.policy.2": {
+ "message": "Es gibt keine Regel (policy) für diesen Klient. Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
+ },
+ "status.policy.3": {
+ "message": "Unbekannter Wert für den Regeltyp (policy type). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
+ },
+ "status.policy.4": {
+ "message": "Die Daten für die Regeln auf dem Server sind beschädigt (möglicherweise manipuliert). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
+ },
+ "status.policy.5": {
+ "message": "Der Klient bestätigt einen falschen Richtlinienschlüssel (policy key). Kontaktieren Sie Ihren Server Administrator oder deaktivieren Sie die Provisionierungsoption für dieses Konto in TbSync."
+ },
+ "status.provision": {
+ "message": "Provisionierung fehlerhaft mit folgendem Status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Antwort vom Server enthält keine Daten."
+ },
+ "status.resync-loop": {
+ "message": "Es ist ein Fehler aufgetreten, der nicht durch wiederholtes Synchronisieren des Kontos behoben werden konnte. Bitte deaktivieren sie das Konto und wiederholen den Vorgang. (Fehler: Synchronisationsschleife)"
+ },
+ "status.security": {
+ "message": "Fehler beim Aufbau einer sicherern Verbindung. Benutzen Sie eventuell ein selbst signiertes Zertifikat oder ein andersartiges nicht vertrauenswürdiges Zertifikat welches nicht in Thunderbird importiert ist? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Nicht unterstützt"
+ },
+ "status.syncing": {
+ "message": "Synchronisierung"
+ },
+ "status.timeout": {
+ "message": "Kommunikations-Timeout."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Server sendet nicht lesbare Antwort."
+ },
+ "status.wbxmlerror": {
+ "message": "Synchronisation fehlgeschlagen. Der Server antwortete mit dem Status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Verletzung des ActiveSync Protokolls: Notwendiges Feld <##replace.1##> ist nicht in der Serverantwort enthalten."
+ },
+ "syncstate.accountdone": {
+ "message": "Kontosynchronisation abgeschlossen"
+ },
+ "syncstate.done": {
+ "message": "Bereite das nächste Element für die Synchronisation vor"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Verarbeite aktualisierte Servereinstellungen"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Ordner erfolgreich gelöscht"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Verarbeite geschätzte Änderungen"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Verarbeite aktualisierte Ordnerliste"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Verarbeite Bestätigung der lokalen Änderungen"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Verarbeite Bestätigung lokal gelöschten Elemente"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Verarbeite aktualisierte Serveroptionen"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Verarbeite Provisionierung"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Verarbeite aktualisierte Elemente"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Lokale Änderungen werden verworfen"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Sende Geräteinformationen"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Verarbeite Synchronisationsschlüssel"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Sende Anfrage bzgl. aktualisierter Servereinstellungen"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Löschen des Ordners wird vorbereitet"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Sende Anfrage bzgl. geschätzter Änderungen"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Sende Anfrage bzgl. aktualisierter Ordnerliste"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Sende lokale Änderungen"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Sende die lokal gelöschten Elemente"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Sende Anfrage bzgl. aktualisierter Serveroptionen"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Sende Anfrage bzgl. Provisionierung"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Sende Anfrage bzgl. Änderungen"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Prüfe lokale Änderungen"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Sende Geräteinformationen"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Sende Anfrage bzgl. Synchronisationsschlüssel"
+ },
+ "syncstate.preparing": {
+ "message": "Bereite das nächste Element für die Synchronisation vor"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Warte auf aktualisierte Servereinstellungen"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Ordner wird gelöscht"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Warte auf geschätzte Änderungen"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Warte auf aktualisierte Ordnerliste"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Warte auf Bestätigung der lokalen Änderungen"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Warte auf Bestätigung lokal gelöschten Elemente"
+ },
+ "syncstate.send.request.options": {
+ "message": "Warte auf aktualisierte Serveroptionen"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Warte auf Provisionierung"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Warte auf aktualisierte Elemente"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Warte auf aktuelle Versionen"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Sende Geräteinformationen"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Warte auf Synchronisationsschlüssel"
+ },
+ "syncstate.syncing": {
+ "message": "Initiiere Synchronisation"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/en-US/messages.json eas4tbsync-4.17/_locales/en-US/messages.json
--- eas4tbsync-4.11/_locales/en-US/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/en-US/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Anniversary:"
- },
- "abCard.AssistantName": {
- "message": "Assistant:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Assistant Phone:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Work Alternative Phone:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Work Fax:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Car Phone:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Work Main Phone:"
- },
- "abCard.Email3Address": {
- "message": "Alternative Email:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Home Alternative Phone:"
- },
- "abCard.ManagerName": {
- "message": "Manager:"
- },
- "abCard.MiddleName": {
- "message": "Middle name:"
- },
- "abCard.OtherAddress": {
- "message": "Address:"
- },
- "abCard.OtherCity": {
- "message": "City:"
- },
- "abCard.OtherCountry": {
- "message": "Country:"
- },
- "abCard.OtherState": {
- "message": "State:"
- },
- "abCard.OtherZip": {
- "message": "ZIP Code:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radio Phone:"
- },
- "abCard.Spouse": {
- "message": "Spouse:"
- },
- "abCard.header.eas": {
- "message": "Other Fields (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Additional home numbers:"
- },
- "abCard.header.messaging": {
- "message": "Messaging:"
- },
- "abCard.header.otheraddress": {
- "message": "Other Address (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Additional numbers:"
- },
- "abCard.header.people": {
- "message": "People:"
- },
- "abCard.header.worknumbers": {
- "message": "Additional work numbers:"
- },
- "acl.readonly": {
- "message": "Read-only server access (revert local changes)"
- },
- "acl.readwrite": {
- "message": "Read from and write to server"
- },
- "add.description": {
- "message": "Please select one of the available server configuration options and enter the requested details. "
- },
- "add.name": {
- "message": "Account name:"
- },
- "add.ok": {
- "message": "Add account"
- },
- "add.password": {
- "message": "Password:"
- },
- "add.server": {
- "message": "Server configuration:"
- },
- "add.shortdescription": {
- "message": "Account information"
- },
- "add.title": {
- "message": "Adding an Exchange ActiveSync account to TbSync"
- },
- "add.url": {
- "message": "Server address:"
- },
- "add.urldescription": {
- "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "User name (email address):"
- },
- "autocomplete.serverdirectory": {
- "message": "global server directory"
- },
- "autodiscover.Failed": {
- "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "Autodiscover needs a valid email address as user name."
- },
- "autodiscover.Ok": {
- "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
- },
- "autodiscover.Querying": {
- "message": "Searching for settings…"
- },
- "config.auto": {
- "message": "ActiveSync server configuration (Autodiscover)"
- },
- "config.custom": {
- "message": "ActiveSync server configuration"
- },
- "deletefolder.confirm": {
- "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
- },
- "deletefolder.menuentry": {
- "message": "Permanently purge folder “##replace.1##” from trash"
- },
- "deletefolder.notallowed": {
- "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
- },
- "extensionDescription": {
- "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
- },
- "extensionName": {
- "message": "Provider for Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Account settings"
- },
- "manager.tabs.outOfOffice": {
- "message": "Auto responder"
- },
- "manager.tabs.syncsettings": {
- "message": "Options"
- },
- "newaccount.add_auto": {
- "message": "Autodiscover settings and add account"
- },
- "newaccount.add_custom": {
- "message": "Add account"
- },
- "pref.AccountName": {
- "message": "Description"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync version"
- },
- "pref.DeviceId": {
- "message": "ActiveSync device ID"
- },
- "pref.ServerName": {
- "message": "Server address"
- },
- "pref.ServerNameDescription": {
- "message": "e.g. mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Show folders found in trash"
- },
- "pref.UserName": {
- "message": "User name"
- },
- "pref.UserNameDescription": {
- "message": "User name is usually the email address of your account."
- },
- "pref.autodetect": {
- "message": "best available"
- },
- "pref.birthday": {
- "message": "Send birthday information"
- },
- "pref.calendaroptions": {
- "message": "Calendar options"
- },
- "pref.contactoptions": {
- "message": "Contact options"
- },
- "pref.displayoverride": {
- "message": "Override Display Name with “First Name” + “Second Name”"
- },
- "pref.generaloptions": {
- "message": "General options"
- },
- "pref.provision": {
- "message": "Enforce provisioning (required by Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Comma"
- },
- "pref.seperator.description": {
- "message": "Separator for multiline address field."
- },
- "pref.seperator.linebreak": {
- "message": "Line break"
- },
- "pref.synclimit.1month": {
- "message": "from 4 weeks ago"
- },
- "pref.synclimit.2weeks": {
- "message": "from 2 weeks ago"
- },
- "pref.synclimit.3month": {
- "message": "from 3 months ago"
- },
- "pref.synclimit.6month": {
- "message": "from 6 months ago"
- },
- "pref.synclimit.all": {
- "message": "everything"
- },
- "pref.synclimit.description": {
- "message": "Synchronization period: "
- },
- "pref.usehttps": {
- "message": "Use secure connection (connect via https)"
- },
- "recyclebin": {
- "message": "Trash"
- },
- "servertype.auto": {
- "message": "Automatic configuration"
- },
- "servertype.custom": {
- "message": "Custom configuration"
- },
- "servertype.description.auto": {
- "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
- },
- "servertype.description.custom": {
- "message": "Setup your account by manually providing the address of the server you want to connect."
- },
- "servertype.description.office365": {
- "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Double click to unlock all predefined server settings."
- },
- "status.401": {
- "message": "Could not authenticate, check username and password (HTTP Error 401)."
- },
- "status.403": {
- "message": "Server rejected connection (forbidden) (HTTP Error 403)."
- },
- "status.404": {
- "message": "User not found (HTTP Error 404)."
- },
- "status.449": {
- "message": "Server requests provisioning (HTTP Error 449)."
- },
- "status.500": {
- "message": "Unknown Server Error (HTTP Error 500)."
- },
- "status.503": {
- "message": "Service unavailable (HTTP Error 503)."
- },
- "status.BadItemSkipped": {
- "message": "Bad Item Skipped: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Cannot delete a system folder (status 3)"
- },
- "status.FolderDelete.4": {
- "message": "Folder does not exist (status 4), resyncing"
- },
- "status.FolderDelete.6": {
- "message": "Command could not be completed, an error occurred on the server (status 6)"
- },
- "status.FolderDelete.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.FolderSync.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.InvalidServerOptions": {
- "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "The EAS Server rejected the last request."
- },
- "status.ServerRejectedSomeItems": {
- "message": "The EAS server did not accept ##replace.1## elements."
- },
- "status.Sync.12": {
- "message": "Folder hierarchy changed (status 12), resyncing"
- },
- "status.Sync.3": {
- "message": "Invalid synchronization key (status 3), resyncing"
- },
- "status.Sync.4": {
- "message": "Malformed request (status 4)"
- },
- "status.Sync.5": {
- "message": "Temporary server issues or invalid item (status 5)"
- },
- "status.Sync.6": {
- "message": "Invalid item (status 6)"
- },
- "status.Sync.8": {
- "message": "Object not found (status 8)"
- },
- "status.aborted": {
- "message": "Not synchronized"
- },
- "status.disabled": {
- "message": "Disabled"
- },
- "status.empty-response": {
- "message": "Server sends unexpected empty response."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Forbidden calendar item in a task folder (please resort)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Forbidden task item in a calendar folder (please resort)"
- },
- "status.global.101": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
- },
- "status.global.102": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
- },
- "status.global.103": {
- "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
- },
- "status.global.110": {
- "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
- },
- "status.global.clientdenied": {
- "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
- },
- "status.httperror": {
- "message": "Communication error (HTTP status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Invalid server response (junk)."
- },
- "status.malformed-xml": {
- "message": "Could not parse XML. Check event log for details."
- },
- "status.modified": {
- "message": "Local modifications"
- },
- "status.network": {
- "message": "Could not connect to server (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Could not connect to server."
- },
- "status.nosupportedeasversion": {
- "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
- },
- "status.notargets": {
- "message": "Aborting Sync, because sync targets could not be created."
- },
- "status.notsupportedeasversion": {
- "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Account needs to be synchronized, at least one item is out of sync."
- },
- "status.nouserhost": {
- "message": "Missing username and/or server. Please provide those values."
- },
- "status.pending": {
- "message": "Waiting to be synchronized"
- },
- "status.policy.2": {
- "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.3": {
- "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.4": {
- "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.5": {
- "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
- },
- "status.provision": {
- "message": "Provisioning failed with status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Response from the server contains no data."
- },
- "status.resync-loop": {
- "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
- },
- "status.security": {
- "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Not yet supported, skipped"
- },
- "status.syncing": {
- "message": "Synchronizing"
- },
- "status.timeout": {
- "message": "Communication timeout."
- },
- "status.wbxml-parse-error": {
- "message": "Server sends unreadable response."
- },
- "status.wbxmlerror": {
- "message": "Sync failed. Server responded with status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
- },
- "syncstate.accountdone": {
- "message": "Finished account"
- },
- "syncstate.done": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Processing updated server settings"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Folder deleted"
- },
- "syncstate.eval.response.estimate": {
- "message": "Processing change estimate"
- },
- "syncstate.eval.response.folders": {
- "message": "Processing folder list update"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Processing acknowledgment of local changes"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Processing acknowledgment of local deletes"
- },
- "syncstate.eval.response.options": {
- "message": "Processing server options"
- },
- "syncstate.eval.response.provision": {
- "message": "Processing provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Processing remote changes"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Reverting local changes"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.eval.response.synckey": {
- "message": "Processing SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Requesting updated server settings"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparing to delete folder"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Requesting change estimate"
- },
- "syncstate.prepare.request.folders": {
- "message": "Sending folder list update"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Sending local changes"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Sending local deletes"
- },
- "syncstate.prepare.request.options": {
- "message": "Requesting server options"
- },
- "syncstate.prepare.request.provision": {
- "message": "Requesting provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Requesting remote changes"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Collecting local changes"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Requesting SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Waiting for updated server settings"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Waiting for folder to be deleted"
- },
- "syncstate.send.request.estimate": {
- "message": "Waiting for change estimate"
- },
- "syncstate.send.request.folders": {
- "message": "Waiting for folder list update"
- },
- "syncstate.send.request.localchanges": {
- "message": "Waiting for acknowledgment of local changes"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Waiting for acknowledgment of local deletes"
- },
- "syncstate.send.request.options": {
- "message": "Waiting for server options"
- },
- "syncstate.send.request.provision": {
- "message": "Waiting for provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Waiting for remote changes"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Waiting for most recent versions"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.send.request.synckey": {
- "message": "Waiting for SyncKey"
- },
- "syncstate.syncing": {
- "message": "Initialize synchronization"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Anniversary:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistant:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Assistant Phone:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Work Alternative Phone:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Work Fax:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Car Phone:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Work Main Phone:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternative Email:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Home Alternative Phone:"
+ },
+ "abCard.ManagerName": {
+ "message": "Manager:"
+ },
+ "abCard.MiddleName": {
+ "message": "Middle name:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Address:"
+ },
+ "abCard.OtherCity": {
+ "message": "City:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Country:"
+ },
+ "abCard.OtherState": {
+ "message": "State:"
+ },
+ "abCard.OtherZip": {
+ "message": "ZIP Code:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radio Phone:"
+ },
+ "abCard.Spouse": {
+ "message": "Spouse:"
+ },
+ "abCard.header.eas": {
+ "message": "Other Fields (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Additional home numbers:"
+ },
+ "abCard.header.messaging": {
+ "message": "Messaging:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Other Address (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Additional numbers:"
+ },
+ "abCard.header.people": {
+ "message": "People:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Additional work numbers:"
+ },
+ "acl.readonly": {
+ "message": "Read-only server access (revert local changes)"
+ },
+ "acl.readwrite": {
+ "message": "Read from and write to server"
+ },
+ "add.description": {
+ "message": "Please select one of the available server configuration options and enter the requested details. "
+ },
+ "add.name": {
+ "message": "Account name:"
+ },
+ "add.ok": {
+ "message": "Add account"
+ },
+ "add.password": {
+ "message": "Password:"
+ },
+ "add.server": {
+ "message": "Server configuration:"
+ },
+ "add.shortdescription": {
+ "message": "Account information"
+ },
+ "add.title": {
+ "message": "Adding an Exchange ActiveSync account to TbSync"
+ },
+ "add.url": {
+ "message": "Server address:"
+ },
+ "add.urldescription": {
+ "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "User name (email address):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "global server directory"
+ },
+ "autodiscover.Failed": {
+ "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Autodiscover needs a valid email address as user name."
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
+ },
+ "autodiscover.Querying": {
+ "message": "Searching for settings…"
+ },
+ "config.auto": {
+ "message": "ActiveSync server configuration (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "ActiveSync server configuration"
+ },
+ "deletefolder.confirm": {
+ "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Permanently purge folder “##replace.1##” from trash"
+ },
+ "deletefolder.notallowed": {
+ "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
+ },
+ "extensionDescription": {
+ "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
+ },
+ "extensionName": {
+ "message": "Provider for Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Account settings"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Auto responder"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Options"
+ },
+ "newaccount.add_auto": {
+ "message": "Autodiscover settings and add account"
+ },
+ "newaccount.add_custom": {
+ "message": "Add account"
+ },
+ "pref.AccountName": {
+ "message": "Description"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync version"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync device ID"
+ },
+ "pref.ServerName": {
+ "message": "Server address"
+ },
+ "pref.ServerNameDescription": {
+ "message": "e.g. mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Show folders found in trash"
+ },
+ "pref.UserName": {
+ "message": "User name"
+ },
+ "pref.UserNameDescription": {
+ "message": "User name is usually the email address of your account."
+ },
+ "pref.autodetect": {
+ "message": "best available"
+ },
+ "pref.birthday": {
+ "message": "Send birthday information"
+ },
+ "pref.calendaroptions": {
+ "message": "Calendar options"
+ },
+ "pref.contactoptions": {
+ "message": "Contact options"
+ },
+ "pref.displayoverride": {
+ "message": "Override Display Name with “First Name” + “Second Name”"
+ },
+ "pref.generaloptions": {
+ "message": "General options"
+ },
+ "pref.provision": {
+ "message": "Enforce provisioning (required by Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Comma"
+ },
+ "pref.seperator.description": {
+ "message": "Separator for multiline address field."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Line break"
+ },
+ "pref.synclimit.1month": {
+ "message": "from 4 weeks ago"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "from 2 weeks ago"
+ },
+ "pref.synclimit.3month": {
+ "message": "from 3 months ago"
+ },
+ "pref.synclimit.6month": {
+ "message": "from 6 months ago"
+ },
+ "pref.synclimit.all": {
+ "message": "everything"
+ },
+ "pref.synclimit.description": {
+ "message": "Synchronization period: "
+ },
+ "pref.usehttps": {
+ "message": "Use secure connection (connect via https)"
+ },
+ "recyclebin": {
+ "message": "Trash"
+ },
+ "servertype.auto": {
+ "message": "Automatic configuration"
+ },
+ "servertype.custom": {
+ "message": "Custom configuration"
+ },
+ "servertype.description.auto": {
+ "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
+ },
+ "servertype.description.custom": {
+ "message": "Setup your account by manually providing the address of the server you want to connect."
+ },
+ "servertype.description.office365": {
+ "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Double click to unlock all predefined server settings."
+ },
+ "status.401": {
+ "message": "Could not authenticate, check username and password (HTTP Error 401)."
+ },
+ "status.403": {
+ "message": "Server rejected connection (forbidden) (HTTP Error 403)."
+ },
+ "status.404": {
+ "message": "User not found (HTTP Error 404)."
+ },
+ "status.449": {
+ "message": "Server requests provisioning (HTTP Error 449)."
+ },
+ "status.500": {
+ "message": "Unknown Server Error (HTTP Error 500)."
+ },
+ "status.503": {
+ "message": "Service unavailable (HTTP Error 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Bad Item Skipped: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Cannot delete a system folder (status 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Folder does not exist (status 4), resyncing"
+ },
+ "status.FolderDelete.6": {
+ "message": "Command could not be completed, an error occurred on the server (status 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.FolderSync.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.InvalidServerOptions": {
+ "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "The EAS Server rejected the last request."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "The EAS server did not accept ##replace.1## elements."
+ },
+ "status.Sync.12": {
+ "message": "Folder hierarchy changed (status 12), resyncing"
+ },
+ "status.Sync.3": {
+ "message": "Invalid synchronization key (status 3), resyncing"
+ },
+ "status.Sync.4": {
+ "message": "Malformed request (status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Temporary server issues or invalid item (status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Invalid item (status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Object not found (status 8)"
+ },
+ "status.aborted": {
+ "message": "Not synchronized"
+ },
+ "status.disabled": {
+ "message": "Disabled"
+ },
+ "status.empty-response": {
+ "message": "Server sends unexpected empty response."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Forbidden calendar item in a task folder (please resort)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Forbidden task item in a calendar folder (please resort)"
+ },
+ "status.global.101": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
+ },
+ "status.global.102": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
+ },
+ "status.global.103": {
+ "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
+ },
+ "status.global.110": {
+ "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
+ },
+ "status.httperror": {
+ "message": "Communication error (HTTP status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Invalid server response (junk)."
+ },
+ "status.malformed-xml": {
+ "message": "Could not parse XML. Check event log for details."
+ },
+ "status.modified": {
+ "message": "Local modifications"
+ },
+ "status.network": {
+ "message": "Could not connect to server (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Could not connect to server."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
+ },
+ "status.notargets": {
+ "message": "Aborting Sync, because sync targets could not be created."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Account needs to be synchronized, at least one item is out of sync."
+ },
+ "status.nouserhost": {
+ "message": "Missing username and/or server. Please provide those values."
+ },
+ "status.pending": {
+ "message": "Waiting to be synchronized"
+ },
+ "status.policy.2": {
+ "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.3": {
+ "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.4": {
+ "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.5": {
+ "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.provision": {
+ "message": "Provisioning failed with status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Response from the server contains no data."
+ },
+ "status.resync-loop": {
+ "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
+ },
+ "status.security": {
+ "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Not yet supported, skipped"
+ },
+ "status.syncing": {
+ "message": "Synchronizing"
+ },
+ "status.timeout": {
+ "message": "Communication timeout."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Server sends unreadable response."
+ },
+ "status.wbxmlerror": {
+ "message": "Sync failed. Server responded with status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
+ },
+ "syncstate.accountdone": {
+ "message": "Finished account"
+ },
+ "syncstate.done": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Processing updated server settings"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Folder deleted"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Processing change estimate"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Processing folder list update"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Processing acknowledgment of local changes"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Processing acknowledgment of local deletes"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Processing server options"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Processing provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Processing remote changes"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Reverting local changes"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Processing SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Requesting updated server settings"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparing to delete folder"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Requesting change estimate"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Sending folder list update"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Sending local changes"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Sending local deletes"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Requesting server options"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Requesting provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Requesting remote changes"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Collecting local changes"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Requesting SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Waiting for updated server settings"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Waiting for folder to be deleted"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Waiting for change estimate"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Waiting for folder list update"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Waiting for acknowledgment of local changes"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Waiting for acknowledgment of local deletes"
+ },
+ "syncstate.send.request.options": {
+ "message": "Waiting for server options"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Waiting for provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Waiting for remote changes"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Waiting for most recent versions"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Waiting for SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Initialize synchronization"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/es/messages.json eas4tbsync-4.17/_locales/es/messages.json
--- eas4tbsync-4.11/_locales/es/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/es/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Aniversario:"
- },
- "abCard.AssistantName": {
- "message": "Asistente:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Teléfono de asistente:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Teléfono de trabajo alternativo:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax de trabajo:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Teléfono del coche:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Teléfono del trabajo:"
- },
- "abCard.Email3Address": {
- "message": "Correo electrónico alternativo:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Teléfono de casa alternativo:"
- },
- "abCard.ManagerName": {
- "message": "Jefe:"
- },
- "abCard.MiddleName": {
- "message": "Segundo nombre:"
- },
- "abCard.OtherAddress": {
- "message": "Dirección:"
- },
- "abCard.OtherCity": {
- "message": "Ciudad:"
- },
- "abCard.OtherCountry": {
- "message": "País:"
- },
- "abCard.OtherState": {
- "message": "Estado:"
- },
- "abCard.OtherZip": {
- "message": "Código postal:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radioteléfono:"
- },
- "abCard.Spouse": {
- "message": "Pareja:"
- },
- "abCard.header.eas": {
- "message": "Otros campos (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Números de casa adicionales:"
- },
- "abCard.header.messaging": {
- "message": "Mensajes:"
- },
- "abCard.header.otheraddress": {
- "message": "Otra dirección (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Números adicionales:"
- },
- "abCard.header.people": {
- "message": "Personas:"
- },
- "abCard.header.worknumbers": {
- "message": "Números de trabajo adicionales:"
- },
- "acl.readonly": {
- "message": "Acceso de solo lectura al servidor (revertir cambios locales)"
- },
- "acl.readwrite": {
- "message": "Leer y escribir en el servidor"
- },
- "add.description": {
- "message": "Seleccione una de las opciones de configuración del servidor disponibles y escriba los detalles solicitados. "
- },
- "add.name": {
- "message": "Nombre de cuenta:"
- },
- "add.ok": {
- "message": "Añadir cuenta"
- },
- "add.password": {
- "message": "Contraseña:"
- },
- "add.server": {
- "message": "Configuración del servidor:"
- },
- "add.shortdescription": {
- "message": "Información de la cuenta"
- },
- "add.title": {
- "message": "Añadir una cuenta de Exchange ActiveSync a TbSync"
- },
- "add.url": {
- "message": "Dirección del servidor:"
- },
- "add.urldescription": {
- "message": "La dirección básica del servidor debería ser suficiente (por ejemplo, correo.servidor.com). Sin embargo, también es posible proporcionar la URL completa (por ejemplo, https://correo.servidor.com/Servidor-Microsoft-ActiveSync)."
- },
- "add.user": {
- "message": "Nombre de usuario (correo electrónico):"
- },
- "autocomplete.serverdirectory": {
- "message": "servidor de directorio global"
- },
- "autodiscover.Failed": {
- "message": "Ha fallado la detección automática del usuario «##user##». Es posible que las credenciales sean incorrectas, que su proveedor de ActiveSync tengo a un problema eventual o que no admita la detección automática."
- },
- "autodiscover.NeedEmail": {
- "message": "La detección automática requiere una dirección de correo electrónico válida como nombre de usuario."
- },
- "autodiscover.Ok": {
- "message": "La detección automática ha sido correcta. Ya puede revisar los ajustes opcionales y establecer la conexión de sincronización."
- },
- "autodiscover.Querying": {
- "message": "Buscando ajustes…"
- },
- "config.auto": {
- "message": "Configuración del servidor de ActiveSync (detección automática)"
- },
- "config.custom": {
- "message": "Configuración del servidor de ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "¿Realmente quiere ELIMINAR DEFINITIVAMENTE la carpeta «##replace.1##» de la papelera?"
- },
- "deletefolder.menuentry": {
- "message": "Eliminar definitivamente la carpeta «##replace.1##» de la papelera"
- },
- "deletefolder.notallowed": {
- "message": "Cancele la suscripción a la carpeta «##replace.1##» para poder eliminarla de la papelera."
- },
- "extensionDescription": {
- "message": "Añade soporte para sincronización de cuentas de Exchange ActiveSync a TbSync (contactos, tareas y calendarios)."
- },
- "extensionName": {
- "message": "Proveedor de Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Ajustes de la cuenta"
- },
- "manager.tabs.outOfOffice": {
- "message": "Respuesta automática"
- },
- "manager.tabs.syncsettings": {
- "message": "Opciones"
- },
- "newaccount.add_auto": {
- "message": "Detectar ajustes automáticamente y añadir cuenta"
- },
- "newaccount.add_custom": {
- "message": "Añadir cuenta"
- },
- "pref.AccountName": {
- "message": "Descripción"
- },
- "pref.ActiveSyncVersion": {
- "message": "Versión de ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID de dispositivo de ActiveSync"
- },
- "pref.ServerName": {
- "message": "Dirección del servidor"
- },
- "pref.ServerNameDescription": {
- "message": "por ejemplo, correo.servidor.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Mostrar carpetas encontradas en la papelera"
- },
- "pref.UserName": {
- "message": "Nombre de usuario"
- },
- "pref.UserNameDescription": {
- "message": "El nombre de usuario suele ser la dirección de correo electrónico de su cuenta."
- },
- "pref.autodetect": {
- "message": "mejor disponible"
- },
- "pref.birthday": {
- "message": "Enviar información de cumpleaños"
- },
- "pref.calendaroptions": {
- "message": "Opciones de calendario"
- },
- "pref.contactoptions": {
- "message": "Opciones de contactos"
- },
- "pref.displayoverride": {
- "message": "Reemplazar nombre de pantalla con «Nombre» + «Segundo nombre»"
- },
- "pref.generaloptions": {
- "message": "Opciones generales"
- },
- "pref.provision": {
- "message": "Forzar aprovisionamiento (requerido por Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Coma"
- },
- "pref.seperator.description": {
- "message": "Separador para campo de dirección en varias líneas."
- },
- "pref.seperator.linebreak": {
- "message": "Salto de línea"
- },
- "pref.synclimit.1month": {
- "message": "desde 4 semanas atrás"
- },
- "pref.synclimit.2weeks": {
- "message": "desde 2 semanas atrás"
- },
- "pref.synclimit.3month": {
- "message": "desde 3 meses atrás"
- },
- "pref.synclimit.6month": {
- "message": "desde 6 meses atrás"
- },
- "pref.synclimit.all": {
- "message": "todo"
- },
- "pref.synclimit.description": {
- "message": "Periodo de sincronización: "
- },
- "pref.usehttps": {
- "message": "Usar conexión segura (conectar mediante https)"
- },
- "recyclebin": {
- "message": "Papelera"
- },
- "servertype.auto": {
- "message": "Configuración automática"
- },
- "servertype.custom": {
- "message": "Configuración personalizada"
- },
- "servertype.description.auto": {
- "message": "Es posible detectar la configuración de muchos servidores de ActiveSync con solo proporcionar su dirección de correo electrónico."
- },
- "servertype.description.custom": {
- "message": "Configure la cuenta proporcionando manualmente la dirección del servidor al que desea conectar."
- },
- "servertype.description.office365": {
- "message": "Las cuentas conectadas a Office 365 utilizan un proceso de autenticación avanzado, llamado OAuth 2.0, que también admite autenticación multifactor (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Haga doble clic para desbloquear todos los ajustes predefinidos del servidor."
- },
- "status.401": {
- "message": "No ha sido posible autentificar, compruebe el nombre de usuario y contraseña (error HTTP 401)."
- },
- "status.403": {
- "message": "El servidor rechazó la conexión (prohibida) (error HTTP 403)."
- },
- "status.404": {
- "message": "Usuario no encontrado (error HTTP 404)."
- },
- "status.449": {
- "message": "El servidor solicita aprovisionamiento (error HTTP 449)."
- },
- "status.500": {
- "message": "Error de servidor desconocido (error HTTP 500)."
- },
- "status.503": {
- "message": "Servicio no disponible (error HTTP 503)."
- },
- "status.BadItemSkipped": {
- "message": "Objeto incorrecto omitido: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "No es posible eliminar una carpeta del sistema (estado 3)"
- },
- "status.FolderDelete.4": {
- "message": "La carpeta no existe (estado 4), resincronizando"
- },
- "status.FolderDelete.6": {
- "message": "No ha sido posible completar el comando, se ha producido un error en el servidor (estado 6)"
- },
- "status.FolderDelete.9": {
- "message": "Clave de sincronización no válida (estado 9), resincronizando"
- },
- "status.FolderSync.9": {
- "message": "Clave de sincronización no válida (estado 9), resincronizando"
- },
- "status.InvalidServerOptions": {
- "message": "El servidor no proporciona información sobre las versiones de ActiveSync compatibles. ¿Está EAS bloqueado para este usuario o este cliente (TbSync)? Puede intentar configurar la versión de ActiveSync manualmente."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "El servidor de EAS rechazó la última petición."
- },
- "status.ServerRejectedSomeItems": {
- "message": "El servidor de EAS no aceptó ##replace.1## elementos."
- },
- "status.Sync.12": {
- "message": "Jerarquía de carpetas cambiada (estado 12), resincronizando"
- },
- "status.Sync.3": {
- "message": "Clave de sincronización no válida (estado 3), resincronizando"
- },
- "status.Sync.4": {
- "message": "Solicitud mal formada (estado 4)"
- },
- "status.Sync.5": {
- "message": "Problemas temporales del servidor o elemento no válido (estado 5)"
- },
- "status.Sync.6": {
- "message": "Elemento no válido (estado 6)"
- },
- "status.Sync.8": {
- "message": "Objeto no encontrado (estado 8)"
- },
- "status.aborted": {
- "message": "Sin sincronizar"
- },
- "status.disabled": {
- "message": "Desactivado"
- },
- "status.empty-response": {
- "message": "El servidor envía una respuesta vacía inesperada."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Elemento de calendario prohibido en una carpeta de tareas (reorganice, por favor)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Elemento de tareas prohibido en una carpeta de calendario (reorganice, por favor)"
- },
- "status.global.101": {
- "message": "La solicitud contiene WBXML pero no se pudo decodificar como XML (error EAS 101)."
- },
- "status.global.102": {
- "message": "La solicitud contiene WBXML pero no se pudo decodificar como XML (error EAS 102)."
- },
- "status.global.103": {
- "message": "El XML proporcionado en la solicitud no cumple los requisitos de protocolo (error EAS 103)."
- },
- "status.global.110": {
- "message": "El servidor informó de un error interno y no deberíamos volver a intentarlo inmediatamente. La sincronización periódica automática se ha desactivado durante 30 minutos (error EAS 110)."
- },
- "status.global.clientdenied": {
- "message": "El servidor de EAS notifica <##replace.2##> (estado ##replace.1##) y no permite a TbSync acceder a tu cuenta."
- },
- "status.httperror": {
- "message": "Error de comunicación (estado HTTP ##replace.1##)."
- },
- "status.invalid": {
- "message": "Respuesta del servidor no válida (corrupta)."
- },
- "status.malformed-xml": {
- "message": "No ha sido posible analizar el XML. Compruebe el registro de eventos para más detalles."
- },
- "status.modified": {
- "message": "Modificaciones locales"
- },
- "status.network": {
- "message": "No ha sido posible conectar al servidor (##replace.1##)."
- },
- "status.networkerror": {
- "message": "No ha sido posible conectar al servidor."
- },
- "status.nosupportedeasversion": {
- "message": "El servidor no es compatible con las versiones de ActiveSync 2.5 y 14.0 (solo ##replace.1##). TbSync no funcionará con este servidor de ActiveSync."
- },
- "status.notargets": {
- "message": "Sincronización interrumpida porque no se han podido crear los destinos de la sincronización."
- },
- "status.notsupportedeasversion": {
- "message": "El servidor no es compatible con la versión seleccionada de ActiveSync, ##replace.1## (solo ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Es necesario sincronizar la cuenta: uno o varios elementos están sin sincronizar."
- },
- "status.nouserhost": {
- "message": "Falta el nombre de usuario o el servidor. Por favor, proporcione esos datos."
- },
- "status.pending": {
- "message": "Esperando sincronización"
- },
- "status.policy.2": {
- "message": "No hay ninguna directiva para este cliente. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
- },
- "status.policy.3": {
- "message": "El valor PolicyType es desconocido. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
- },
- "status.policy.4": {
- "message": "Los datos de directivas del servidor están dañados (posiblemente manipulados). Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
- },
- "status.policy.5": {
- "message": "El cliente está reconociendo la clave de directiva incorrecta. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
- },
- "status.provision": {
- "message": "El aprovisionamiento falló con el estado <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "La respuesta del servidor no contiene datos."
- },
- "status.resync-loop": {
- "message": "Se ha producido un error que no se pudo corregir volviendo a sincronizar la cuenta. Desactive la cuenta e inténtelo de nuevo (error: bucle de resincronización)."
- },
- "status.security": {
- "message": "No ha sido posible establecer una conexión segura. ¿Estás usando un certificado autofirmado, o que no es de confianza, sin importarlo a Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "No se admite aún; omitido"
- },
- "status.syncing": {
- "message": "Sincronizando"
- },
- "status.timeout": {
- "message": "Tiempo de comunicación agotado."
- },
- "status.wbxml-parse-error": {
- "message": "El servidor envía una respuesta ilegible."
- },
- "status.wbxmlerror": {
- "message": "Error al sincronizar. El servidor respondió con el estado <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Violación del protocolo de ActiveSync: falta el campo obligatorio <##replace.1##> en la respuesta del servidor."
- },
- "syncstate.accountdone": {
- "message": "Cuenta finalizada"
- },
- "syncstate.done": {
- "message": "Preparando el siguiente elemento para la sincronización"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Procesando la configuración actualizada del servidor"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Carpeta eliminada"
- },
- "syncstate.eval.response.estimate": {
- "message": "Procesando estimación de cambio"
- },
- "syncstate.eval.response.folders": {
- "message": "Procesando la lista de carpetas actualizada"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Procesando el reconocimiento de cambios locales"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Procesando el reconocimiento de eliminaciones locales"
- },
- "syncstate.eval.response.options": {
- "message": "Procesando opciones del servidor"
- },
- "syncstate.eval.response.provision": {
- "message": "Procesando aprovisionamiento"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Procesando los cambios remotos"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Revirtiendo los cambios locales"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Enviando información del dispositivo"
- },
- "syncstate.eval.response.synckey": {
- "message": "Procesando SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Solicitando la configuración actualizada del servidor"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparando la eliminación de la carpeta"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Solicitando estimación de cambios"
- },
- "syncstate.prepare.request.folders": {
- "message": "Enviando actualización de lista de carpetas"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Enviando los cambios locales"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Enviando las eliminaciones locales"
- },
- "syncstate.prepare.request.options": {
- "message": "Solicitando opciones de servidor"
- },
- "syncstate.prepare.request.provision": {
- "message": "Solicitud de aprovisionamiento"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Procesando los cambios remotos"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Recopilando los cambios locales"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Enviando información del dispositivo"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Solicitando SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparando el siguiente elemento para la sincronización"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Esperando la configuración actualizada del servidor"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Esperando la eliminación de la carpeta"
- },
- "syncstate.send.request.estimate": {
- "message": "Esperando la estimación de cambios"
- },
- "syncstate.send.request.folders": {
- "message": "Esperando la actualización de la lista de carpetas"
- },
- "syncstate.send.request.localchanges": {
- "message": "Esperando el reconocimiento de cambios locales"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Esperando el reconocimiento de eliminaciones locales"
- },
- "syncstate.send.request.options": {
- "message": "Esperando las opciones del servidor"
- },
- "syncstate.send.request.provision": {
- "message": "Esperando el aprovisionamiento"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Esperando los cambios remotos"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Esperando las versiones más recientes"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Enviando información del dispositivo"
- },
- "syncstate.send.request.synckey": {
- "message": "Esperando a SyncKey"
- },
- "syncstate.syncing": {
- "message": "Iniciar sincronización"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Aniversario:"
+ },
+ "abCard.AssistantName": {
+ "message": "Asistente:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Teléfono de asistente:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Teléfono de trabajo alternativo:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax de trabajo:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Teléfono del coche:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Teléfono del trabajo:"
+ },
+ "abCard.Email3Address": {
+ "message": "Correo electrónico alternativo:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Teléfono de casa alternativo:"
+ },
+ "abCard.ManagerName": {
+ "message": "Jefe:"
+ },
+ "abCard.MiddleName": {
+ "message": "Segundo nombre:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Dirección:"
+ },
+ "abCard.OtherCity": {
+ "message": "Ciudad:"
+ },
+ "abCard.OtherCountry": {
+ "message": "País:"
+ },
+ "abCard.OtherState": {
+ "message": "Estado:"
+ },
+ "abCard.OtherZip": {
+ "message": "Código postal:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radioteléfono:"
+ },
+ "abCard.Spouse": {
+ "message": "Pareja:"
+ },
+ "abCard.header.eas": {
+ "message": "Otros campos (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Números de casa adicionales:"
+ },
+ "abCard.header.messaging": {
+ "message": "Mensajes:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Otra dirección (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Números adicionales:"
+ },
+ "abCard.header.people": {
+ "message": "Personas:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Números de trabajo adicionales:"
+ },
+ "acl.readonly": {
+ "message": "Acceso de solo lectura al servidor (revertir cambios locales)"
+ },
+ "acl.readwrite": {
+ "message": "Leer y escribir en el servidor"
+ },
+ "add.description": {
+ "message": "Seleccione una de las opciones de configuración del servidor disponibles y escriba los detalles solicitados. "
+ },
+ "add.name": {
+ "message": "Nombre de cuenta:"
+ },
+ "add.ok": {
+ "message": "Añadir cuenta"
+ },
+ "add.password": {
+ "message": "Contraseña:"
+ },
+ "add.server": {
+ "message": "Configuración del servidor:"
+ },
+ "add.shortdescription": {
+ "message": "Información de la cuenta"
+ },
+ "add.title": {
+ "message": "Añadir una cuenta de Exchange ActiveSync a TbSync"
+ },
+ "add.url": {
+ "message": "Dirección del servidor:"
+ },
+ "add.urldescription": {
+ "message": "La dirección básica del servidor debería ser suficiente (por ejemplo, correo.servidor.com). Sin embargo, también es posible proporcionar la URL completa (por ejemplo, https://correo.servidor.com/Servidor-Microsoft-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Nombre de usuario (correo electrónico):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "servidor de directorio global"
+ },
+ "autodiscover.Failed": {
+ "message": "Ha fallado la detección automática del usuario «##user##». Es posible que las credenciales sean incorrectas, que su proveedor de ActiveSync tengo a un problema eventual o que no admita la detección automática."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "La detección automática requiere una dirección de correo electrónico válida como nombre de usuario."
+ },
+ "autodiscover.Ok": {
+ "message": "La detección automática ha sido correcta. Ya puede revisar los ajustes opcionales y establecer la conexión de sincronización."
+ },
+ "autodiscover.Querying": {
+ "message": "Buscando ajustes…"
+ },
+ "config.auto": {
+ "message": "Configuración del servidor de ActiveSync (detección automática)"
+ },
+ "config.custom": {
+ "message": "Configuración del servidor de ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "¿Realmente quiere ELIMINAR DEFINITIVAMENTE la carpeta «##replace.1##» de la papelera?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Eliminar definitivamente la carpeta «##replace.1##» de la papelera"
+ },
+ "deletefolder.notallowed": {
+ "message": "Cancele la suscripción a la carpeta «##replace.1##» para poder eliminarla de la papelera."
+ },
+ "extensionDescription": {
+ "message": "Añade soporte para sincronización de cuentas de Exchange ActiveSync a TbSync (contactos, tareas y calendarios)."
+ },
+ "extensionName": {
+ "message": "Proveedor de Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Ajustes de la cuenta"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Respuesta automática"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Opciones"
+ },
+ "newaccount.add_auto": {
+ "message": "Detectar ajustes automáticamente y añadir cuenta"
+ },
+ "newaccount.add_custom": {
+ "message": "Añadir cuenta"
+ },
+ "pref.AccountName": {
+ "message": "Descripción"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Versión de ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID de dispositivo de ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Dirección del servidor"
+ },
+ "pref.ServerNameDescription": {
+ "message": "por ejemplo, correo.servidor.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Mostrar carpetas encontradas en la papelera"
+ },
+ "pref.UserName": {
+ "message": "Nombre de usuario"
+ },
+ "pref.UserNameDescription": {
+ "message": "El nombre de usuario suele ser la dirección de correo electrónico de su cuenta."
+ },
+ "pref.autodetect": {
+ "message": "mejor disponible"
+ },
+ "pref.birthday": {
+ "message": "Enviar información de cumpleaños"
+ },
+ "pref.calendaroptions": {
+ "message": "Opciones de calendario"
+ },
+ "pref.contactoptions": {
+ "message": "Opciones de contactos"
+ },
+ "pref.displayoverride": {
+ "message": "Reemplazar nombre de pantalla con «Nombre» + «Segundo nombre»"
+ },
+ "pref.generaloptions": {
+ "message": "Opciones generales"
+ },
+ "pref.provision": {
+ "message": "Forzar aprovisionamiento (requerido por Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Coma"
+ },
+ "pref.seperator.description": {
+ "message": "Separador para campo de dirección en varias líneas."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Salto de línea"
+ },
+ "pref.synclimit.1month": {
+ "message": "desde 4 semanas atrás"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "desde 2 semanas atrás"
+ },
+ "pref.synclimit.3month": {
+ "message": "desde 3 meses atrás"
+ },
+ "pref.synclimit.6month": {
+ "message": "desde 6 meses atrás"
+ },
+ "pref.synclimit.all": {
+ "message": "todo"
+ },
+ "pref.synclimit.description": {
+ "message": "Periodo de sincronización: "
+ },
+ "pref.usehttps": {
+ "message": "Usar conexión segura (conectar mediante https)"
+ },
+ "recyclebin": {
+ "message": "Papelera"
+ },
+ "servertype.auto": {
+ "message": "Configuración automática"
+ },
+ "servertype.custom": {
+ "message": "Configuración personalizada"
+ },
+ "servertype.description.auto": {
+ "message": "Es posible detectar la configuración de muchos servidores de ActiveSync con solo proporcionar su dirección de correo electrónico."
+ },
+ "servertype.description.custom": {
+ "message": "Configure la cuenta proporcionando manualmente la dirección del servidor al que desea conectar."
+ },
+ "servertype.description.office365": {
+ "message": "Las cuentas conectadas a Office 365 utilizan un proceso de autenticación avanzado, llamado OAuth 2.0, que también admite autenticación multifactor (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Haga doble clic para desbloquear todos los ajustes predefinidos del servidor."
+ },
+ "status.401": {
+ "message": "No ha sido posible autentificar, compruebe el nombre de usuario y contraseña (error HTTP 401)."
+ },
+ "status.403": {
+ "message": "El servidor rechazó la conexión (prohibida) (error HTTP 403)."
+ },
+ "status.404": {
+ "message": "Usuario no encontrado (error HTTP 404)."
+ },
+ "status.449": {
+ "message": "El servidor solicita aprovisionamiento (error HTTP 449)."
+ },
+ "status.500": {
+ "message": "Error de servidor desconocido (error HTTP 500)."
+ },
+ "status.503": {
+ "message": "Servicio no disponible (error HTTP 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Objeto incorrecto omitido: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "No es posible eliminar una carpeta del sistema (estado 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "La carpeta no existe (estado 4), resincronizando"
+ },
+ "status.FolderDelete.6": {
+ "message": "No ha sido posible completar el comando, se ha producido un error en el servidor (estado 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Clave de sincronización no válida (estado 9), resincronizando"
+ },
+ "status.FolderSync.9": {
+ "message": "Clave de sincronización no válida (estado 9), resincronizando"
+ },
+ "status.InvalidServerOptions": {
+ "message": "El servidor no proporciona información sobre las versiones de ActiveSync compatibles. ¿Está EAS bloqueado para este usuario o este cliente (TbSync)? Puede intentar configurar la versión de ActiveSync manualmente."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "El servidor de EAS rechazó la última petición."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "El servidor de EAS no aceptó ##replace.1## elementos."
+ },
+ "status.Sync.12": {
+ "message": "Jerarquía de carpetas cambiada (estado 12), resincronizando"
+ },
+ "status.Sync.3": {
+ "message": "Clave de sincronización no válida (estado 3), resincronizando"
+ },
+ "status.Sync.4": {
+ "message": "Solicitud mal formada (estado 4)"
+ },
+ "status.Sync.5": {
+ "message": "Problemas temporales del servidor o elemento no válido (estado 5)"
+ },
+ "status.Sync.6": {
+ "message": "Elemento no válido (estado 6)"
+ },
+ "status.Sync.8": {
+ "message": "Objeto no encontrado (estado 8)"
+ },
+ "status.aborted": {
+ "message": "Sin sincronizar"
+ },
+ "status.disabled": {
+ "message": "Desactivado"
+ },
+ "status.empty-response": {
+ "message": "El servidor envía una respuesta vacía inesperada."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Elemento de calendario prohibido en una carpeta de tareas (reorganice, por favor)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Elemento de tareas prohibido en una carpeta de calendario (reorganice, por favor)"
+ },
+ "status.global.101": {
+ "message": "La solicitud contiene WBXML pero no se pudo decodificar como XML (error EAS 101)."
+ },
+ "status.global.102": {
+ "message": "La solicitud contiene WBXML pero no se pudo decodificar como XML (error EAS 102)."
+ },
+ "status.global.103": {
+ "message": "El XML proporcionado en la solicitud no cumple los requisitos de protocolo (error EAS 103)."
+ },
+ "status.global.110": {
+ "message": "El servidor informó de un error interno y no deberíamos volver a intentarlo inmediatamente. La sincronización periódica automática se ha desactivado durante 30 minutos (error EAS 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "El servidor de EAS notifica <##replace.2##> (estado ##replace.1##) y no permite a TbSync acceder a tu cuenta."
+ },
+ "status.httperror": {
+ "message": "Error de comunicación (estado HTTP ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Respuesta del servidor no válida (corrupta)."
+ },
+ "status.malformed-xml": {
+ "message": "No ha sido posible analizar el XML. Compruebe el registro de eventos para más detalles."
+ },
+ "status.modified": {
+ "message": "Modificaciones locales"
+ },
+ "status.network": {
+ "message": "No ha sido posible conectar al servidor (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "No ha sido posible conectar al servidor."
+ },
+ "status.nosupportedeasversion": {
+ "message": "El servidor no es compatible con las versiones de ActiveSync 2.5 y 14.0 (solo ##replace.1##). TbSync no funcionará con este servidor de ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Sincronización interrumpida porque no se han podido crear los destinos de la sincronización."
+ },
+ "status.notsupportedeasversion": {
+ "message": "El servidor no es compatible con la versión seleccionada de ActiveSync, ##replace.1## (solo ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Es necesario sincronizar la cuenta: uno o varios elementos están sin sincronizar."
+ },
+ "status.nouserhost": {
+ "message": "Falta el nombre de usuario o el servidor. Por favor, proporcione esos datos."
+ },
+ "status.pending": {
+ "message": "Esperando sincronización"
+ },
+ "status.policy.2": {
+ "message": "No hay ninguna directiva para este cliente. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
+ },
+ "status.policy.3": {
+ "message": "El valor PolicyType es desconocido. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
+ },
+ "status.policy.4": {
+ "message": "Los datos de directivas del servidor están dañados (posiblemente manipulados). Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
+ },
+ "status.policy.5": {
+ "message": "El cliente está reconociendo la clave de directiva incorrecta. Póngase en contacto con el administrador del servidor o deshabilite el aprovisionamiento de esta cuenta."
+ },
+ "status.provision": {
+ "message": "El aprovisionamiento falló con el estado <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "La respuesta del servidor no contiene datos."
+ },
+ "status.resync-loop": {
+ "message": "Se ha producido un error que no se pudo corregir volviendo a sincronizar la cuenta. Desactive la cuenta e inténtelo de nuevo (error: bucle de resincronización)."
+ },
+ "status.security": {
+ "message": "No ha sido posible establecer una conexión segura. ¿Estás usando un certificado autofirmado, o que no es de confianza, sin importarlo a Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "No se admite aún; omitido"
+ },
+ "status.syncing": {
+ "message": "Sincronizando"
+ },
+ "status.timeout": {
+ "message": "Tiempo de comunicación agotado."
+ },
+ "status.wbxml-parse-error": {
+ "message": "El servidor envía una respuesta ilegible."
+ },
+ "status.wbxmlerror": {
+ "message": "Error al sincronizar. El servidor respondió con el estado <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Violación del protocolo de ActiveSync: falta el campo obligatorio <##replace.1##> en la respuesta del servidor."
+ },
+ "syncstate.accountdone": {
+ "message": "Cuenta finalizada"
+ },
+ "syncstate.done": {
+ "message": "Preparando el siguiente elemento para la sincronización"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Procesando la configuración actualizada del servidor"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Carpeta eliminada"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Procesando estimación de cambio"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Procesando la lista de carpetas actualizada"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Procesando el reconocimiento de cambios locales"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Procesando el reconocimiento de eliminaciones locales"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Procesando opciones del servidor"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Procesando aprovisionamiento"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Procesando los cambios remotos"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Revirtiendo los cambios locales"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Enviando información del dispositivo"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Procesando SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Solicitando la configuración actualizada del servidor"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparando la eliminación de la carpeta"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Solicitando estimación de cambios"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Enviando actualización de lista de carpetas"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Enviando los cambios locales"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Enviando las eliminaciones locales"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Solicitando opciones de servidor"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Solicitud de aprovisionamiento"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Procesando los cambios remotos"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Recopilando los cambios locales"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Enviando información del dispositivo"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Solicitando SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparando el siguiente elemento para la sincronización"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Esperando la configuración actualizada del servidor"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Esperando la eliminación de la carpeta"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Esperando la estimación de cambios"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Esperando la actualización de la lista de carpetas"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Esperando el reconocimiento de cambios locales"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Esperando el reconocimiento de eliminaciones locales"
+ },
+ "syncstate.send.request.options": {
+ "message": "Esperando las opciones del servidor"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Esperando el aprovisionamiento"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Esperando los cambios remotos"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Esperando las versiones más recientes"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Enviando información del dispositivo"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Esperando a SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Iniciar sincronización"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/fr/messages.json eas4tbsync-4.17/_locales/fr/messages.json
--- eas4tbsync-4.11/_locales/fr/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/fr/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Anniversaire :"
- },
- "abCard.AssistantName": {
- "message": "Assistant(e) :"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Téléphone Assistant(e) :"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Téléphone Bureau Alternatif :"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax de bureau :"
- },
- "abCard.CarPhoneNumber": {
- "message": "Téléphone Voiture :"
- },
- "abCard.CompanyMainPhone": {
- "message": "Téléphone de Bureau Principal :"
- },
- "abCard.Email3Address": {
- "message": "Courriel alternatif :"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Téléphone Domicile Alternatif :"
- },
- "abCard.ManagerName": {
- "message": "Supérieur(e) :"
- },
- "abCard.MiddleName": {
- "message": "Deuxième prénom :"
- },
- "abCard.OtherAddress": {
- "message": "Adresse :"
- },
- "abCard.OtherCity": {
- "message": "Ville :"
- },
- "abCard.OtherCountry": {
- "message": "Pays :"
- },
- "abCard.OtherState": {
- "message": "État :"
- },
- "abCard.OtherZip": {
- "message": "Code postal :"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Téléphone Radio :"
- },
- "abCard.Spouse": {
- "message": "Épou(x/se) :"
- },
- "abCard.header.eas": {
- "message": "Autres champs (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Téléphones domicile supplémentaires :"
- },
- "abCard.header.messaging": {
- "message": "Messagerie :"
- },
- "abCard.header.otheraddress": {
- "message": "Autre Adresse (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Numéros de téléphone supplémentaires :"
- },
- "abCard.header.people": {
- "message": "Personnes :"
- },
- "abCard.header.worknumbers": {
- "message": "Téléphones de bureau supplémentaires :"
- },
- "acl.readonly": {
- "message": "Accès au serveur en lecture seule (annule les modifications locales)"
- },
- "acl.readwrite": {
- "message": "Lecture et écriture sur le serveur"
- },
- "add.description": {
- "message": "Veuillez sélectionner une des options de configuration du serveur disponibles et entrer les détails demandés. "
- },
- "add.name": {
- "message": "Nom du compte :"
- },
- "add.ok": {
- "message": "Ajouter un compte"
- },
- "add.password": {
- "message": "Mot de passe :"
- },
- "add.server": {
- "message": "Configuration du serveur :"
- },
- "add.shortdescription": {
- "message": "Informations du compte"
- },
- "add.title": {
- "message": "Ajout d'un compte Exchange ActiveSync à TbSync"
- },
- "add.url": {
- "message": "Adresse du serveur :"
- },
- "add.urldescription": {
- "message": "Il devrait suffire de fournir uniquement l'adresse de base du serveur (par exemple : mail.votreserveur.com). Cependant, il est également possible de fournir l'URL complète (par exemple : https://mail.votreserveur.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Nom d'utilisateur (adresse e-mail) :"
- },
- "autocomplete.serverdirectory": {
- "message": "annuaire global du serveur"
- },
- "autodiscover.Failed": {
- "message": "L'Autodiscover pour l'utilisateur <##user##> a échoué. Soit les informations d'identification fournies étaient erronées, soit votre fournisseur ActiveSync a un problème temporaire, soit il ne prend pas en charge l'Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "L'Autodiscover a besoin d'une adresse courriel valide comme nom d'utilisateur."
- },
- "autodiscover.Ok": {
- "message": "L'Autodiscover est terminée avec succès, vous pouvez maintenant vérifier les paramètres optionnels et établir la connexion de synchronisation."
- },
- "autodiscover.Querying": {
- "message": "Recherche de paramètres…"
- },
- "config.auto": {
- "message": "Configuration du serveur ActiveSync (Autodiscover)"
- },
- "config.custom": {
- "message": "Configuration du serveur ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "Voulez-vous vraiment SUPPRIMER DÉFINITIVEMENT le dossier « ##replace.1##» de la corbeille ?"
- },
- "deletefolder.menuentry": {
- "message": "Supprimer définitivement le dossier « ##replace.1##» de la corbeille"
- },
- "deletefolder.notallowed": {
- "message": "Veuillez vous désabonner du dossier « ##replace.1##» avant d'essayer de le supprimer de la corbeille."
- },
- "extensionDescription": {
- "message": "Ajouter la prise en charge de la synchronisation des comptes Exchange ActiveSync à TbSync (contacts, tâches et calendriers)."
- },
- "extensionName": {
- "message": "Fournisseur pour Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Paramètres du compte"
- },
- "manager.tabs.outOfOffice": {
- "message": "Répondeur automatique"
- },
- "manager.tabs.syncsettings": {
- "message": "Paramètres"
- },
- "newaccount.add_auto": {
- "message": "Paramètres Autodiscover et ajout de compte"
- },
- "newaccount.add_custom": {
- "message": "Ajouter un compte"
- },
- "pref.AccountName": {
- "message": "Description"
- },
- "pref.ActiveSyncVersion": {
- "message": "Version d'ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID de périphérique ActiveSync"
- },
- "pref.ServerName": {
- "message": "Adresse du serveur"
- },
- "pref.ServerNameDescription": {
- "message": "par exemple mail.votreserveur.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Afficher les dossiers trouvés dans la corbeille"
- },
- "pref.UserName": {
- "message": "Nom d'utilisateur"
- },
- "pref.UserNameDescription": {
- "message": "Le nom d'utilisateur est généralement l'adresse e-mail de votre compte."
- },
- "pref.autodetect": {
- "message": "le meilleur disponible"
- },
- "pref.birthday": {
- "message": "Envoyer la date de naissance"
- },
- "pref.calendaroptions": {
- "message": "Options de calendrier"
- },
- "pref.contactoptions": {
- "message": "Options des contacts"
- },
- "pref.displayoverride": {
- "message": "Remplacer le nom affiché par « Prénom » + « Nom »"
- },
- "pref.generaloptions": {
- "message": "Options générales"
- },
- "pref.provision": {
- "message": "Forcer l'approvisionnement (requis par Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Virgule"
- },
- "pref.seperator.description": {
- "message": "Séparateur pour le champ d'adresse multiligne."
- },
- "pref.seperator.linebreak": {
- "message": "Saut de ligne"
- },
- "pref.synclimit.1month": {
- "message": "les 4 dernières semaines"
- },
- "pref.synclimit.2weeks": {
- "message": "les 2 dernières semaines"
- },
- "pref.synclimit.3month": {
- "message": "les 3 derniers mois"
- },
- "pref.synclimit.6month": {
- "message": "les 6 derniers mois"
- },
- "pref.synclimit.all": {
- "message": "tout"
- },
- "pref.synclimit.description": {
- "message": "Période de synchronisation : "
- },
- "pref.usehttps": {
- "message": "Utiliser une connexion sécurisée (se connecter via https)"
- },
- "recyclebin": {
- "message": "Corbeille"
- },
- "servertype.auto": {
- "message": "Configuration automatique"
- },
- "servertype.custom": {
- "message": "Configuration personnalisée"
- },
- "servertype.description.auto": {
- "message": "La configuration de nombreux serveurs ActiveSync peut être découverte en fournissant uniquement votre adresse e-mail."
- },
- "servertype.description.custom": {
- "message": "Configurez votre compte en fournissant manuellement l'adresse du serveur que vous souhaitez connecter."
- },
- "servertype.description.office365": {
- "message": "Les comptes connectés à Office 365 utilisent un processus d'authentification moderne appelé OAuth 2.0 qui supporte également l'authentification multi-facteur (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Double-cliquez pour déverrouiller tous les paramètres prédéfinis du serveur."
- },
- "status.401": {
- "message": "L'authentification a échoué. Veuillez vérifier le couple nom d'utilisateur/mot de passe (erreur HTTP 401)."
- },
- "status.403": {
- "message": "Le serveur a rejeté la connexion (interdite) (Erreur HTTP 403)."
- },
- "status.404": {
- "message": "Utilisateur introuvable (Erreur HTTP 404)."
- },
- "status.449": {
- "message": "Le serveur demande le provisionnement (erreur HTTP 449)."
- },
- "status.500": {
- "message": "Erreur serveur inconnue (Erreur HTTP 500)."
- },
- "status.503": {
- "message": "Service indisponible (Erreur HTTP 503)."
- },
- "status.BadItemSkipped": {
- "message": "Mauvais élément ignoré : ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Impossible de supprimer un dossier système (statut 3)"
- },
- "status.FolderDelete.4": {
- "message": "Le dossier n'existe pas (statut 4), resynchronisation"
- },
- "status.FolderDelete.6": {
- "message": "La commande n'a pas pu être terminée, une erreur est survenue sur le serveur (statut 6)"
- },
- "status.FolderDelete.9": {
- "message": "Clé de synchronisation invalide (statut 9), resynchronisation"
- },
- "status.FolderSync.9": {
- "message": "Clé de synchronisation invalide (statut 9), resynchronisation"
- },
- "status.InvalidServerOptions": {
- "message": "Le serveur ne fournit pas d'informations sur les versions ActiveSync supportées. EAS est-il bloqué pour cet utilisateur ou ce client (TbSync) ? Vous pouvez essayer de définir manuellement la version ActiveSync."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "Le serveur EAS a rejeté la dernière demande."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Le serveur EAS n'a pas accepté les éléments ##replace.1##."
- },
- "status.Sync.12": {
- "message": "La hiérarchie des dossiers a changé (statut 12), resynchronisation"
- },
- "status.Sync.3": {
- "message": "Clé de synchronisation invalide (statut 3), resynchronisation"
- },
- "status.Sync.4": {
- "message": "Requête mal formée (statut 4)"
- },
- "status.Sync.5": {
- "message": "Problèmes de serveur temporaires ou élément invalide (statut 5)"
- },
- "status.Sync.6": {
- "message": "Élément invalide (statut 6)"
- },
- "status.Sync.8": {
- "message": "Objet introuvable (statut 8)"
- },
- "status.aborted": {
- "message": "Non synchronisé"
- },
- "status.disabled": {
- "message": "Désactivé"
- },
- "status.empty-response": {
- "message": "Le serveur a renvoyé une réponse vide inattendue."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Élément de calendrier interdit dans un dossier de tâche (veuillez intervenir)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Élément de calendrier interdit dans un dossier de tâche (veuillez intervenir)"
- },
- "status.global.101": {
- "message": "La requête contient WBXML mais n'a pas pu être décodée en XML (EAS Error 101)."
- },
- "status.global.102": {
- "message": "La requête contient WBXML mais n'a pas pu être décodée en XML (EAS Error 102)."
- },
- "status.global.103": {
- "message": "Le XML fourni dans la requête ne respecte pas les exigences du protocole (EAS Error 103)."
- },
- "status.global.110": {
- "message": "Le serveur a signalé une erreur interne et nous ne devrions pas réessayer immédiatement. La synchronisation périodique automatique a été désactivée pendant 30 minutes (EAS Error 110)."
- },
- "status.global.clientdenied": {
- "message": "Le serveur EAS signale <##replace.2##> (status ##replace.1##) et n'autorise pas TbSync à accéder à votre compte."
- },
- "status.httperror": {
- "message": "Erreur de communication (statut HTTP ##replace.1##)."
- },
- "status.invalid": {
- "message": "Réponse du serveur invalide (pourriels)."
- },
- "status.malformed-xml": {
- "message": "Impossible d’analyser le XML. Vérifiez le journal des événements pour plus de détails."
- },
- "status.modified": {
- "message": "Modifications locales présentes"
- },
- "status.network": {
- "message": "Impossible de se connecter au serveur (##replace.1##)."
- },
- "status.networkerror": {
- "message": "La connexion au serveur a échoué."
- },
- "status.nosupportedeasversion": {
- "message": "Le serveur ne prend pas en charge ActiveSync v2.5 ou v14.0 (seulement ##replace.1##). TbSync ne fonctionnera pas avec ce serveur ActiveSync."
- },
- "status.notargets": {
- "message": "Annulation de la synchronisation en cours : il est impossible de créer les destinations de synchronisation."
- },
- "status.notsupportedeasversion": {
- "message": "Le serveur ne prend pas en charge la sélection ActiveSync v##replace.1## (seulement ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Le compte doit être synchronisé : au moins un éléments n'est pas synchronisé."
- },
- "status.nouserhost": {
- "message": "Nom d'utilisateur et/ou serveur manquant. Veuillez fournir ces valeurs."
- },
- "status.pending": {
- "message": "En attente de synchronisation"
- },
- "status.policy.2": {
- "message": "Il n'y a pas de politique pour ce client. Contactez l'administrateur de votre serveur ou désactivez le provisioning pour ce compte."
- },
- "status.policy.3": {
- "message": "Valeur de PolicyType inconnue. Contactez l'administrateur du serveur ou désactivez le provisioning pour ce compte."
- },
- "status.policy.4": {
- "message": "Les données de stratégie sur le serveur sont corrompues (potentiellement altérées). Contactez l'administrateur de votre serveur ou désactivez le provisioning pour ce compte."
- },
- "status.policy.5": {
- "message": "Le client reconnaît la mauvaise clé de stratégie. Contactez l'administrateur du serveur ou désactivez le provisioning pour ce compte."
- },
- "status.provision": {
- "message": "Le provisioning a échoué avec le statut <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "La réponse du serveur ne contient aucune donnée."
- },
- "status.resync-loop": {
- "message": "Il y a eu une erreur à partir de laquelle nous n'avons pas pu rétablir la situation en resynchronisant le compte. Veuillez désactiver le compte et réessayer. (Erreur : boucle de resynchronisation)"
- },
- "status.security": {
- "message": "Impossible d'établir une connexion sécurisée. Utilisez-vous un certificat auto-signé ou autrement non fiable sans l'importer dans Thunderbird ? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Pas encore pris en charge, ignoré"
- },
- "status.syncing": {
- "message": "Synchronisation en cours"
- },
- "status.timeout": {
- "message": "Délai de communication expiré."
- },
- "status.wbxml-parse-error": {
- "message": "Le serveur envoie une réponse illisible."
- },
- "status.wbxmlerror": {
- "message": "La synchronisation a échoué. Le serveur a répondu avec le statut <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Violation du protocole ActiveSync : le champ obligatoire <##replace.1##> est absent de la réponse du serveur."
- },
- "syncstate.accountdone": {
- "message": "Synchronisation du compte terminée"
- },
- "syncstate.done": {
- "message": "Préparation du prochain élément pour la synchronisation"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Traitement des paramètres du serveur mis à jour"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Dossier supprimé"
- },
- "syncstate.eval.response.estimate": {
- "message": "Traitement de l'estimation des changements"
- },
- "syncstate.eval.response.folders": {
- "message": "Mise à jour de la liste des dossiers en cours de traitement"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Traitement de la confirmation de réception des modifications locales"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Traitement de la confirmation de réception des suppressions locales"
- },
- "syncstate.eval.response.options": {
- "message": "Traitement des options du serveur"
- },
- "syncstate.eval.response.provision": {
- "message": "Traitement de la provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Traitement des modifications à distance"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Rétablissement des modification locales"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Envoi des informations de l'appareil"
- },
- "syncstate.eval.response.synckey": {
- "message": "Traitement de la clé de synchronisation"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Demande de mise à jour des paramètres du serveur"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Préparation de la suppression du dossier"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Demande de l'estimation des changements"
- },
- "syncstate.prepare.request.folders": {
- "message": "Envoi de la mise à jour de la liste de dossiers"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Envoi des modifications locales"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Envoi des suppressions locales"
- },
- "syncstate.prepare.request.options": {
- "message": "Demande des options du serveur"
- },
- "syncstate.prepare.request.provision": {
- "message": "Demande de provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Traitement des modifications à distance"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Collecte des modifications locales"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Envoi des informations de l'appareil"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Demande de clé de synchronisation"
- },
- "syncstate.preparing": {
- "message": "Préparation du prochain élément pour la synchronisation"
- },
- "syncstate.send.request.autodiscover": {
- "message": "En attente de mise à jour des paramètres du serveur"
- },
- "syncstate.send.request.deletefolder": {
- "message": "En attente de la suppression du dossier"
- },
- "syncstate.send.request.estimate": {
- "message": "En attente de l'estimation des changements"
- },
- "syncstate.send.request.folders": {
- "message": "En attente de mise à jour de la liste des dossiers"
- },
- "syncstate.send.request.localchanges": {
- "message": "En attente de la confirmation de réception des modifications locales"
- },
- "syncstate.send.request.localdeletes": {
- "message": "En attente de la confirmation de réception des suppressions locales"
- },
- "syncstate.send.request.options": {
- "message": "En attente des options du serveur"
- },
- "syncstate.send.request.provision": {
- "message": "En attente de provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "En attente des modifications à distance"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "En attente des versions les plus récentes"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Envoi des informations de l'appareil"
- },
- "syncstate.send.request.synckey": {
- "message": "En attente de clé de synchronisation"
- },
- "syncstate.syncing": {
- "message": "Initialisation de la synchronisation"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Anniversaire :"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistant(e) :"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Téléphone Assistant(e) :"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Téléphone Bureau Alternatif :"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax de bureau :"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Téléphone Voiture :"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Téléphone de Bureau Principal :"
+ },
+ "abCard.Email3Address": {
+ "message": "Courriel alternatif :"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Téléphone Domicile Alternatif :"
+ },
+ "abCard.ManagerName": {
+ "message": "Supérieur(e) :"
+ },
+ "abCard.MiddleName": {
+ "message": "Deuxième prénom :"
+ },
+ "abCard.OtherAddress": {
+ "message": "Adresse :"
+ },
+ "abCard.OtherCity": {
+ "message": "Ville :"
+ },
+ "abCard.OtherCountry": {
+ "message": "Pays :"
+ },
+ "abCard.OtherState": {
+ "message": "État :"
+ },
+ "abCard.OtherZip": {
+ "message": "Code postal :"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Téléphone Radio :"
+ },
+ "abCard.Spouse": {
+ "message": "Épou(x/se) :"
+ },
+ "abCard.header.eas": {
+ "message": "Autres champs (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Téléphones domicile supplémentaires :"
+ },
+ "abCard.header.messaging": {
+ "message": "Messagerie :"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Autre Adresse (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Numéros de téléphone supplémentaires :"
+ },
+ "abCard.header.people": {
+ "message": "Personnes :"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Téléphones de bureau supplémentaires :"
+ },
+ "acl.readonly": {
+ "message": "Accès au serveur en lecture seule (annule les modifications locales)"
+ },
+ "acl.readwrite": {
+ "message": "Lecture et écriture sur le serveur"
+ },
+ "add.description": {
+ "message": "Veuillez sélectionner une des options de configuration du serveur disponibles et entrer les détails demandés. "
+ },
+ "add.name": {
+ "message": "Nom du compte :"
+ },
+ "add.ok": {
+ "message": "Ajouter un compte"
+ },
+ "add.password": {
+ "message": "Mot de passe :"
+ },
+ "add.server": {
+ "message": "Configuration du serveur :"
+ },
+ "add.shortdescription": {
+ "message": "Informations du compte"
+ },
+ "add.title": {
+ "message": "Ajout d'un compte Exchange ActiveSync à TbSync"
+ },
+ "add.url": {
+ "message": "Adresse du serveur :"
+ },
+ "add.urldescription": {
+ "message": "Il devrait suffire de fournir uniquement l'adresse de base du serveur (par exemple : mail.votreserveur.com). Cependant, il est également possible de fournir l'URL complète (par exemple : https://mail.votreserveur.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Nom d'utilisateur (adresse e-mail) :"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "annuaire global du serveur"
+ },
+ "autodiscover.Failed": {
+ "message": "L'Autodiscover pour l'utilisateur <##user##> a échoué. Soit les informations d'identification fournies étaient erronées, soit votre fournisseur ActiveSync a un problème temporaire, soit il ne prend pas en charge l'Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "L'Autodiscover a besoin d'une adresse courriel valide comme nom d'utilisateur."
+ },
+ "autodiscover.Ok": {
+ "message": "L'Autodiscover est terminée avec succès, vous pouvez maintenant vérifier les paramètres optionnels et établir la connexion de synchronisation."
+ },
+ "autodiscover.Querying": {
+ "message": "Recherche de paramètres…"
+ },
+ "config.auto": {
+ "message": "Configuration du serveur ActiveSync (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "Configuration du serveur ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "Voulez-vous vraiment SUPPRIMER DÉFINITIVEMENT le dossier « ##replace.1##» de la corbeille ?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Supprimer définitivement le dossier « ##replace.1##» de la corbeille"
+ },
+ "deletefolder.notallowed": {
+ "message": "Veuillez vous désabonner du dossier « ##replace.1##» avant d'essayer de le supprimer de la corbeille."
+ },
+ "extensionDescription": {
+ "message": "Ajouter la prise en charge de la synchronisation des comptes Exchange ActiveSync à TbSync (contacts, tâches et calendriers)."
+ },
+ "extensionName": {
+ "message": "Fournisseur pour Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Paramètres du compte"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Répondeur automatique"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Paramètres"
+ },
+ "newaccount.add_auto": {
+ "message": "Paramètres Autodiscover et ajout de compte"
+ },
+ "newaccount.add_custom": {
+ "message": "Ajouter un compte"
+ },
+ "pref.AccountName": {
+ "message": "Description"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Version d'ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID de périphérique ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Adresse du serveur"
+ },
+ "pref.ServerNameDescription": {
+ "message": "par exemple mail.votreserveur.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Afficher les dossiers trouvés dans la corbeille"
+ },
+ "pref.UserName": {
+ "message": "Nom d'utilisateur"
+ },
+ "pref.UserNameDescription": {
+ "message": "Le nom d'utilisateur est généralement l'adresse e-mail de votre compte."
+ },
+ "pref.autodetect": {
+ "message": "le meilleur disponible"
+ },
+ "pref.birthday": {
+ "message": "Envoyer la date de naissance"
+ },
+ "pref.calendaroptions": {
+ "message": "Options de calendrier"
+ },
+ "pref.contactoptions": {
+ "message": "Options des contacts"
+ },
+ "pref.displayoverride": {
+ "message": "Remplacer le nom affiché par « Prénom » + « Nom »"
+ },
+ "pref.generaloptions": {
+ "message": "Options générales"
+ },
+ "pref.provision": {
+ "message": "Forcer l'approvisionnement (requis par Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Virgule"
+ },
+ "pref.seperator.description": {
+ "message": "Séparateur pour le champ d'adresse multiligne."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Saut de ligne"
+ },
+ "pref.synclimit.1month": {
+ "message": "les 4 dernières semaines"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "les 2 dernières semaines"
+ },
+ "pref.synclimit.3month": {
+ "message": "les 3 derniers mois"
+ },
+ "pref.synclimit.6month": {
+ "message": "les 6 derniers mois"
+ },
+ "pref.synclimit.all": {
+ "message": "tout"
+ },
+ "pref.synclimit.description": {
+ "message": "Période de synchronisation : "
+ },
+ "pref.usehttps": {
+ "message": "Utiliser une connexion sécurisée (se connecter via https)"
+ },
+ "recyclebin": {
+ "message": "Corbeille"
+ },
+ "servertype.auto": {
+ "message": "Configuration automatique"
+ },
+ "servertype.custom": {
+ "message": "Configuration personnalisée"
+ },
+ "servertype.description.auto": {
+ "message": "La configuration de nombreux serveurs ActiveSync peut être découverte en fournissant uniquement votre adresse e-mail."
+ },
+ "servertype.description.custom": {
+ "message": "Configurez votre compte en fournissant manuellement l'adresse du serveur que vous souhaitez connecter."
+ },
+ "servertype.description.office365": {
+ "message": "Les comptes connectés à Office 365 utilisent un processus d'authentification moderne appelé OAuth 2.0 qui supporte également l'authentification multi-facteur (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Double-cliquez pour déverrouiller tous les paramètres prédéfinis du serveur."
+ },
+ "status.401": {
+ "message": "L'authentification a échoué. Veuillez vérifier le couple nom d'utilisateur/mot de passe (erreur HTTP 401)."
+ },
+ "status.403": {
+ "message": "Le serveur a rejeté la connexion (interdite) (Erreur HTTP 403)."
+ },
+ "status.404": {
+ "message": "Utilisateur introuvable (Erreur HTTP 404)."
+ },
+ "status.449": {
+ "message": "Le serveur demande le provisionnement (erreur HTTP 449)."
+ },
+ "status.500": {
+ "message": "Erreur serveur inconnue (Erreur HTTP 500)."
+ },
+ "status.503": {
+ "message": "Service indisponible (Erreur HTTP 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Mauvais élément ignoré : ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Impossible de supprimer un dossier système (statut 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Le dossier n'existe pas (statut 4), resynchronisation"
+ },
+ "status.FolderDelete.6": {
+ "message": "La commande n'a pas pu être terminée, une erreur est survenue sur le serveur (statut 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Clé de synchronisation invalide (statut 9), resynchronisation"
+ },
+ "status.FolderSync.9": {
+ "message": "Clé de synchronisation invalide (statut 9), resynchronisation"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Le serveur ne fournit pas d'informations sur les versions ActiveSync supportées. EAS est-il bloqué pour cet utilisateur ou ce client (TbSync) ? Vous pouvez essayer de définir manuellement la version ActiveSync."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Le serveur EAS a rejeté la dernière demande."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Le serveur EAS n'a pas accepté les éléments ##replace.1##."
+ },
+ "status.Sync.12": {
+ "message": "La hiérarchie des dossiers a changé (statut 12), resynchronisation"
+ },
+ "status.Sync.3": {
+ "message": "Clé de synchronisation invalide (statut 3), resynchronisation"
+ },
+ "status.Sync.4": {
+ "message": "Requête mal formée (statut 4)"
+ },
+ "status.Sync.5": {
+ "message": "Problèmes de serveur temporaires ou élément invalide (statut 5)"
+ },
+ "status.Sync.6": {
+ "message": "Élément invalide (statut 6)"
+ },
+ "status.Sync.8": {
+ "message": "Objet introuvable (statut 8)"
+ },
+ "status.aborted": {
+ "message": "Non synchronisé"
+ },
+ "status.disabled": {
+ "message": "Désactivé"
+ },
+ "status.empty-response": {
+ "message": "Le serveur a renvoyé une réponse vide inattendue."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Élément de calendrier interdit dans un dossier de tâche (veuillez intervenir)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Élément de calendrier interdit dans un dossier de tâche (veuillez intervenir)"
+ },
+ "status.global.101": {
+ "message": "La requête contient WBXML mais n'a pas pu être décodée en XML (EAS Error 101)."
+ },
+ "status.global.102": {
+ "message": "La requête contient WBXML mais n'a pas pu être décodée en XML (EAS Error 102)."
+ },
+ "status.global.103": {
+ "message": "Le XML fourni dans la requête ne respecte pas les exigences du protocole (EAS Error 103)."
+ },
+ "status.global.110": {
+ "message": "Le serveur a signalé une erreur interne et nous ne devrions pas réessayer immédiatement. La synchronisation périodique automatique a été désactivée pendant 30 minutes (EAS Error 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "Le serveur EAS signale <##replace.2##> (status ##replace.1##) et n'autorise pas TbSync à accéder à votre compte."
+ },
+ "status.httperror": {
+ "message": "Erreur de communication (statut HTTP ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Réponse du serveur invalide (pourriels)."
+ },
+ "status.malformed-xml": {
+ "message": "Impossible d’analyser le XML. Vérifiez le journal des événements pour plus de détails."
+ },
+ "status.modified": {
+ "message": "Modifications locales présentes"
+ },
+ "status.network": {
+ "message": "Impossible de se connecter au serveur (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "La connexion au serveur a échoué."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Le serveur ne prend pas en charge ActiveSync v2.5 ou v14.0 (seulement ##replace.1##). TbSync ne fonctionnera pas avec ce serveur ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Annulation de la synchronisation en cours : il est impossible de créer les destinations de synchronisation."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Le serveur ne prend pas en charge la sélection ActiveSync v##replace.1## (seulement ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Le compte doit être synchronisé : au moins un éléments n'est pas synchronisé."
+ },
+ "status.nouserhost": {
+ "message": "Nom d'utilisateur et/ou serveur manquant. Veuillez fournir ces valeurs."
+ },
+ "status.pending": {
+ "message": "En attente de synchronisation"
+ },
+ "status.policy.2": {
+ "message": "Il n'y a pas de politique pour ce client. Contactez l'administrateur de votre serveur ou désactivez le provisioning pour ce compte."
+ },
+ "status.policy.3": {
+ "message": "Valeur de PolicyType inconnue. Contactez l'administrateur du serveur ou désactivez le provisioning pour ce compte."
+ },
+ "status.policy.4": {
+ "message": "Les données de stratégie sur le serveur sont corrompues (potentiellement altérées). Contactez l'administrateur de votre serveur ou désactivez le provisioning pour ce compte."
+ },
+ "status.policy.5": {
+ "message": "Le client reconnaît la mauvaise clé de stratégie. Contactez l'administrateur du serveur ou désactivez le provisioning pour ce compte."
+ },
+ "status.provision": {
+ "message": "Le provisioning a échoué avec le statut <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "La réponse du serveur ne contient aucune donnée."
+ },
+ "status.resync-loop": {
+ "message": "Il y a eu une erreur à partir de laquelle nous n'avons pas pu rétablir la situation en resynchronisant le compte. Veuillez désactiver le compte et réessayer. (Erreur : boucle de resynchronisation)"
+ },
+ "status.security": {
+ "message": "Impossible d'établir une connexion sécurisée. Utilisez-vous un certificat auto-signé ou autrement non fiable sans l'importer dans Thunderbird ? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Pas encore pris en charge, ignoré"
+ },
+ "status.syncing": {
+ "message": "Synchronisation en cours"
+ },
+ "status.timeout": {
+ "message": "Délai de communication expiré."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Le serveur envoie une réponse illisible."
+ },
+ "status.wbxmlerror": {
+ "message": "La synchronisation a échoué. Le serveur a répondu avec le statut <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Violation du protocole ActiveSync : le champ obligatoire <##replace.1##> est absent de la réponse du serveur."
+ },
+ "syncstate.accountdone": {
+ "message": "Synchronisation du compte terminée"
+ },
+ "syncstate.done": {
+ "message": "Préparation du prochain élément pour la synchronisation"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Traitement des paramètres du serveur mis à jour"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Dossier supprimé"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Traitement de l'estimation des changements"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Mise à jour de la liste des dossiers en cours de traitement"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Traitement de la confirmation de réception des modifications locales"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Traitement de la confirmation de réception des suppressions locales"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Traitement des options du serveur"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Traitement de la provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Traitement des modifications à distance"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Rétablissement des modification locales"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Envoi des informations de l'appareil"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Traitement de la clé de synchronisation"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Demande de mise à jour des paramètres du serveur"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Préparation de la suppression du dossier"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Demande de l'estimation des changements"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Envoi de la mise à jour de la liste de dossiers"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Envoi des modifications locales"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Envoi des suppressions locales"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Demande des options du serveur"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Demande de provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Traitement des modifications à distance"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Collecte des modifications locales"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Envoi des informations de l'appareil"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Demande de clé de synchronisation"
+ },
+ "syncstate.preparing": {
+ "message": "Préparation du prochain élément pour la synchronisation"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "En attente de mise à jour des paramètres du serveur"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "En attente de la suppression du dossier"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "En attente de l'estimation des changements"
+ },
+ "syncstate.send.request.folders": {
+ "message": "En attente de mise à jour de la liste des dossiers"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "En attente de la confirmation de réception des modifications locales"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "En attente de la confirmation de réception des suppressions locales"
+ },
+ "syncstate.send.request.options": {
+ "message": "En attente des options du serveur"
+ },
+ "syncstate.send.request.provision": {
+ "message": "En attente de provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "En attente des modifications à distance"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "En attente des versions les plus récentes"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Envoi des informations de l'appareil"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "En attente de clé de synchronisation"
+ },
+ "syncstate.syncing": {
+ "message": "Initialisation de la synchronisation"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/gl/messages.json eas4tbsync-4.17/_locales/gl/messages.json
--- eas4tbsync-4.11/_locales/gl/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/gl/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Aniversario:"
- },
- "abCard.AssistantName": {
- "message": "Asistente:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Teléfono do asistente:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Teléfono alternativo do traballo:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax do traballo:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Teléfono do coche:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Teléfono principal do traballo:"
- },
- "abCard.Email3Address": {
- "message": "Correo electrónico alternativo:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Teléfono de casa alternativo:"
- },
- "abCard.ManagerName": {
- "message": "Supervisor:"
- },
- "abCard.MiddleName": {
- "message": "Segundo nome:"
- },
- "abCard.OtherAddress": {
- "message": "Enderezo:"
- },
- "abCard.OtherCity": {
- "message": "Cidade:"
- },
- "abCard.OtherCountry": {
- "message": "País:"
- },
- "abCard.OtherState": {
- "message": "Estado:"
- },
- "abCard.OtherZip": {
- "message": "Código postal:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radioteléfóno:"
- },
- "abCard.Spouse": {
- "message": "Cónxuxe:"
- },
- "abCard.header.eas": {
- "message": "Outros campos (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Números adicionais de casa:"
- },
- "abCard.header.messaging": {
- "message": "Mensaxería:"
- },
- "abCard.header.otheraddress": {
- "message": "Outros enderezos (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Números adicionais:"
- },
- "abCard.header.people": {
- "message": "Persoas:"
- },
- "abCard.header.worknumbers": {
- "message": "Números adicionais do traballo:"
- },
- "acl.readonly": {
- "message": "Acceso só de lectura ao servidor (reverter cambios locais)"
- },
- "acl.readwrite": {
- "message": "Leer e escribir no servidor"
- },
- "add.description": {
- "message": "Por favor, selecciona unha das opcións de configuración do servidor e insire os detalles solicitados. "
- },
- "add.name": {
- "message": "Nome da conta:"
- },
- "add.ok": {
- "message": "Engadir conta"
- },
- "add.password": {
- "message": "Contrasinal:"
- },
- "add.server": {
- "message": "Configuración do servidor:"
- },
- "add.shortdescription": {
- "message": "Información da conta"
- },
- "add.title": {
- "message": "Engadindo unha conta Exchange ActiveSync a TbSync"
- },
- "add.url": {
- "message": "Enderezo do servidor:"
- },
- "add.urldescription": {
- "message": "Debería de ser suficiente con proporcionar só o enderezo básico do servidor (por exemplo, correo.dominio.gal). Con todo, tamén é posible facilitar o URL completo (por exemplo, https://correo.dominio.gal/Servidor-Microsoft-ActiveSync)."
- },
- "add.user": {
- "message": "Nome de usuario (enderezo de correo electrónico):"
- },
- "autocomplete.serverdirectory": {
- "message": "directorio global de servidores"
- },
- "autodiscover.Failed": {
- "message": "Fallou o Autodiscover para o usuario <##user##>. Ou ben proporcionaches unhas credenciais erróneas ou ben o teu provedor de ActiveSync ten un problema temporal, ou ben non admite o Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "Autodiscover precisa dun enderezo de correo electónico válido como nome de usuario."
- },
- "autodiscover.Ok": {
- "message": "Autodiscover completouse correctamente; agora podes revisar os axustes opcionais e establecer a conexión de sincronización."
- },
- "autodiscover.Querying": {
- "message": "Buscando os axustes…"
- },
- "config.auto": {
- "message": "Configuración do servidor de ActiveSync (Autodiscover)"
- },
- "config.custom": {
- "message": "Configuración do servidor de ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "Queres ELIMINAR DEFINITIVAMENTE o cartafol “##replace.1##” da papeleira?"
- },
- "deletefolder.menuentry": {
- "message": "Eliminar definitivamente o cartafol “##replace.1##” da papeleira"
- },
- "deletefolder.notallowed": {
- "message": "Por favor, cancela a subscrición ao cartafol “##replace.1##” antes de intentar eliminalo da papeleira."
- },
- "extensionDescription": {
- "message": "Engade soporte a TbSync para a sincronización de contas de Exchange ActiveSync (contactos, tarefas e calendarios)."
- },
- "extensionName": {
- "message": "Provedor de Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Axustes da conta"
- },
- "manager.tabs.outOfOffice": {
- "message": "Resposta automática"
- },
- "manager.tabs.syncsettings": {
- "message": "Opcións"
- },
- "newaccount.add_auto": {
- "message": "Axustes de Autodiscover e engadir conta"
- },
- "newaccount.add_custom": {
- "message": "Engadir conta"
- },
- "pref.AccountName": {
- "message": "Descrición"
- },
- "pref.ActiveSyncVersion": {
- "message": "Versión de ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID de dispositivo de ActiveSync"
- },
- "pref.ServerName": {
- "message": "Enderezo do servidor"
- },
- "pref.ServerNameDescription": {
- "message": "por exemplo, correo.dominio.gal"
- },
- "pref.ShowTrashedFolders": {
- "message": "Amosar cartafois atopados na papeleira"
- },
- "pref.UserName": {
- "message": "Nome de usuario"
- },
- "pref.UserNameDescription": {
- "message": "O nome de usuario adoita ser o enderezo de correo electrónico da túa conta."
- },
- "pref.autodetect": {
- "message": "mellor dispoñible"
- },
- "pref.birthday": {
- "message": "Enviar información do aniversario"
- },
- "pref.calendaroptions": {
- "message": "Opcións do calendario"
- },
- "pref.contactoptions": {
- "message": "Opcións dos contactos"
- },
- "pref.displayoverride": {
- "message": "Substituír o nome amosado por «Nome» + «Segundo nome»"
- },
- "pref.generaloptions": {
- "message": "Opcións xerais"
- },
- "pref.provision": {
- "message": "Forzar aprovisionamento (requirido por Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Coma"
- },
- "pref.seperator.description": {
- "message": "Separador de campo de enderezo en varias liñas."
- },
- "pref.seperator.linebreak": {
- "message": "Salto de liña"
- },
- "pref.synclimit.1month": {
- "message": "desde hai 4 semanas"
- },
- "pref.synclimit.2weeks": {
- "message": "desde hai 2 semanas"
- },
- "pref.synclimit.3month": {
- "message": "desde hai 3 meses"
- },
- "pref.synclimit.6month": {
- "message": "desde hai 6 meses"
- },
- "pref.synclimit.all": {
- "message": "todo"
- },
- "pref.synclimit.description": {
- "message": "Período de sincronización: "
- },
- "pref.usehttps": {
- "message": "Usar conexión segura (conectar mediante https)"
- },
- "recyclebin": {
- "message": "Papeleira"
- },
- "servertype.auto": {
- "message": "Configuración automática"
- },
- "servertype.custom": {
- "message": "Configuración personalizada"
- },
- "servertype.description.auto": {
- "message": "É posible detectar a configuración de moitos servidores ActiveSync con só proporcionar o teu enderezo de correo electrónico."
- },
- "servertype.description.custom": {
- "message": "Configura a conta proporciando manualmente o enderezo do servidor ao que queres conectar."
- },
- "servertype.description.office365": {
- "message": "As contas conectadas a Office 365 utilizan un proceso de autenticación moderno, chamado OAuth 2.0, que tamén admite autenticación multifactor (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Fai dobre clic para desbloquear todos os axustes predefinidos do servidor."
- },
- "status.401": {
- "message": "Non foi posible autenticarse, comproba o nome de usuario e o contrasinal (erro HTTP 401)."
- },
- "status.403": {
- "message": "O servidor rexeitou a conexión (prohibida) (erro HTTP 403)."
- },
- "status.404": {
- "message": "Usuario non atopado (erro HTTP 404)."
- },
- "status.449": {
- "message": "O servidor solicita aprovisionamento (erro HTTP 449)."
- },
- "status.500": {
- "message": "Erro descoñecido do servidor (erro HTTP 500)."
- },
- "status.503": {
- "message": "Servicio non dispoñible (erro HTTP 503)."
- },
- "status.BadItemSkipped": {
- "message": "Omitido obxecto incorrecto: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Non é posible eliminar un cartafol do sistema (estado 3)"
- },
- "status.FolderDelete.4": {
- "message": "O cartafol non existe (estado 4), resincronizando"
- },
- "status.FolderDelete.6": {
- "message": "O comando non se completou, produciuse un erro no servidor (estado 6)"
- },
- "status.FolderDelete.9": {
- "message": "Chave de sincronización non válida (estado 9), resincronizando"
- },
- "status.FolderSync.9": {
- "message": "Chave de sincronización non válida (estado 9), resincronizando"
- },
- "status.InvalidServerOptions": {
- "message": "El servidor non proporciona información sobre as versións de ActiveSync compatibles. Está EAS bloqueado para este usuario ou para este cliente (TbSync)? Podes intentar establecer a versión de ActiveSync manualmente."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "O servidor de EAS rexeitou a última petición."
- },
- "status.ServerRejectedSomeItems": {
- "message": "O servidor de EAS non aceptou ##replace.1## elementos."
- },
- "status.Sync.12": {
- "message": "Cambiou a xerarquía de cartafois (estado 12), resincronizando"
- },
- "status.Sync.3": {
- "message": "Chave de sincronización non válida (estado 3), resincronizando"
- },
- "status.Sync.4": {
- "message": "Solicitude mal formada (estado 4)"
- },
- "status.Sync.5": {
- "message": "Problemas temporais do servidor ou elemento non válido (estado 5)"
- },
- "status.Sync.6": {
- "message": "Elemento non válido (estado 6)"
- },
- "status.Sync.8": {
- "message": "Obxecto non atopado (estado 8)"
- },
- "status.aborted": {
- "message": "Sen sincronizar"
- },
- "status.disabled": {
- "message": "Desactivado"
- },
- "status.empty-response": {
- "message": "O servidor envía unha resposta baleira non esperada."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Elemento do calendario prohibido nun cartafol de tarefas (por favor, reorganiza)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Elemento de tarefas prohibido nun cartafol do calendario (por favor, reorganiza)"
- },
- "status.global.101": {
- "message": "A solicitude contén WBXML pero non puido ser descodificado a XML (erro EAS 101)."
- },
- "status.global.102": {
- "message": "A solicitude contén WBXML pero non puido ser descodificado a XML (erro EAS 102)."
- },
- "status.global.103": {
- "message": "O XML proporcionado na solicitude non cumple os requirimentos do protocolo (erro EAS 103)."
- },
- "status.global.110": {
- "message": "O servidor informou dun erro interno e non deberías reconectar de inmediato. Desactivouse a sincronización periódica automática durante 30 minutos (erro EAS 110)."
- },
- "status.global.clientdenied": {
- "message": "O servidor EAS notifica <##replace.2##> (estado ##replace.1##) e non permite que TbSync acceda á túa conta."
- },
- "status.httperror": {
- "message": "Erro de comunicación (estado HTTP ##replace.1##)."
- },
- "status.invalid": {
- "message": "Resposta do servidor non válida (corrompida)."
- },
- "status.malformed-xml": {
- "message": "Non se puido analizar o XML. Revisa o rexistro de eventos para dispor de máis detalles."
- },
- "status.modified": {
- "message": "Modificacións locais"
- },
- "status.network": {
- "message": "Non se puido conectar ao servidor (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Non se puido conectar ao servidor."
- },
- "status.nosupportedeasversion": {
- "message": "O servidor non é compatible con ActiveSync v2.5 ou v14.0 (só ##replace.1##). TbSync non funcionará con este servidor de ActiveSync."
- },
- "status.notargets": {
- "message": "Sincronización interrompida porque no se puideron crear os destinos da sincronización."
- },
- "status.notsupportedeasversion": {
- "message": "O servidor non é compatible con ActiveSync v##replace.1## (só ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "É preciso sincronizar a conta: hai algún un elemento sen sincronizar."
- },
- "status.nouserhost": {
- "message": "Falta o nome de usuario ou o servidor. Por favor, proporciona eses datos."
- },
- "status.pending": {
- "message": "Agardando pola sincronización"
- },
- "status.policy.2": {
- "message": "Non hai ningunha directiva para este cliente. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
- },
- "status.policy.3": {
- "message": "Valor de PolicyType descoñecido. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
- },
- "status.policy.4": {
- "message": "Os datos de directivas do servidor están danados (posiblemente manipulados). Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
- },
- "status.policy.5": {
- "message": "O cliente está a recoñecer a chave de directiva incorrecta. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
- },
- "status.provision": {
- "message": "O aprovisionamento fallou co estado <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "A resposta do servidor non contén datos."
- },
- "status.resync-loop": {
- "message": "Produciuse un erro que non se puido corrixir volvendo a sincronizar a conta. Desactiva a conta e inténtao outra vez (erro: bucle de resincronización)"
- },
- "status.security": {
- "message": "No se puido establecer unha conexión segura. Estás a usar un certificado autofirmado, ou que non é de confianza, sen importarlo a Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Aínda non soportado, omitido"
- },
- "status.syncing": {
- "message": "Sincronizando"
- },
- "status.timeout": {
- "message": "Tempo de comunicación esgotado."
- },
- "status.wbxml-parse-error": {
- "message": "O servidor envía unha resposta ilexible."
- },
- "status.wbxmlerror": {
- "message": "Erro ao sincronizar. O servidor respondeu co estado <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Violación do protocolo de ActiveSync: falta o campo obrigatorio <##replace.1##> na respuesta do servidor."
- },
- "syncstate.accountdone": {
- "message": "Conta rematada"
- },
- "syncstate.done": {
- "message": "Preparando o seguinte elemento para a sincronización"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Procesando os axustes do servidor actualizados"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Cartafol eliminado"
- },
- "syncstate.eval.response.estimate": {
- "message": "Procesando a estimación do cambio"
- },
- "syncstate.eval.response.folders": {
- "message": "Procesando a lista de cartafois actualizada"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Procesando o recoñecemento de cambios locais"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Procesando o recoñecemento de eliminacións locais"
- },
- "syncstate.eval.response.options": {
- "message": "Procesando as opcións do servidor"
- },
- "syncstate.eval.response.provision": {
- "message": "Procesando o aprovisionamento"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Procesando os cambios remotos"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Revertendo os cambios locais"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Enviando información do dispositivo"
- },
- "syncstate.eval.response.synckey": {
- "message": "Procesando SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Solicitando axustes actualizados do servidor"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparando a elimanción do cartafol"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Solicitando a estimación dos cambios"
- },
- "syncstate.prepare.request.folders": {
- "message": "Enviando a actualización da lista de cartafois"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Enviando os cambios locais"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Enviando as eliminacións locais"
- },
- "syncstate.prepare.request.options": {
- "message": "Solicitando as opcións do servidor"
- },
- "syncstate.prepare.request.provision": {
- "message": "Solicitando o aprovisionamento"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Solicitando os cambios remotos"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Recolectando os cambios locais"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Enviando información do dispositivo"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Solicitando SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparando o seguinte elemento para a sincronización"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Agardando polos axustes actualizados do servidor"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Agardando pola eliminación do cartafol"
- },
- "syncstate.send.request.estimate": {
- "message": "Agardando pola estimación de cambios"
- },
- "syncstate.send.request.folders": {
- "message": "Agardando pola actualización da lista de cartafois"
- },
- "syncstate.send.request.localchanges": {
- "message": "Agardando polo recoñecemento de cambios locais"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Agardando polo recoñecemento de eliminacións locais"
- },
- "syncstate.send.request.options": {
- "message": "Agardando polas opcións do servidor"
- },
- "syncstate.send.request.provision": {
- "message": "Agardando polo aprovisionamento"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Agardando polos cambios remotos"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Agardando polas versións máis recentes"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Enviando información do dispositivo"
- },
- "syncstate.send.request.synckey": {
- "message": "Agardando por SyncKey"
- },
- "syncstate.syncing": {
- "message": "Iniciar sincronización"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Aniversario:"
+ },
+ "abCard.AssistantName": {
+ "message": "Asistente:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Teléfono do asistente:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Teléfono alternativo do traballo:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax do traballo:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Teléfono do coche:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Teléfono principal do traballo:"
+ },
+ "abCard.Email3Address": {
+ "message": "Correo electrónico alternativo:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Teléfono de casa alternativo:"
+ },
+ "abCard.ManagerName": {
+ "message": "Supervisor:"
+ },
+ "abCard.MiddleName": {
+ "message": "Segundo nome:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Enderezo:"
+ },
+ "abCard.OtherCity": {
+ "message": "Cidade:"
+ },
+ "abCard.OtherCountry": {
+ "message": "País:"
+ },
+ "abCard.OtherState": {
+ "message": "Estado:"
+ },
+ "abCard.OtherZip": {
+ "message": "Código postal:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radioteléfóno:"
+ },
+ "abCard.Spouse": {
+ "message": "Cónxuxe:"
+ },
+ "abCard.header.eas": {
+ "message": "Outros campos (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Números adicionais de casa:"
+ },
+ "abCard.header.messaging": {
+ "message": "Mensaxería:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Outros enderezos (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Números adicionais:"
+ },
+ "abCard.header.people": {
+ "message": "Persoas:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Números adicionais do traballo:"
+ },
+ "acl.readonly": {
+ "message": "Acceso só de lectura ao servidor (reverter cambios locais)"
+ },
+ "acl.readwrite": {
+ "message": "Leer e escribir no servidor"
+ },
+ "add.description": {
+ "message": "Por favor, selecciona unha das opcións de configuración do servidor e insire os detalles solicitados. "
+ },
+ "add.name": {
+ "message": "Nome da conta:"
+ },
+ "add.ok": {
+ "message": "Engadir conta"
+ },
+ "add.password": {
+ "message": "Contrasinal:"
+ },
+ "add.server": {
+ "message": "Configuración do servidor:"
+ },
+ "add.shortdescription": {
+ "message": "Información da conta"
+ },
+ "add.title": {
+ "message": "Engadindo unha conta Exchange ActiveSync a TbSync"
+ },
+ "add.url": {
+ "message": "Enderezo do servidor:"
+ },
+ "add.urldescription": {
+ "message": "Debería de ser suficiente con proporcionar só o enderezo básico do servidor (por exemplo, correo.dominio.gal). Con todo, tamén é posible facilitar o URL completo (por exemplo, https://correo.dominio.gal/Servidor-Microsoft-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Nome de usuario (enderezo de correo electrónico):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "directorio global de servidores"
+ },
+ "autodiscover.Failed": {
+ "message": "Fallou o Autodiscover para o usuario <##user##>. Ou ben proporcionaches unhas credenciais erróneas ou ben o teu provedor de ActiveSync ten un problema temporal, ou ben non admite o Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Autodiscover precisa dun enderezo de correo electónico válido como nome de usuario."
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover completouse correctamente; agora podes revisar os axustes opcionais e establecer a conexión de sincronización."
+ },
+ "autodiscover.Querying": {
+ "message": "Buscando os axustes…"
+ },
+ "config.auto": {
+ "message": "Configuración do servidor de ActiveSync (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "Configuración do servidor de ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "Queres ELIMINAR DEFINITIVAMENTE o cartafol “##replace.1##” da papeleira?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Eliminar definitivamente o cartafol “##replace.1##” da papeleira"
+ },
+ "deletefolder.notallowed": {
+ "message": "Por favor, cancela a subscrición ao cartafol “##replace.1##” antes de intentar eliminalo da papeleira."
+ },
+ "extensionDescription": {
+ "message": "Engade soporte a TbSync para a sincronización de contas de Exchange ActiveSync (contactos, tarefas e calendarios)."
+ },
+ "extensionName": {
+ "message": "Provedor de Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Axustes da conta"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Resposta automática"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Opcións"
+ },
+ "newaccount.add_auto": {
+ "message": "Axustes de Autodiscover e engadir conta"
+ },
+ "newaccount.add_custom": {
+ "message": "Engadir conta"
+ },
+ "pref.AccountName": {
+ "message": "Descrición"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Versión de ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID de dispositivo de ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Enderezo do servidor"
+ },
+ "pref.ServerNameDescription": {
+ "message": "por exemplo, correo.dominio.gal"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Amosar cartafois atopados na papeleira"
+ },
+ "pref.UserName": {
+ "message": "Nome de usuario"
+ },
+ "pref.UserNameDescription": {
+ "message": "O nome de usuario adoita ser o enderezo de correo electrónico da túa conta."
+ },
+ "pref.autodetect": {
+ "message": "mellor dispoñible"
+ },
+ "pref.birthday": {
+ "message": "Enviar información do aniversario"
+ },
+ "pref.calendaroptions": {
+ "message": "Opcións do calendario"
+ },
+ "pref.contactoptions": {
+ "message": "Opcións dos contactos"
+ },
+ "pref.displayoverride": {
+ "message": "Substituír o nome amosado por «Nome» + «Segundo nome»"
+ },
+ "pref.generaloptions": {
+ "message": "Opcións xerais"
+ },
+ "pref.provision": {
+ "message": "Forzar aprovisionamento (requirido por Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Coma"
+ },
+ "pref.seperator.description": {
+ "message": "Separador de campo de enderezo en varias liñas."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Salto de liña"
+ },
+ "pref.synclimit.1month": {
+ "message": "desde hai 4 semanas"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "desde hai 2 semanas"
+ },
+ "pref.synclimit.3month": {
+ "message": "desde hai 3 meses"
+ },
+ "pref.synclimit.6month": {
+ "message": "desde hai 6 meses"
+ },
+ "pref.synclimit.all": {
+ "message": "todo"
+ },
+ "pref.synclimit.description": {
+ "message": "Período de sincronización: "
+ },
+ "pref.usehttps": {
+ "message": "Usar conexión segura (conectar mediante https)"
+ },
+ "recyclebin": {
+ "message": "Papeleira"
+ },
+ "servertype.auto": {
+ "message": "Configuración automática"
+ },
+ "servertype.custom": {
+ "message": "Configuración personalizada"
+ },
+ "servertype.description.auto": {
+ "message": "É posible detectar a configuración de moitos servidores ActiveSync con só proporcionar o teu enderezo de correo electrónico."
+ },
+ "servertype.description.custom": {
+ "message": "Configura a conta proporciando manualmente o enderezo do servidor ao que queres conectar."
+ },
+ "servertype.description.office365": {
+ "message": "As contas conectadas a Office 365 utilizan un proceso de autenticación moderno, chamado OAuth 2.0, que tamén admite autenticación multifactor (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Fai dobre clic para desbloquear todos os axustes predefinidos do servidor."
+ },
+ "status.401": {
+ "message": "Non foi posible autenticarse, comproba o nome de usuario e o contrasinal (erro HTTP 401)."
+ },
+ "status.403": {
+ "message": "O servidor rexeitou a conexión (prohibida) (erro HTTP 403)."
+ },
+ "status.404": {
+ "message": "Usuario non atopado (erro HTTP 404)."
+ },
+ "status.449": {
+ "message": "O servidor solicita aprovisionamento (erro HTTP 449)."
+ },
+ "status.500": {
+ "message": "Erro descoñecido do servidor (erro HTTP 500)."
+ },
+ "status.503": {
+ "message": "Servicio non dispoñible (erro HTTP 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Omitido obxecto incorrecto: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Non é posible eliminar un cartafol do sistema (estado 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "O cartafol non existe (estado 4), resincronizando"
+ },
+ "status.FolderDelete.6": {
+ "message": "O comando non se completou, produciuse un erro no servidor (estado 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Chave de sincronización non válida (estado 9), resincronizando"
+ },
+ "status.FolderSync.9": {
+ "message": "Chave de sincronización non válida (estado 9), resincronizando"
+ },
+ "status.InvalidServerOptions": {
+ "message": "El servidor non proporciona información sobre as versións de ActiveSync compatibles. Está EAS bloqueado para este usuario ou para este cliente (TbSync)? Podes intentar establecer a versión de ActiveSync manualmente."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "O servidor de EAS rexeitou a última petición."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "O servidor de EAS non aceptou ##replace.1## elementos."
+ },
+ "status.Sync.12": {
+ "message": "Cambiou a xerarquía de cartafois (estado 12), resincronizando"
+ },
+ "status.Sync.3": {
+ "message": "Chave de sincronización non válida (estado 3), resincronizando"
+ },
+ "status.Sync.4": {
+ "message": "Solicitude mal formada (estado 4)"
+ },
+ "status.Sync.5": {
+ "message": "Problemas temporais do servidor ou elemento non válido (estado 5)"
+ },
+ "status.Sync.6": {
+ "message": "Elemento non válido (estado 6)"
+ },
+ "status.Sync.8": {
+ "message": "Obxecto non atopado (estado 8)"
+ },
+ "status.aborted": {
+ "message": "Sen sincronizar"
+ },
+ "status.disabled": {
+ "message": "Desactivado"
+ },
+ "status.empty-response": {
+ "message": "O servidor envía unha resposta baleira non esperada."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Elemento do calendario prohibido nun cartafol de tarefas (por favor, reorganiza)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Elemento de tarefas prohibido nun cartafol do calendario (por favor, reorganiza)"
+ },
+ "status.global.101": {
+ "message": "A solicitude contén WBXML pero non puido ser descodificado a XML (erro EAS 101)."
+ },
+ "status.global.102": {
+ "message": "A solicitude contén WBXML pero non puido ser descodificado a XML (erro EAS 102)."
+ },
+ "status.global.103": {
+ "message": "O XML proporcionado na solicitude non cumple os requirimentos do protocolo (erro EAS 103)."
+ },
+ "status.global.110": {
+ "message": "O servidor informou dun erro interno e non deberías reconectar de inmediato. Desactivouse a sincronización periódica automática durante 30 minutos (erro EAS 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "O servidor EAS notifica <##replace.2##> (estado ##replace.1##) e non permite que TbSync acceda á túa conta."
+ },
+ "status.httperror": {
+ "message": "Erro de comunicación (estado HTTP ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Resposta do servidor non válida (corrompida)."
+ },
+ "status.malformed-xml": {
+ "message": "Non se puido analizar o XML. Revisa o rexistro de eventos para dispor de máis detalles."
+ },
+ "status.modified": {
+ "message": "Modificacións locais"
+ },
+ "status.network": {
+ "message": "Non se puido conectar ao servidor (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Non se puido conectar ao servidor."
+ },
+ "status.nosupportedeasversion": {
+ "message": "O servidor non é compatible con ActiveSync v2.5 ou v14.0 (só ##replace.1##). TbSync non funcionará con este servidor de ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Sincronización interrompida porque no se puideron crear os destinos da sincronización."
+ },
+ "status.notsupportedeasversion": {
+ "message": "O servidor non é compatible con ActiveSync v##replace.1## (só ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "É preciso sincronizar a conta: hai algún un elemento sen sincronizar."
+ },
+ "status.nouserhost": {
+ "message": "Falta o nome de usuario ou o servidor. Por favor, proporciona eses datos."
+ },
+ "status.pending": {
+ "message": "Agardando pola sincronización"
+ },
+ "status.policy.2": {
+ "message": "Non hai ningunha directiva para este cliente. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
+ },
+ "status.policy.3": {
+ "message": "Valor de PolicyType descoñecido. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
+ },
+ "status.policy.4": {
+ "message": "Os datos de directivas do servidor están danados (posiblemente manipulados). Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
+ },
+ "status.policy.5": {
+ "message": "O cliente está a recoñecer a chave de directiva incorrecta. Contacta co administrador do servidor ou desactiva o aprovisionamento desta conta."
+ },
+ "status.provision": {
+ "message": "O aprovisionamento fallou co estado <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "A resposta do servidor non contén datos."
+ },
+ "status.resync-loop": {
+ "message": "Produciuse un erro que non se puido corrixir volvendo a sincronizar a conta. Desactiva a conta e inténtao outra vez (erro: bucle de resincronización)"
+ },
+ "status.security": {
+ "message": "No se puido establecer unha conexión segura. Estás a usar un certificado autofirmado, ou que non é de confianza, sen importarlo a Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Aínda non soportado, omitido"
+ },
+ "status.syncing": {
+ "message": "Sincronizando"
+ },
+ "status.timeout": {
+ "message": "Tempo de comunicación esgotado."
+ },
+ "status.wbxml-parse-error": {
+ "message": "O servidor envía unha resposta ilexible."
+ },
+ "status.wbxmlerror": {
+ "message": "Erro ao sincronizar. O servidor respondeu co estado <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Violación do protocolo de ActiveSync: falta o campo obrigatorio <##replace.1##> na respuesta do servidor."
+ },
+ "syncstate.accountdone": {
+ "message": "Conta rematada"
+ },
+ "syncstate.done": {
+ "message": "Preparando o seguinte elemento para a sincronización"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Procesando os axustes do servidor actualizados"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Cartafol eliminado"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Procesando a estimación do cambio"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Procesando a lista de cartafois actualizada"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Procesando o recoñecemento de cambios locais"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Procesando o recoñecemento de eliminacións locais"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Procesando as opcións do servidor"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Procesando o aprovisionamento"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Procesando os cambios remotos"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Revertendo os cambios locais"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Enviando información do dispositivo"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Procesando SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Solicitando axustes actualizados do servidor"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparando a elimanción do cartafol"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Solicitando a estimación dos cambios"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Enviando a actualización da lista de cartafois"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Enviando os cambios locais"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Enviando as eliminacións locais"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Solicitando as opcións do servidor"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Solicitando o aprovisionamento"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Solicitando os cambios remotos"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Recolectando os cambios locais"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Enviando información do dispositivo"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Solicitando SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparando o seguinte elemento para a sincronización"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Agardando polos axustes actualizados do servidor"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Agardando pola eliminación do cartafol"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Agardando pola estimación de cambios"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Agardando pola actualización da lista de cartafois"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Agardando polo recoñecemento de cambios locais"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Agardando polo recoñecemento de eliminacións locais"
+ },
+ "syncstate.send.request.options": {
+ "message": "Agardando polas opcións do servidor"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Agardando polo aprovisionamento"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Agardando polos cambios remotos"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Agardando polas versións máis recentes"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Enviando información do dispositivo"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Agardando por SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Iniciar sincronización"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/hu/messages.json eas4tbsync-4.17/_locales/hu/messages.json
--- eas4tbsync-4.11/_locales/hu/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/hu/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Évforduló:"
- },
- "abCard.AssistantName": {
- "message": "Asszisztens:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Asszisztensi telefon:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "2. munkahelyi telefon:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Munkahelyi fax:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Autóstelefon:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Fő munkahelyi telefon:"
- },
- "abCard.Email3Address": {
- "message": "Másodlagos e-mail:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "2. otthoni telefon:"
- },
- "abCard.ManagerName": {
- "message": "Vezető:"
- },
- "abCard.MiddleName": {
- "message": "Második keresztnév:"
- },
- "abCard.OtherAddress": {
- "message": "Cím:"
- },
- "abCard.OtherCity": {
- "message": "Város:"
- },
- "abCard.OtherCountry": {
- "message": "Ország:"
- },
- "abCard.OtherState": {
- "message": "Állam/tartomány:"
- },
- "abCard.OtherZip": {
- "message": "Irányítószám:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Rádió-távbeszélő:"
- },
- "abCard.Spouse": {
- "message": "Házastárs:"
- },
- "abCard.header.eas": {
- "message": "Egyéb mezők (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "További otthoni számok:"
- },
- "abCard.header.messaging": {
- "message": "Üzenetek:"
- },
- "abCard.header.otheraddress": {
- "message": "Egyéb cím (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "További számok:"
- },
- "abCard.header.people": {
- "message": "Emberek:"
- },
- "abCard.header.worknumbers": {
- "message": "További munkahelyi számok:"
- },
- "acl.readonly": {
- "message": "Csak olvasható hozzáférés (helyi változások visszavonása)"
- },
- "acl.readwrite": {
- "message": "Olvasás és írás a kiszolgálón"
- },
- "add.description": {
- "message": "Válasszon az elérhető kiszolgálóbeállítások közül, és adja meg a kért részleteket. "
- },
- "add.name": {
- "message": "Felhasználónév:"
- },
- "add.ok": {
- "message": "Fiók hozzáadása"
- },
- "add.password": {
- "message": "Jelszó:"
- },
- "add.server": {
- "message": "Kiszolgálóbeállítások:"
- },
- "add.shortdescription": {
- "message": "Fiókadatok"
- },
- "add.title": {
- "message": "Exchange ActiveSync-fiók hozzáadása a TbSynchez"
- },
- "add.url": {
- "message": "Kiszolgáló címe:"
- },
- "add.urldescription": {
- "message": "Elégséges, ha csak az alap kiszolgálócímet adja meg (például: posta.kiszolgálód.hu). De a teljes URL-t is megadhatja (például: https://posta.kiszolgálód.hu/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Felhasználónév (e-mail-cím):"
- },
- "autocomplete.serverdirectory": {
- "message": "globális kiszolgálójegyzék"
- },
- "autodiscover.Failed": {
- "message": "A(z) <##user##> felhasználó automatikus felderítése sikertelen. Vagy hibásak voltak a megadott hitelesítő adatok, vagy az ActiveSync szolgáltató ideiglenes problémákat tapasztal, vagy nem támogatja az automatikus felderítést."
- },
- "autodiscover.NeedEmail": {
- "message": "Az önműködő felismerésnek érvényes e-mail címnek kell lennie felhasználói névként."
- },
- "autodiscover.Ok": {
- "message": "Az önműködő felderítés sikeresen befejeződött, most ellenőrizheti az választható beállításokat és létrehozhatja az összehangolási kapcsolatot."
- },
- "autodiscover.Querying": {
- "message": "Beállítások keresése…"
- },
- "config.auto": {
- "message": "Az ActiveSync kiszolgáló beállítások (önműködő észlelés)"
- },
- "config.custom": {
- "message": "Az ActiveSync kiszolgáló beállítások"
- },
- "deletefolder.confirm": {
- "message": "Tényleg azt szeretné, hogy a(z) „##replace.1##” mappa véglegesen törölje a kukát?"
- },
- "deletefolder.menuentry": {
- "message": "„##replace.1##” mappa kuka ürítése"
- },
- "deletefolder.notallowed": {
- "message": "Kérjük, törölje le a(z) „##replace.1##” mappát, mielőtt megpróbálnánk kuka ürítése."
- },
- "extensionDescription": {
- "message": "Az Exchange ActiveSync-fiókok szinkronizálásának támogatása a TbSyncben (névjegyek, feladatok és naptárak)."
- },
- "extensionName": {
- "message": "Exchange ActiveSync-szolgáltató"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Fiókbeállítások"
- },
- "manager.tabs.outOfOffice": {
- "message": "Automatikus válasz"
- },
- "manager.tabs.syncsettings": {
- "message": "Beállítások"
- },
- "newaccount.add_auto": {
- "message": "Automatikus felfedezés beállításai és fiók hozzáadása"
- },
- "newaccount.add_custom": {
- "message": "Fiók hozzáadása"
- },
- "pref.AccountName": {
- "message": "Leírás"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync verzió"
- },
- "pref.DeviceId": {
- "message": "ActiveSync eszközazonosító"
- },
- "pref.ServerName": {
- "message": "Kiszolgáló címe"
- },
- "pref.ServerNameDescription": {
- "message": "például: posta.kiszolgálód.hu"
- },
- "pref.ShowTrashedFolders": {
- "message": "A kukában található mappák megjelenítése"
- },
- "pref.UserName": {
- "message": "Felhasználónév"
- },
- "pref.UserNameDescription": {
- "message": "A felhasználónév általában a fiókja e-mail-címe."
- },
- "pref.autodetect": {
- "message": "az elérhető legjobb"
- },
- "pref.birthday": {
- "message": "Születésnapi információk küldése"
- },
- "pref.calendaroptions": {
- "message": "Naptár beállításai"
- },
- "pref.contactoptions": {
- "message": "Névjegyzék beállításai"
- },
- "pref.displayoverride": {
- "message": "Megjelenítési név felülbírálása ezzel: „keresztnév” + „második keresztnév”"
- },
- "pref.generaloptions": {
- "message": "Általános beállítások"
- },
- "pref.provision": {
- "message": "Lekötés megkövetelése (a Kerio követelménye)"
- },
- "pref.seperator.comma": {
- "message": "Vessző"
- },
- "pref.seperator.description": {
- "message": "A többsoros címmező elválasztója."
- },
- "pref.seperator.linebreak": {
- "message": "Sortörés"
- },
- "pref.synclimit.1month": {
- "message": "4 héttel ezelőtt"
- },
- "pref.synclimit.2weeks": {
- "message": "2 héttel ezelőtt"
- },
- "pref.synclimit.3month": {
- "message": "3 hónappal ezelőtt"
- },
- "pref.synclimit.6month": {
- "message": "6 hónappal ezelőtt"
- },
- "pref.synclimit.all": {
- "message": "mindent"
- },
- "pref.synclimit.description": {
- "message": "Szinkronizálási időszak: "
- },
- "pref.usehttps": {
- "message": "Biztonságos kapcsolat használata (kapcsolódás https-n keresztül)"
- },
- "recyclebin": {
- "message": "Kuka"
- },
- "servertype.auto": {
- "message": "Automatikus beállítás"
- },
- "servertype.custom": {
- "message": "Egyéni beállítás"
- },
- "servertype.description.auto": {
- "message": "Számos ActiveSync-kiszolgáló beállítása automatikusan felfedezhető pusztán az e-mail-címe megadásával."
- },
- "servertype.description.custom": {
- "message": "Fiók beállítása a használandó kiszolgáló címének kézi megadásával."
- },
- "servertype.description.office365": {
- "message": "Az Office 365-höz kapcsolódó fiókok az OAuth 2.0 nevű modern hitelesítési folyamatot használják, amely támogatja a többfaktoros hitelesítést (MFA) is."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Kattintson duplán az összes előre megadott kiszolgálóbeállítás feloldásához."
- },
- "status.401": {
- "message": "A hitelesítés nem sikerült, ellenőrizze a felhasználónevet és a jelszót (401-es HTTP-hiba)."
- },
- "status.403": {
- "message": "A kiszolgáló elutasította a kapcsolatot (403-as HTTP-hiba)."
- },
- "status.404": {
- "message": "A felhasználó nem található (404-es HTTP-hiba)."
- },
- "status.449": {
- "message": "A kiszolgáló lekötést két (449-es HTTP-hiba)."
- },
- "status.500": {
- "message": "Ismeretlen kiszolgálóhiba (500-as HTTP-hiba)."
- },
- "status.503": {
- "message": "A szolgáltatás nem elérhető (503-ás HTTP-hiba)."
- },
- "status.BadItemSkipped": {
- "message": "Hibás elem kihagyva: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Nem lehet törölni egy rendszermappát (3-as állapot)"
- },
- "status.FolderDelete.4": {
- "message": "A mappa nem létezik (4-es állapot), újraszinkronizálás"
- },
- "status.FolderDelete.6": {
- "message": "A parancs nem fejezhető be, hiba történt a kiszolgálón (6-os állapot)"
- },
- "status.FolderDelete.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.FolderSync.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.InvalidServerOptions": {
- "message": "A kiszolgáló nem nyújt felvilágosítást a támogatott ActiveSync verziókról. EAS akadályozva van ez a felhasználó vagy az ügyfél (Thunderbird-összehangolás) számára? Megpróbálhatja kézzel beállítani az ActiveSync verziót."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "Az EAS-kiszolgáló elutasította az utolsó kérést."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Az EAS-kiszolgáló nem fogadta el a(z) ##replace.1## elemeket."
- },
- "status.Sync.12": {
- "message": "A mappahierarchia megváltozott (12-es állapot), újraszinkronizálás"
- },
- "status.Sync.3": {
- "message": "Érvénytelen szinkronizálási kulcs (3-as állapot), újraszinkronizálás"
- },
- "status.Sync.4": {
- "message": "Rosszul formázott kérés (4-es állapot)"
- },
- "status.Sync.5": {
- "message": "Ideiglenes kiszolgálóprobléma vagy érvénytelen elem (5-ös állapot)"
- },
- "status.Sync.6": {
- "message": "Érvénytelen elem (6-os állapot)"
- },
- "status.Sync.8": {
- "message": "Az objektum nem található (8-as állapot)"
- },
- "status.aborted": {
- "message": "Nincs szinkronizálva"
- },
- "status.disabled": {
- "message": "Letiltva"
- },
- "status.empty-response": {
- "message": "A kiszolgáló váratlan üres választ küldött."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Tiltott naptárelem a feladatok mappában (rendezze újra)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Tiltott feladatelem a naptár mappában (rendezze újra)"
- },
- "status.global.101": {
- "message": "A kérés WBXML-t tartalmaz, de nem sikerült XML-be dekódolni (101-es EAS-hiba)."
- },
- "status.global.102": {
- "message": "A kérés WBXML-t tartalmaz, de nem sikerült XML-be dekódolni (102-es EAS-hiba)."
- },
- "status.global.103": {
- "message": "A kérésben megadott XML nem követi a protokoll követelményeit (103-as EAS-hiba)."
- },
- "status.global.110": {
- "message": "A kiszolgáló belső hibát jelentett, és nem szabad azonnal újrapróbálkozni. Az automatikus szinkronizálás 30 percre felfüggesztésre került (110-es EAS hiba)."
- },
- "status.global.clientdenied": {
- "message": "Az EAS-kiszolgáló ezt jelenti: <##replace.2##> (állapot: ##replace.1##), és nem engedélyezi a TbSync számára a fiókja elérését."
- },
- "status.httperror": {
- "message": "Kommunikációs hiba (HTTP állapot: ##replace.1##)."
- },
- "status.invalid": {
- "message": "Érvénytelen kiszolgálóválasz (szemét)."
- },
- "status.malformed-xml": {
- "message": "Az XML feldolgozása nem sikerült. Ellenőrizze az eseménynaplót a részletekért."
- },
- "status.modified": {
- "message": "Helyi módosítások"
- },
- "status.network": {
- "message": "Nem sikerült kapcsolódni a kiszolgálóhoz (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Nem sikerült kapcsolódni a kiszolgálóhoz."
- },
- "status.nosupportedeasversion": {
- "message": "A kiszolgáló nem támogatja az ActiveSync v2.5-öt vagy a v14.0-t (csak ezt: ##replace.1##). A TbSync nem fog működni ezzel az ActiveSync-kiszolgálóval."
- },
- "status.notargets": {
- "message": "A szinkronizálás megszakítása, mert a szinkronizálási célokat nem lehetett létrehozni."
- },
- "status.notsupportedeasversion": {
- "message": "A kiszolgáló nem támogatja a kiválasztott ActiveSync ##replace.1## verziót (csak ezt: ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "A fiókot szinkronizálni kell, legalább egy elem nincs szinkronizálva."
- },
- "status.nouserhost": {
- "message": "Hiányzó felhasználónév vagy kiszolgáló. Adja meg ezeket az értékeket."
- },
- "status.pending": {
- "message": "Várakozás a szinkronizálásra"
- },
- "status.policy.2": {
- "message": "Nincs házirend ehhez a klienshez. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
- },
- "status.policy.3": {
- "message": "Ismeretlen házirendtípus érték. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
- },
- "status.policy.4": {
- "message": "A kiszolgáló házirendadatai sérültek (esetleg meghamisították). Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
- },
- "status.policy.5": {
- "message": "A kliens nyugtázza a hibás házirendkulcsot. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
- },
- "status.provision": {
- "message": "A lekötés sikertelen, állapot: <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "A kiszolgáló válasza nem tartalmaz adatokat."
- },
- "status.resync-loop": {
- "message": "Hiba történt, amelyből nem sikerült helyreállni a fiók újraszinkronizálásával. Tiltsa le a fiókot, és próbálja meg újra. (Hiba: állandó újraszinkronizálás)"
- },
- "status.security": {
- "message": "A biztonságos kapcsolat létrehozása nem sikerült. Önaláírt vagy más, nem megbízható tanúsítványt importált a Thunderbirdbe? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Még nem támogatott, kihagyva"
- },
- "status.syncing": {
- "message": "Szinkronizálás"
- },
- "status.timeout": {
- "message": "Kommunikációs időtúllépés."
- },
- "status.wbxml-parse-error": {
- "message": "A kiszolgáló olvashatatlan választ küld."
- },
- "status.wbxmlerror": {
- "message": "A szinkronizálás sikertelen. A kiszolgáló a következő állapottal válaszolt: <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync protokollsértés: A(z) <##replace.1##> kötelező mező hiányzik a kiszolgáló válaszából."
- },
- "syncstate.accountdone": {
- "message": "Fiók kész"
- },
- "syncstate.done": {
- "message": "A következő elem előkészítése szinkronizálásra"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Frissített kiszolgálóbeállítások feldolgozása"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "A mappa törölve"
- },
- "syncstate.eval.response.estimate": {
- "message": "Változásbecslés feldolgozása"
- },
- "syncstate.eval.response.folders": {
- "message": "A mappalista frissítés feldolgozása"
- },
- "syncstate.eval.response.localchanges": {
- "message": "A helyi változások nyugtázásának feldolgozása"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "A helyi törlések nyugtázásának feldolgozása"
- },
- "syncstate.eval.response.options": {
- "message": "A kiszolgáló beállításainak feldolgozása"
- },
- "syncstate.eval.response.provision": {
- "message": "Lekötés feldolgozása"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "A távoli módosítások feldolgozása"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "A helyi változások visszaállítása"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Eszközinformációk küldése"
- },
- "syncstate.eval.response.synckey": {
- "message": "Szinkronizálási kulcs feldolgozása"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Frissített kiszolgálóbeállítások kérése"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Felkészülés a mappa törlésére"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Változásbecslés kérése"
- },
- "syncstate.prepare.request.folders": {
- "message": "Mappalista-frissítés elküldése"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Helyi változások küldése"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Helyi törlések küldése"
- },
- "syncstate.prepare.request.options": {
- "message": "A kiszolgálóbeállítások kérése"
- },
- "syncstate.prepare.request.provision": {
- "message": "Lekötés kérése"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Távoli módosítások kérése"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Helyi változások összegyűjtése"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Eszközinformációk küldése"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Szinkronizálási kulcs kérése"
- },
- "syncstate.preparing": {
- "message": "A következő elem előkészítése szinkronizálásra"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Várakozás a frissített kiszolgálóbeállításokra"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Várakozás a mappa törlésére"
- },
- "syncstate.send.request.estimate": {
- "message": "Várakozás a változásbecslésre"
- },
- "syncstate.send.request.folders": {
- "message": "Várakozás a mappalista-frissítésre"
- },
- "syncstate.send.request.localchanges": {
- "message": "Várakozás a helyi változások elismerésére"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Várakozás a helyi törlések nyugtázására"
- },
- "syncstate.send.request.options": {
- "message": "Várakozás a kiszolgálóbeállításokra"
- },
- "syncstate.send.request.provision": {
- "message": "Várakozás a lekötésre"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Várakozás a távoli módosításokra"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Várakozás a legfrissebb verziókra"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Eszközinformációk küldése"
- },
- "syncstate.send.request.synckey": {
- "message": "Várakozás a szinkronizálási kulcsra"
- },
- "syncstate.syncing": {
- "message": "Szinkronizálás előkészítése"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Évforduló:"
+ },
+ "abCard.AssistantName": {
+ "message": "Asszisztens:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Asszisztensi telefon:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "2. munkahelyi telefon:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Munkahelyi fax:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Autóstelefon:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Fő munkahelyi telefon:"
+ },
+ "abCard.Email3Address": {
+ "message": "Másodlagos e-mail:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "2. otthoni telefon:"
+ },
+ "abCard.ManagerName": {
+ "message": "Vezető:"
+ },
+ "abCard.MiddleName": {
+ "message": "Második keresztnév:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Cím:"
+ },
+ "abCard.OtherCity": {
+ "message": "Város:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Ország:"
+ },
+ "abCard.OtherState": {
+ "message": "Állam/tartomány:"
+ },
+ "abCard.OtherZip": {
+ "message": "Irányítószám:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Rádió-távbeszélő:"
+ },
+ "abCard.Spouse": {
+ "message": "Házastárs:"
+ },
+ "abCard.header.eas": {
+ "message": "Egyéb mezők (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "További otthoni számok:"
+ },
+ "abCard.header.messaging": {
+ "message": "Üzenetek:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Egyéb cím (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "További számok:"
+ },
+ "abCard.header.people": {
+ "message": "Emberek:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "További munkahelyi számok:"
+ },
+ "acl.readonly": {
+ "message": "Csak olvasható hozzáférés (helyi változások visszavonása)"
+ },
+ "acl.readwrite": {
+ "message": "Olvasás és írás a kiszolgálón"
+ },
+ "add.description": {
+ "message": "Válasszon az elérhető kiszolgálóbeállítások közül, és adja meg a kért részleteket. "
+ },
+ "add.name": {
+ "message": "Felhasználónév:"
+ },
+ "add.ok": {
+ "message": "Fiók hozzáadása"
+ },
+ "add.password": {
+ "message": "Jelszó:"
+ },
+ "add.server": {
+ "message": "Kiszolgálóbeállítások:"
+ },
+ "add.shortdescription": {
+ "message": "Fiókadatok"
+ },
+ "add.title": {
+ "message": "Exchange ActiveSync-fiók hozzáadása a TbSynchez"
+ },
+ "add.url": {
+ "message": "Kiszolgáló címe:"
+ },
+ "add.urldescription": {
+ "message": "Elégséges, ha csak az alap kiszolgálócímet adja meg (például: posta.kiszolgálód.hu). De a teljes URL-t is megadhatja (például: https://posta.kiszolgálód.hu/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Felhasználónév (e-mail-cím):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "globális kiszolgálójegyzék"
+ },
+ "autodiscover.Failed": {
+ "message": "A(z) <##user##> felhasználó automatikus felderítése sikertelen. Vagy hibásak voltak a megadott hitelesítő adatok, vagy az ActiveSync szolgáltató ideiglenes problémákat tapasztal, vagy nem támogatja az automatikus felderítést."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Az önműködő felismerésnek érvényes e-mail címnek kell lennie felhasználói névként."
+ },
+ "autodiscover.Ok": {
+ "message": "Az önműködő felderítés sikeresen befejeződött, most ellenőrizheti az választható beállításokat és létrehozhatja az összehangolási kapcsolatot."
+ },
+ "autodiscover.Querying": {
+ "message": "Beállítások keresése…"
+ },
+ "config.auto": {
+ "message": "Az ActiveSync kiszolgáló beállítások (önműködő észlelés)"
+ },
+ "config.custom": {
+ "message": "Az ActiveSync kiszolgáló beállítások"
+ },
+ "deletefolder.confirm": {
+ "message": "Tényleg azt szeretné, hogy a(z) „##replace.1##” mappa véglegesen törölje a kukát?"
+ },
+ "deletefolder.menuentry": {
+ "message": "„##replace.1##” mappa kuka ürítése"
+ },
+ "deletefolder.notallowed": {
+ "message": "Kérjük, törölje le a(z) „##replace.1##” mappát, mielőtt megpróbálnánk kuka ürítése."
+ },
+ "extensionDescription": {
+ "message": "Az Exchange ActiveSync-fiókok szinkronizálásának támogatása a TbSyncben (névjegyek, feladatok és naptárak)."
+ },
+ "extensionName": {
+ "message": "Exchange ActiveSync-szolgáltató"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Fiókbeállítások"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Automatikus válasz"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Beállítások"
+ },
+ "newaccount.add_auto": {
+ "message": "Automatikus felfedezés beállításai és fiók hozzáadása"
+ },
+ "newaccount.add_custom": {
+ "message": "Fiók hozzáadása"
+ },
+ "pref.AccountName": {
+ "message": "Leírás"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync verzió"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync eszközazonosító"
+ },
+ "pref.ServerName": {
+ "message": "Kiszolgáló címe"
+ },
+ "pref.ServerNameDescription": {
+ "message": "például: posta.kiszolgálód.hu"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "A kukában található mappák megjelenítése"
+ },
+ "pref.UserName": {
+ "message": "Felhasználónév"
+ },
+ "pref.UserNameDescription": {
+ "message": "A felhasználónév általában a fiókja e-mail-címe."
+ },
+ "pref.autodetect": {
+ "message": "az elérhető legjobb"
+ },
+ "pref.birthday": {
+ "message": "Születésnapi információk küldése"
+ },
+ "pref.calendaroptions": {
+ "message": "Naptár beállításai"
+ },
+ "pref.contactoptions": {
+ "message": "Névjegyzék beállításai"
+ },
+ "pref.displayoverride": {
+ "message": "Megjelenítési név felülbírálása ezzel: „keresztnév” + „második keresztnév”"
+ },
+ "pref.generaloptions": {
+ "message": "Általános beállítások"
+ },
+ "pref.provision": {
+ "message": "Lekötés megkövetelése (a Kerio követelménye)"
+ },
+ "pref.seperator.comma": {
+ "message": "Vessző"
+ },
+ "pref.seperator.description": {
+ "message": "A többsoros címmező elválasztója."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Sortörés"
+ },
+ "pref.synclimit.1month": {
+ "message": "4 héttel ezelőtt"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "2 héttel ezelőtt"
+ },
+ "pref.synclimit.3month": {
+ "message": "3 hónappal ezelőtt"
+ },
+ "pref.synclimit.6month": {
+ "message": "6 hónappal ezelőtt"
+ },
+ "pref.synclimit.all": {
+ "message": "mindent"
+ },
+ "pref.synclimit.description": {
+ "message": "Szinkronizálási időszak: "
+ },
+ "pref.usehttps": {
+ "message": "Biztonságos kapcsolat használata (kapcsolódás https-n keresztül)"
+ },
+ "recyclebin": {
+ "message": "Kuka"
+ },
+ "servertype.auto": {
+ "message": "Automatikus beállítás"
+ },
+ "servertype.custom": {
+ "message": "Egyéni beállítás"
+ },
+ "servertype.description.auto": {
+ "message": "Számos ActiveSync-kiszolgáló beállítása automatikusan felfedezhető pusztán az e-mail-címe megadásával."
+ },
+ "servertype.description.custom": {
+ "message": "Fiók beállítása a használandó kiszolgáló címének kézi megadásával."
+ },
+ "servertype.description.office365": {
+ "message": "Az Office 365-höz kapcsolódó fiókok az OAuth 2.0 nevű modern hitelesítési folyamatot használják, amely támogatja a többfaktoros hitelesítést (MFA) is."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Kattintson duplán az összes előre megadott kiszolgálóbeállítás feloldásához."
+ },
+ "status.401": {
+ "message": "A hitelesítés nem sikerült, ellenőrizze a felhasználónevet és a jelszót (401-es HTTP-hiba)."
+ },
+ "status.403": {
+ "message": "A kiszolgáló elutasította a kapcsolatot (403-as HTTP-hiba)."
+ },
+ "status.404": {
+ "message": "A felhasználó nem található (404-es HTTP-hiba)."
+ },
+ "status.449": {
+ "message": "A kiszolgáló lekötést két (449-es HTTP-hiba)."
+ },
+ "status.500": {
+ "message": "Ismeretlen kiszolgálóhiba (500-as HTTP-hiba)."
+ },
+ "status.503": {
+ "message": "A szolgáltatás nem elérhető (503-ás HTTP-hiba)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Hibás elem kihagyva: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Nem lehet törölni egy rendszermappát (3-as állapot)"
+ },
+ "status.FolderDelete.4": {
+ "message": "A mappa nem létezik (4-es állapot), újraszinkronizálás"
+ },
+ "status.FolderDelete.6": {
+ "message": "A parancs nem fejezhető be, hiba történt a kiszolgálón (6-os állapot)"
+ },
+ "status.FolderDelete.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.FolderSync.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.InvalidServerOptions": {
+ "message": "A kiszolgáló nem nyújt felvilágosítást a támogatott ActiveSync verziókról. EAS akadályozva van ez a felhasználó vagy az ügyfél (Thunderbird-összehangolás) számára? Megpróbálhatja kézzel beállítani az ActiveSync verziót."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Az EAS-kiszolgáló elutasította az utolsó kérést."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Az EAS-kiszolgáló nem fogadta el a(z) ##replace.1## elemeket."
+ },
+ "status.Sync.12": {
+ "message": "A mappahierarchia megváltozott (12-es állapot), újraszinkronizálás"
+ },
+ "status.Sync.3": {
+ "message": "Érvénytelen szinkronizálási kulcs (3-as állapot), újraszinkronizálás"
+ },
+ "status.Sync.4": {
+ "message": "Rosszul formázott kérés (4-es állapot)"
+ },
+ "status.Sync.5": {
+ "message": "Ideiglenes kiszolgálóprobléma vagy érvénytelen elem (5-ös állapot)"
+ },
+ "status.Sync.6": {
+ "message": "Érvénytelen elem (6-os állapot)"
+ },
+ "status.Sync.8": {
+ "message": "Az objektum nem található (8-as állapot)"
+ },
+ "status.aborted": {
+ "message": "Nincs szinkronizálva"
+ },
+ "status.disabled": {
+ "message": "Letiltva"
+ },
+ "status.empty-response": {
+ "message": "A kiszolgáló váratlan üres választ küldött."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Tiltott naptárelem a feladatok mappában (rendezze újra)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Tiltott feladatelem a naptár mappában (rendezze újra)"
+ },
+ "status.global.101": {
+ "message": "A kérés WBXML-t tartalmaz, de nem sikerült XML-be dekódolni (101-es EAS-hiba)."
+ },
+ "status.global.102": {
+ "message": "A kérés WBXML-t tartalmaz, de nem sikerült XML-be dekódolni (102-es EAS-hiba)."
+ },
+ "status.global.103": {
+ "message": "A kérésben megadott XML nem követi a protokoll követelményeit (103-as EAS-hiba)."
+ },
+ "status.global.110": {
+ "message": "A kiszolgáló belső hibát jelentett, és nem szabad azonnal újrapróbálkozni. Az automatikus szinkronizálás 30 percre felfüggesztésre került (110-es EAS hiba)."
+ },
+ "status.global.clientdenied": {
+ "message": "Az EAS-kiszolgáló ezt jelenti: <##replace.2##> (állapot: ##replace.1##), és nem engedélyezi a TbSync számára a fiókja elérését."
+ },
+ "status.httperror": {
+ "message": "Kommunikációs hiba (HTTP állapot: ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Érvénytelen kiszolgálóválasz (szemét)."
+ },
+ "status.malformed-xml": {
+ "message": "Az XML feldolgozása nem sikerült. Ellenőrizze az eseménynaplót a részletekért."
+ },
+ "status.modified": {
+ "message": "Helyi módosítások"
+ },
+ "status.network": {
+ "message": "Nem sikerült kapcsolódni a kiszolgálóhoz (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Nem sikerült kapcsolódni a kiszolgálóhoz."
+ },
+ "status.nosupportedeasversion": {
+ "message": "A kiszolgáló nem támogatja az ActiveSync v2.5-öt vagy a v14.0-t (csak ezt: ##replace.1##). A TbSync nem fog működni ezzel az ActiveSync-kiszolgálóval."
+ },
+ "status.notargets": {
+ "message": "A szinkronizálás megszakítása, mert a szinkronizálási célokat nem lehetett létrehozni."
+ },
+ "status.notsupportedeasversion": {
+ "message": "A kiszolgáló nem támogatja a kiválasztott ActiveSync ##replace.1## verziót (csak ezt: ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "A fiókot szinkronizálni kell, legalább egy elem nincs szinkronizálva."
+ },
+ "status.nouserhost": {
+ "message": "Hiányzó felhasználónév vagy kiszolgáló. Adja meg ezeket az értékeket."
+ },
+ "status.pending": {
+ "message": "Várakozás a szinkronizálásra"
+ },
+ "status.policy.2": {
+ "message": "Nincs házirend ehhez a klienshez. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
+ },
+ "status.policy.3": {
+ "message": "Ismeretlen házirendtípus érték. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
+ },
+ "status.policy.4": {
+ "message": "A kiszolgáló házirendadatai sérültek (esetleg meghamisították). Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
+ },
+ "status.policy.5": {
+ "message": "A kliens nyugtázza a hibás házirendkulcsot. Vegye fel a kapcsolatot a kiszolgáló rendszergazdájával, vagy tiltsa le a fiók lekötését."
+ },
+ "status.provision": {
+ "message": "A lekötés sikertelen, állapot: <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "A kiszolgáló válasza nem tartalmaz adatokat."
+ },
+ "status.resync-loop": {
+ "message": "Hiba történt, amelyből nem sikerült helyreállni a fiók újraszinkronizálásával. Tiltsa le a fiókot, és próbálja meg újra. (Hiba: állandó újraszinkronizálás)"
+ },
+ "status.security": {
+ "message": "A biztonságos kapcsolat létrehozása nem sikerült. Önaláírt vagy más, nem megbízható tanúsítványt importált a Thunderbirdbe? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Még nem támogatott, kihagyva"
+ },
+ "status.syncing": {
+ "message": "Szinkronizálás"
+ },
+ "status.timeout": {
+ "message": "Kommunikációs időtúllépés."
+ },
+ "status.wbxml-parse-error": {
+ "message": "A kiszolgáló olvashatatlan választ küld."
+ },
+ "status.wbxmlerror": {
+ "message": "A szinkronizálás sikertelen. A kiszolgáló a következő állapottal válaszolt: <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync protokollsértés: A(z) <##replace.1##> kötelező mező hiányzik a kiszolgáló válaszából."
+ },
+ "syncstate.accountdone": {
+ "message": "Fiók kész"
+ },
+ "syncstate.done": {
+ "message": "A következő elem előkészítése szinkronizálásra"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Frissített kiszolgálóbeállítások feldolgozása"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "A mappa törölve"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Változásbecslés feldolgozása"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "A mappalista frissítés feldolgozása"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "A helyi változások nyugtázásának feldolgozása"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "A helyi törlések nyugtázásának feldolgozása"
+ },
+ "syncstate.eval.response.options": {
+ "message": "A kiszolgáló beállításainak feldolgozása"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Lekötés feldolgozása"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "A távoli módosítások feldolgozása"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "A helyi változások visszaállítása"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Eszközinformációk küldése"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Szinkronizálási kulcs feldolgozása"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Frissített kiszolgálóbeállítások kérése"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Felkészülés a mappa törlésére"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Változásbecslés kérése"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Mappalista-frissítés elküldése"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Helyi változások küldése"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Helyi törlések küldése"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "A kiszolgálóbeállítások kérése"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Lekötés kérése"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Távoli módosítások kérése"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Helyi változások összegyűjtése"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Eszközinformációk küldése"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Szinkronizálási kulcs kérése"
+ },
+ "syncstate.preparing": {
+ "message": "A következő elem előkészítése szinkronizálásra"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Várakozás a frissített kiszolgálóbeállításokra"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Várakozás a mappa törlésére"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Várakozás a változásbecslésre"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Várakozás a mappalista-frissítésre"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Várakozás a helyi változások elismerésére"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Várakozás a helyi törlések nyugtázására"
+ },
+ "syncstate.send.request.options": {
+ "message": "Várakozás a kiszolgálóbeállításokra"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Várakozás a lekötésre"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Várakozás a távoli módosításokra"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Várakozás a legfrissebb verziókra"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Eszközinformációk küldése"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Várakozás a szinkronizálási kulcsra"
+ },
+ "syncstate.syncing": {
+ "message": "Szinkronizálás előkészítése"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/it/messages.json eas4tbsync-4.17/_locales/it/messages.json
--- eas4tbsync-4.11/_locales/it/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/it/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Anniversario:"
- },
- "abCard.AssistantName": {
- "message": "Assistente:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Telefono assistente:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Secondo telefono ufficio:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax ufficio:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Telefono auto:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Telefono lavoro principale:"
- },
- "abCard.Email3Address": {
- "message": "Indirizzo di posta elettronica alternativo:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Secondo telefono casa:"
- },
- "abCard.ManagerName": {
- "message": "Supervisore:"
- },
- "abCard.MiddleName": {
- "message": "Secondo nome:"
- },
- "abCard.OtherAddress": {
- "message": "Indirizzo:"
- },
- "abCard.OtherCity": {
- "message": "Città:"
- },
- "abCard.OtherCountry": {
- "message": "Paese:"
- },
- "abCard.OtherState": {
- "message": "Stato:"
- },
- "abCard.OtherZip": {
- "message": "CAP:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Telefono radio:"
- },
- "abCard.Spouse": {
- "message": "Coniuge:"
- },
- "abCard.header.eas": {
- "message": "Altri campi (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Numeri casa aggiuntivi:"
- },
- "abCard.header.messaging": {
- "message": "Messaggeria:"
- },
- "abCard.header.otheraddress": {
- "message": "Altro indirizzo (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Numeri aggiuntivi:"
- },
- "abCard.header.people": {
- "message": "Persone:"
- },
- "abCard.header.worknumbers": {
- "message": "Numeri lavoro aggiuntivi:"
- },
- "acl.readonly": {
- "message": "Accesso al server in sola lettura (ripristina le modifiche locali)"
- },
- "acl.readwrite": {
- "message": "Leggi e scrivi sul server"
- },
- "add.description": {
- "message": "Selezionare una delle opzioni configurazione server disponibili e immettere i dettagli richiesti. "
- },
- "add.name": {
- "message": "Nome account:"
- },
- "add.ok": {
- "message": "Aggiungi account"
- },
- "add.password": {
- "message": "Password:"
- },
- "add.server": {
- "message": "Configurazione server:"
- },
- "add.shortdescription": {
- "message": "Informazioni sul conto"
- },
- "add.title": {
- "message": "Aggiunta account Exchange ActiveSync a TbSync"
- },
- "add.url": {
- "message": "Indirizzo server:"
- },
- "add.urldescription": {
- "message": "Dovrebbe essere sufficiente fornire solo il nome del server (ad es. mail.yourserver.com), ma è anche possibile fornire l'URL completo (ad es. https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Nome utente (indirizzo di posta elettronica):"
- },
- "autocomplete.serverdirectory": {
- "message": "directory globale del server"
- },
- "autodiscover.Failed": {
- "message": "Rilevamento automatico non riuscito per l'utente <##user##>. Le credenziali fornite sono errate o il proprio provider ActiveSync ha un problema temporaneo o non supporta il rilevamento automatico impostazioni."
- },
- "autodiscover.NeedEmail": {
- "message": "Il rilevamento automatico impostazioni richiede che venga specificato un indirizzo di posta elettronica valido come nome utente."
- },
- "autodiscover.Ok": {
- "message": "Rilevamento automatico impostazioni completato con successo, è ora possibile verificare le impostazioni facoltative e stabilire la connessione per la sincronizzazione."
- },
- "autodiscover.Querying": {
- "message": "Rilevamento impostazioni in corso..."
- },
- "config.auto": {
- "message": "Configurazione server ActiveSync (rilevamento automatico)"
- },
- "config.custom": {
- "message": "Configurazione server ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "ELIMINARE PERMANENTEMENTE la cartella '##replace.1##' dal Cestino?"
- },
- "deletefolder.menuentry": {
- "message": "Elimina permanentemente la cartella '##replace.1##' dal Cestino"
- },
- "deletefolder.notallowed": {
- "message": "Annullare la sottoscrizione alla cartella '##replace.1##' prima di provare a eliminarla dal Cestino."
- },
- "extensionDescription": {
- "message": "Aggiunge il supporto per la sincronizzazione di account Exchange ActiveSync (contatti, attività e calendari) a TbSync."
- },
- "extensionName": {
- "message": "Provider Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Impostazioni account"
- },
- "manager.tabs.outOfOffice": {
- "message": "Risponditore automatico"
- },
- "manager.tabs.syncsettings": {
- "message": "Opzioni"
- },
- "newaccount.add_auto": {
- "message": "Rileva automaticamente impostazioni e aggiungi account"
- },
- "newaccount.add_custom": {
- "message": "Aggiungi account"
- },
- "pref.AccountName": {
- "message": "Nome account"
- },
- "pref.ActiveSyncVersion": {
- "message": "Versione ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID dispositivo ActiveSync"
- },
- "pref.ServerName": {
- "message": "Indirizzo server"
- },
- "pref.ServerNameDescription": {
- "message": "ad es. mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Visualizza le cartelle trovate nel Cestino"
- },
- "pref.UserName": {
- "message": "Nome utente"
- },
- "pref.UserNameDescription": {
- "message": "Il nome utente è solitamente l'indirizzo di posta elettronica del proprio account."
- },
- "pref.autodetect": {
- "message": "miglior opzione disponibile"
- },
- "pref.birthday": {
- "message": "Invia informazioni di compleanno"
- },
- "pref.calendaroptions": {
- "message": "Opzioni del calendario"
- },
- "pref.contactoptions": {
- "message": "Opzioni di contatto"
- },
- "pref.displayoverride": {
- "message": "Ignora il Nome visualizzato e mostra Nome + Cognome"
- },
- "pref.generaloptions": {
- "message": "Opzioni generali"
- },
- "pref.provision": {
- "message": "Forza provisioning (opzione richiesta per Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Virgola"
- },
- "pref.seperator.description": {
- "message": "Separatore per i campi indirizzo multiriga."
- },
- "pref.seperator.linebreak": {
- "message": "Separatore riga"
- },
- "pref.synclimit.1month": {
- "message": "di 4 settimane fa"
- },
- "pref.synclimit.2weeks": {
- "message": "di 2 settimane fa"
- },
- "pref.synclimit.3month": {
- "message": "di 3 mesi fa"
- },
- "pref.synclimit.6month": {
- "message": "di 6 mesi fa"
- },
- "pref.synclimit.all": {
- "message": "tutto"
- },
- "pref.synclimit.description": {
- "message": "Periodo di sincronizzazione:"
- },
- "pref.usehttps": {
- "message": "Utilizza connessione sicura (connettiti tramite HTTPS)"
- },
- "recyclebin": {
- "message": "Cestino"
- },
- "servertype.auto": {
- "message": "Configurazione automatica"
- },
- "servertype.custom": {
- "message": "Configurazione personalizzata"
- },
- "servertype.description.auto": {
- "message": "Per molti server ActiveSync la configurazione può essere trovata fornendo solo l'indirizzo di posta elettronica."
- },
- "servertype.description.custom": {
- "message": "Imposta l'account fornendo manualmente l'indirizzo del server a cui connettersi."
- },
- "servertype.description.office365": {
- "message": "Gli account connessi a Office 365 utilizzano un processo di autenticazione moderno denominato OAuth 2.0 che supporta anche l'autenticazione a più fattori (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Cliccare due volte per sbloccare tutte le impostazioni server predefinite."
- },
- "status.401": {
- "message": "Impossibile autenticarsi, controllare nome utente e password."
- },
- "status.403": {
- "message": "Il server ha rifiutato la connessione (vietato)."
- },
- "status.404": {
- "message": "Utente non trovato (errore HTTP 404)."
- },
- "status.449": {
- "message": "Il server richiede il provisioning."
- },
- "status.500": {
- "message": "Errore server sconosciuto (errore HTTP 500)."
- },
- "status.503": {
- "message": "Servizio non disponibile."
- },
- "status.BadItemSkipped": {
- "message": "Oggetto errato saltato: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Impossibile eliminare una cartella di sistema."
- },
- "status.FolderDelete.4": {
- "message": "?? Folder does not exist (status 4), resyncing ??"
- },
- "status.FolderDelete.6": {
- "message": "Impossibile completare il comando, si è verificato un errore sul server."
- },
- "status.FolderDelete.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.FolderSync.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.InvalidServerOptions": {
- "message": "Il server non fornisce informazioni sulle versioni di ActiveSync supportate. EAS è bloccato per questo utente o questo client (TbSync)? È possibile provare a impostare manualmente la versione di ActiveSync."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "Il server EAS ha rifiutato l'ultima richiesta."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Il server EAS non ha accettato ##replace.1## elementi."
- },
- "status.Sync.12": {
- "message": "?? Folder hierarchy changed (status 12), resyncing ??"
- },
- "status.Sync.3": {
- "message": "?? Invalid synchronization key (status 3), resyncing ??"
- },
- "status.Sync.4": {
- "message": "?? Malformed request (status 4) ??"
- },
- "status.Sync.5": {
- "message": "?? Temporary server issues or invalid item (status 5) ??"
- },
- "status.Sync.6": {
- "message": "?? Invalid item (status 6) ??"
- },
- "status.Sync.8": {
- "message": "?? Object not found (status 8) ??"
- },
- "status.aborted": {
- "message": "Non sincronizzato"
- },
- "status.disabled": {
- "message": "L'account non è abilitato, la sincronizzazione è disabilitata."
- },
- "status.empty-response": {
- "message": "Il server invia una risposta vuota inaspettata."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "?? Forbidden calendar item in a task folder (please resort) ??"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "?? Forbidden task item in a calendar folder (please resort) ??"
- },
- "status.global.101": {
- "message": "La richiesta contiene WBXML ma non è possibile decodificarlo in XML (errore 101)."
- },
- "status.global.102": {
- "message": "La richiesta contiene WBXML ma non è possibile decodificarlo in XML (errore 102)."
- },
- "status.global.103": {
- "message": "L'XML fornito nella richiesta non rispetta i requisiti del protocollo (errore 103)."
- },
- "status.global.110": {
- "message": "Il server ha segnalato un errore interno e non dovremmo riprovare immediatamente. La sincronizzazione periodica automatica è stata disattivata per 30 minuti (errore EAS 110)."
- },
- "status.global.clientdenied": {
- "message": "Il server EAS segnala <##replace.2##> (stato ##replace.1##) e non consente a TbSync l'accesso al proprio account."
- },
- "status.httperror": {
- "message": "Errore di comunicazione (stato HTTP ##replace.1##)."
- },
- "status.invalid": {
- "message": "Risposta del server non valida (inutile)."
- },
- "status.malformed-xml": {
- "message": "Impossibile analizzare XML. Controllare il registro eventi per i dettagli."
- },
- "status.modified": {
- "message": "Modifiche locali presenti"
- },
- "status.network": {
- "message": "Impossibile collegarsi al server (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Impossibile connettersi al server."
- },
- "status.nosupportedeasversion": {
- "message": "Il server non supporta ActiveSync v2.5 o v14.0 (solo ##replace.1##). TbSync non funzionerà con questo server ActiveSync."
- },
- "status.notargets": {
- "message": "Interruzione sincronizzazione in corso: non è possibile creare le destinazioni sincronizzazione."
- },
- "status.notsupportedeasversion": {
- "message": "Il server non supporta la versione di ActiveSync selezionata ##replace.1## (solo ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "L'account deve essere sincronizzato, almeno un elemento non è sincronizzato."
- },
- "status.nouserhost": {
- "message": "Nome utente e/o server mancanti. Fornire tali valori."
- },
- "status.pending": {
- "message": "In attesa di sincronizzazione"
- },
- "status.policy.2": {
- "message": "Non esiste alcuna policy per questo client. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
- },
- "status.policy.3": {
- "message": "Valore PolicyType sconosciuto. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
- },
- "status.policy.4": {
- "message": "I dati di policy sul server sono corrotti (forse alterati). Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
- },
- "status.policy.5": {
- "message": "Il client sta riconoscendo una policy con nome errato. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
- },
- "status.provision": {
- "message": "Provisioning non riuscito: stato <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "La risposta dal server non contiene dati."
- },
- "status.resync-loop": {
- "message": "Si è verificato un errore che non è stato possibile correggere eseguendo una nuova sincronizzazione dell'account. Disabilitare l'account e riprovare. (Errore: ciclo di risincronizzazione)"
- },
- "status.security": {
- "message": "Impossibile stabilire una connessione sicura. Si sta utilizzando un certificato autofirmato o non affidabile senza averlo importato in Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Non ancora supportato, omesso"
- },
- "status.syncing": {
- "message": "Sincronizzazione in corso"
- },
- "status.timeout": {
- "message": "Timeout durante la comunicazione."
- },
- "status.wbxml-parse-error": {
- "message": "Il server invia una risposta illeggibile."
- },
- "status.wbxmlerror": {
- "message": "Sincronizzazione non riuscita. Il server ha risposto con lo stato <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Violazione protocollo ActiveSync: il campo obbligatorio <##replace.1##> manca dalla risposta del server."
- },
- "syncstate.accountdone": {
- "message": "Sincronizzazione account completata"
- },
- "syncstate.done": {
- "message": "Preparazione prossimo elemento per la sincronizzazione in corso"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Elaborazione impostazioni server aggiornate in corso"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Cartella eliminata"
- },
- "syncstate.eval.response.estimate": {
- "message": "Elaborazione stima modifiche in corso"
- },
- "syncstate.eval.response.folders": {
- "message": "Elaborazione aggiornamenti elenco cartelle in corso"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Elaborazione riconoscimento modifiche locali in corso"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Elaborazione riconoscimento eliminazioni locali in corso"
- },
- "syncstate.eval.response.options": {
- "message": "Elaborazione opzioni server in corso"
- },
- "syncstate.eval.response.provision": {
- "message": "Elaborazione provisioning in corso"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Elaborazione modifiche remote in corso"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Annullamento modifiche locali in corso"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Invio informazioni dispositivo in corso"
- },
- "syncstate.eval.response.synckey": {
- "message": "Elaborazione chiave di sincronizzazione in corso"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Richiesta impostazioni server aggiornate in corso"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparazione eliminazione cartella in corso"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Richiesta stima modifiche in corso"
- },
- "syncstate.prepare.request.folders": {
- "message": "Invio aggiornamenti elenco cartelle in corso"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Invio modifiche locali in corso"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Invio eliminazioni locali in corso"
- },
- "syncstate.prepare.request.options": {
- "message": "Richiesta opzioni server in corso"
- },
- "syncstate.prepare.request.provision": {
- "message": "Richiesta provisioning in corso"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Richiesta modifiche remote in corso"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Raccolta modifiche locali in corso"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Invio informazioni dispositivo in corso"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Richiesta chiave di sincronizzazione in corso"
- },
- "syncstate.preparing": {
- "message": "Preparazione prossimo elemento per la sincronizzazione in corso"
- },
- "syncstate.send.request.autodiscover": {
- "message": "In attesa delle impostazioni server aggiornate"
- },
- "syncstate.send.request.deletefolder": {
- "message": "In attesa dell'eliminazione della cartella"
- },
- "syncstate.send.request.estimate": {
- "message": "In attesa della stima modifiche"
- },
- "syncstate.send.request.folders": {
- "message": "In attesa degli aggiornamenti elenco cartelle"
- },
- "syncstate.send.request.localchanges": {
- "message": "In attesa del riconoscimento delle modifiche locali"
- },
- "syncstate.send.request.localdeletes": {
- "message": "In attesa del riconoscimento delle eliminazioni locali"
- },
- "syncstate.send.request.options": {
- "message": "In attesa delle opzioni server"
- },
- "syncstate.send.request.provision": {
- "message": "In attesa del provisioning"
- },
- "syncstate.send.request.remotechanges": {
- "message": "In attesa delle modifiche remote"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "In attesa delle versioni più recenti"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Invio informazioni dispositivo in corso"
- },
- "syncstate.send.request.synckey": {
- "message": "In attesa della chiave di sincronizzazione"
- },
- "syncstate.syncing": {
- "message": "Inizializzazione sincronizzazione in corso"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Anniversario:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistente:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Telefono assistente:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Secondo telefono ufficio:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax ufficio:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Telefono auto:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Telefono lavoro principale:"
+ },
+ "abCard.Email3Address": {
+ "message": "Indirizzo di posta elettronica alternativo:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Secondo telefono casa:"
+ },
+ "abCard.ManagerName": {
+ "message": "Supervisore:"
+ },
+ "abCard.MiddleName": {
+ "message": "Secondo nome:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Indirizzo:"
+ },
+ "abCard.OtherCity": {
+ "message": "Città:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Paese:"
+ },
+ "abCard.OtherState": {
+ "message": "Stato:"
+ },
+ "abCard.OtherZip": {
+ "message": "CAP:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Telefono radio:"
+ },
+ "abCard.Spouse": {
+ "message": "Coniuge:"
+ },
+ "abCard.header.eas": {
+ "message": "Altri campi (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Numeri casa aggiuntivi:"
+ },
+ "abCard.header.messaging": {
+ "message": "Messaggeria:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Altro indirizzo (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Numeri aggiuntivi:"
+ },
+ "abCard.header.people": {
+ "message": "Persone:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Numeri lavoro aggiuntivi:"
+ },
+ "acl.readonly": {
+ "message": "Accesso al server in sola lettura (ripristina le modifiche locali)"
+ },
+ "acl.readwrite": {
+ "message": "Leggi e scrivi sul server"
+ },
+ "add.description": {
+ "message": "Selezionare una delle opzioni configurazione server disponibili e immettere i dettagli richiesti. "
+ },
+ "add.name": {
+ "message": "Nome account:"
+ },
+ "add.ok": {
+ "message": "Aggiungi account"
+ },
+ "add.password": {
+ "message": "Password:"
+ },
+ "add.server": {
+ "message": "Configurazione server:"
+ },
+ "add.shortdescription": {
+ "message": "Informazioni sul conto"
+ },
+ "add.title": {
+ "message": "Aggiunta account Exchange ActiveSync a TbSync"
+ },
+ "add.url": {
+ "message": "Indirizzo server:"
+ },
+ "add.urldescription": {
+ "message": "Dovrebbe essere sufficiente fornire solo il nome del server (ad es. mail.yourserver.com), ma è anche possibile fornire l'URL completo (ad es. https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Nome utente (indirizzo di posta elettronica):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "directory globale del server"
+ },
+ "autodiscover.Failed": {
+ "message": "Rilevamento automatico non riuscito per l'utente <##user##>. Le credenziali fornite sono errate o il proprio provider ActiveSync ha un problema temporaneo o non supporta il rilevamento automatico impostazioni."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Il rilevamento automatico impostazioni richiede che venga specificato un indirizzo di posta elettronica valido come nome utente."
+ },
+ "autodiscover.Ok": {
+ "message": "Rilevamento automatico impostazioni completato con successo, è ora possibile verificare le impostazioni facoltative e stabilire la connessione per la sincronizzazione."
+ },
+ "autodiscover.Querying": {
+ "message": "Rilevamento impostazioni in corso..."
+ },
+ "config.auto": {
+ "message": "Configurazione server ActiveSync (rilevamento automatico)"
+ },
+ "config.custom": {
+ "message": "Configurazione server ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "ELIMINARE PERMANENTEMENTE la cartella '##replace.1##' dal Cestino?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Elimina permanentemente la cartella '##replace.1##' dal Cestino"
+ },
+ "deletefolder.notallowed": {
+ "message": "Annullare la sottoscrizione alla cartella '##replace.1##' prima di provare a eliminarla dal Cestino."
+ },
+ "extensionDescription": {
+ "message": "Aggiunge il supporto per la sincronizzazione di account Exchange ActiveSync (contatti, attività e calendari) a TbSync."
+ },
+ "extensionName": {
+ "message": "Provider Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Impostazioni account"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Risponditore automatico"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Opzioni"
+ },
+ "newaccount.add_auto": {
+ "message": "Rileva automaticamente impostazioni e aggiungi account"
+ },
+ "newaccount.add_custom": {
+ "message": "Aggiungi account"
+ },
+ "pref.AccountName": {
+ "message": "Nome account"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Versione ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID dispositivo ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Indirizzo server"
+ },
+ "pref.ServerNameDescription": {
+ "message": "ad es. mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Visualizza le cartelle trovate nel Cestino"
+ },
+ "pref.UserName": {
+ "message": "Nome utente"
+ },
+ "pref.UserNameDescription": {
+ "message": "Il nome utente è solitamente l'indirizzo di posta elettronica del proprio account."
+ },
+ "pref.autodetect": {
+ "message": "miglior opzione disponibile"
+ },
+ "pref.birthday": {
+ "message": "Invia informazioni di compleanno"
+ },
+ "pref.calendaroptions": {
+ "message": "Opzioni del calendario"
+ },
+ "pref.contactoptions": {
+ "message": "Opzioni di contatto"
+ },
+ "pref.displayoverride": {
+ "message": "Ignora il Nome visualizzato e mostra Nome + Cognome"
+ },
+ "pref.generaloptions": {
+ "message": "Opzioni generali"
+ },
+ "pref.provision": {
+ "message": "Forza provisioning (opzione richiesta per Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Virgola"
+ },
+ "pref.seperator.description": {
+ "message": "Separatore per i campi indirizzo multiriga."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Separatore riga"
+ },
+ "pref.synclimit.1month": {
+ "message": "di 4 settimane fa"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "di 2 settimane fa"
+ },
+ "pref.synclimit.3month": {
+ "message": "di 3 mesi fa"
+ },
+ "pref.synclimit.6month": {
+ "message": "di 6 mesi fa"
+ },
+ "pref.synclimit.all": {
+ "message": "tutto"
+ },
+ "pref.synclimit.description": {
+ "message": "Periodo di sincronizzazione:"
+ },
+ "pref.usehttps": {
+ "message": "Utilizza connessione sicura (connettiti tramite HTTPS)"
+ },
+ "recyclebin": {
+ "message": "Cestino"
+ },
+ "servertype.auto": {
+ "message": "Configurazione automatica"
+ },
+ "servertype.custom": {
+ "message": "Configurazione personalizzata"
+ },
+ "servertype.description.auto": {
+ "message": "Per molti server ActiveSync la configurazione può essere trovata fornendo solo l'indirizzo di posta elettronica."
+ },
+ "servertype.description.custom": {
+ "message": "Imposta l'account fornendo manualmente l'indirizzo del server a cui connettersi."
+ },
+ "servertype.description.office365": {
+ "message": "Gli account connessi a Office 365 utilizzano un processo di autenticazione moderno denominato OAuth 2.0 che supporta anche l'autenticazione a più fattori (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Cliccare due volte per sbloccare tutte le impostazioni server predefinite."
+ },
+ "status.401": {
+ "message": "Impossibile autenticarsi, controllare nome utente e password."
+ },
+ "status.403": {
+ "message": "Il server ha rifiutato la connessione (vietato)."
+ },
+ "status.404": {
+ "message": "Utente non trovato (errore HTTP 404)."
+ },
+ "status.449": {
+ "message": "Il server richiede il provisioning."
+ },
+ "status.500": {
+ "message": "Errore server sconosciuto (errore HTTP 500)."
+ },
+ "status.503": {
+ "message": "Servizio non disponibile."
+ },
+ "status.BadItemSkipped": {
+ "message": "Oggetto errato saltato: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Impossibile eliminare una cartella di sistema."
+ },
+ "status.FolderDelete.4": {
+ "message": "?? Folder does not exist (status 4), resyncing ??"
+ },
+ "status.FolderDelete.6": {
+ "message": "Impossibile completare il comando, si è verificato un errore sul server."
+ },
+ "status.FolderDelete.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.FolderSync.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Il server non fornisce informazioni sulle versioni di ActiveSync supportate. EAS è bloccato per questo utente o questo client (TbSync)? È possibile provare a impostare manualmente la versione di ActiveSync."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Il server EAS ha rifiutato l'ultima richiesta."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Il server EAS non ha accettato ##replace.1## elementi."
+ },
+ "status.Sync.12": {
+ "message": "?? Folder hierarchy changed (status 12), resyncing ??"
+ },
+ "status.Sync.3": {
+ "message": "?? Invalid synchronization key (status 3), resyncing ??"
+ },
+ "status.Sync.4": {
+ "message": "?? Malformed request (status 4) ??"
+ },
+ "status.Sync.5": {
+ "message": "?? Temporary server issues or invalid item (status 5) ??"
+ },
+ "status.Sync.6": {
+ "message": "?? Invalid item (status 6) ??"
+ },
+ "status.Sync.8": {
+ "message": "?? Object not found (status 8) ??"
+ },
+ "status.aborted": {
+ "message": "Non sincronizzato"
+ },
+ "status.disabled": {
+ "message": "L'account non è abilitato, la sincronizzazione è disabilitata."
+ },
+ "status.empty-response": {
+ "message": "Il server invia una risposta vuota inaspettata."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "?? Forbidden calendar item in a task folder (please resort) ??"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "?? Forbidden task item in a calendar folder (please resort) ??"
+ },
+ "status.global.101": {
+ "message": "La richiesta contiene WBXML ma non è possibile decodificarlo in XML (errore 101)."
+ },
+ "status.global.102": {
+ "message": "La richiesta contiene WBXML ma non è possibile decodificarlo in XML (errore 102)."
+ },
+ "status.global.103": {
+ "message": "L'XML fornito nella richiesta non rispetta i requisiti del protocollo (errore 103)."
+ },
+ "status.global.110": {
+ "message": "Il server ha segnalato un errore interno e non dovremmo riprovare immediatamente. La sincronizzazione periodica automatica è stata disattivata per 30 minuti (errore EAS 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "Il server EAS segnala <##replace.2##> (stato ##replace.1##) e non consente a TbSync l'accesso al proprio account."
+ },
+ "status.httperror": {
+ "message": "Errore di comunicazione (stato HTTP ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Risposta del server non valida (inutile)."
+ },
+ "status.malformed-xml": {
+ "message": "Impossibile analizzare XML. Controllare il registro eventi per i dettagli."
+ },
+ "status.modified": {
+ "message": "Modifiche locali presenti"
+ },
+ "status.network": {
+ "message": "Impossibile collegarsi al server (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Impossibile connettersi al server."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Il server non supporta ActiveSync v2.5 o v14.0 (solo ##replace.1##). TbSync non funzionerà con questo server ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Interruzione sincronizzazione in corso: non è possibile creare le destinazioni sincronizzazione."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Il server non supporta la versione di ActiveSync selezionata ##replace.1## (solo ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "L'account deve essere sincronizzato, almeno un elemento non è sincronizzato."
+ },
+ "status.nouserhost": {
+ "message": "Nome utente e/o server mancanti. Fornire tali valori."
+ },
+ "status.pending": {
+ "message": "In attesa di sincronizzazione"
+ },
+ "status.policy.2": {
+ "message": "Non esiste alcuna policy per questo client. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
+ },
+ "status.policy.3": {
+ "message": "Valore PolicyType sconosciuto. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
+ },
+ "status.policy.4": {
+ "message": "I dati di policy sul server sono corrotti (forse alterati). Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
+ },
+ "status.policy.5": {
+ "message": "Il client sta riconoscendo una policy con nome errato. Contattare l'amministratore del proprio server o disabilitare il provisioning per questo account."
+ },
+ "status.provision": {
+ "message": "Provisioning non riuscito: stato <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "La risposta dal server non contiene dati."
+ },
+ "status.resync-loop": {
+ "message": "Si è verificato un errore che non è stato possibile correggere eseguendo una nuova sincronizzazione dell'account. Disabilitare l'account e riprovare. (Errore: ciclo di risincronizzazione)"
+ },
+ "status.security": {
+ "message": "Impossibile stabilire una connessione sicura. Si sta utilizzando un certificato autofirmato o non affidabile senza averlo importato in Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Non ancora supportato, omesso"
+ },
+ "status.syncing": {
+ "message": "Sincronizzazione in corso"
+ },
+ "status.timeout": {
+ "message": "Timeout durante la comunicazione."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Il server invia una risposta illeggibile."
+ },
+ "status.wbxmlerror": {
+ "message": "Sincronizzazione non riuscita. Il server ha risposto con lo stato <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Violazione protocollo ActiveSync: il campo obbligatorio <##replace.1##> manca dalla risposta del server."
+ },
+ "syncstate.accountdone": {
+ "message": "Sincronizzazione account completata"
+ },
+ "syncstate.done": {
+ "message": "Preparazione prossimo elemento per la sincronizzazione in corso"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Elaborazione impostazioni server aggiornate in corso"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Cartella eliminata"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Elaborazione stima modifiche in corso"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Elaborazione aggiornamenti elenco cartelle in corso"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Elaborazione riconoscimento modifiche locali in corso"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Elaborazione riconoscimento eliminazioni locali in corso"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Elaborazione opzioni server in corso"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Elaborazione provisioning in corso"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Elaborazione modifiche remote in corso"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Annullamento modifiche locali in corso"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Invio informazioni dispositivo in corso"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Elaborazione chiave di sincronizzazione in corso"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Richiesta impostazioni server aggiornate in corso"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparazione eliminazione cartella in corso"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Richiesta stima modifiche in corso"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Invio aggiornamenti elenco cartelle in corso"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Invio modifiche locali in corso"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Invio eliminazioni locali in corso"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Richiesta opzioni server in corso"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Richiesta provisioning in corso"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Richiesta modifiche remote in corso"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Raccolta modifiche locali in corso"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Invio informazioni dispositivo in corso"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Richiesta chiave di sincronizzazione in corso"
+ },
+ "syncstate.preparing": {
+ "message": "Preparazione prossimo elemento per la sincronizzazione in corso"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "In attesa delle impostazioni server aggiornate"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "In attesa dell'eliminazione della cartella"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "In attesa della stima modifiche"
+ },
+ "syncstate.send.request.folders": {
+ "message": "In attesa degli aggiornamenti elenco cartelle"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "In attesa del riconoscimento delle modifiche locali"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "In attesa del riconoscimento delle eliminazioni locali"
+ },
+ "syncstate.send.request.options": {
+ "message": "In attesa delle opzioni server"
+ },
+ "syncstate.send.request.provision": {
+ "message": "In attesa del provisioning"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "In attesa delle modifiche remote"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "In attesa delle versioni più recenti"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Invio informazioni dispositivo in corso"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "In attesa della chiave di sincronizzazione"
+ },
+ "syncstate.syncing": {
+ "message": "Inizializzazione sincronizzazione in corso"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/ja/messages.json eas4tbsync-4.17/_locales/ja/messages.json
--- eas4tbsync-4.11/_locales/ja/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/ja/messages.json 2025-05-15 11:21:18.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "記念日:"
- },
- "abCard.AssistantName": {
- "message": "アシスタント:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "アシスタントの電話番号:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "勤務先電話番号 2:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "勤務先 FAX:"
- },
- "abCard.CarPhoneNumber": {
- "message": "自動車電話番号:"
- },
- "abCard.CompanyMainPhone": {
- "message": "勤務先電話番号:"
- },
- "abCard.Email3Address": {
- "message": "電子メール 2:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "自宅電話番号 2:"
- },
- "abCard.ManagerName": {
- "message": "マネージャー:"
- },
- "abCard.MiddleName": {
- "message": "ミドルネーム:"
- },
- "abCard.OtherAddress": {
- "message": "住所:"
- },
- "abCard.OtherCity": {
- "message": "町:"
- },
- "abCard.OtherCountry": {
- "message": "国:"
- },
- "abCard.OtherState": {
- "message": "都道府県:"
- },
- "abCard.OtherZip": {
- "message": "郵便番号:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "無線電話の番号:"
- },
- "abCard.Spouse": {
- "message": "配偶者/パートナー:"
- },
- "abCard.header.eas": {
- "message": "その他の項目 (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "自宅電話番号 3:"
- },
- "abCard.header.messaging": {
- "message": "メッセージング:"
- },
- "abCard.header.otheraddress": {
- "message": "その他のアドレス (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "追加の電話番号:"
- },
- "abCard.header.people": {
- "message": "People:"
- },
- "abCard.header.worknumbers": {
- "message": "勤務先電話番号 3:"
- },
- "acl.readonly": {
- "message": "Read-only server access (revert local changes)"
- },
- "acl.readwrite": {
- "message": "Read from and write to server"
- },
- "add.description": {
- "message": "利用可能なサーバー構成オプションのいずれかを選択し、要求された詳細を入力してください。 "
- },
- "add.name": {
- "message": "アカウント名:"
- },
- "add.ok": {
- "message": "アカウントを追加"
- },
- "add.password": {
- "message": "パスワード:"
- },
- "add.server": {
- "message": "サーバー設定:"
- },
- "add.shortdescription": {
- "message": "アカウント情報"
- },
- "add.title": {
- "message": "Adding an Exchange ActiveSync account to TbSync"
- },
- "add.url": {
- "message": "サーバー アドレス:"
- },
- "add.urldescription": {
- "message": "基本的なサーバーアドレスだけを提供するだけで十分です (例: mail.yourserver.com)。 ただし、完全な URL を提供することもできます (例: https://mail.yourserver.com/Microsoft-Server-ActiveSync)。"
- },
- "add.user": {
- "message": "ユーザー名 (電子メールアドレス):"
- },
- "autocomplete.serverdirectory": {
- "message": "global server directory"
- },
- "autodiscover.Failed": {
- "message": "ユーザー <##user##> の自動検出に失敗しました。指定された資格情報が間違っているか、ActiveSyncプロバイダに一時的な問題があるか、自動検出をサポートしていません。"
- },
- "autodiscover.NeedEmail": {
- "message": "自動検出にはユーザー名として有効なメールアドレスが必要です。"
- },
- "autodiscover.Ok": {
- "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
- },
- "autodiscover.Querying": {
- "message": "設定を検索中…"
- },
- "config.auto": {
- "message": "ActiveSync サーバー設定 (自動検出)"
- },
- "config.custom": {
- "message": "ActiveSync サーバー設定"
- },
- "deletefolder.confirm": {
- "message": "本当にごみ箱からフォルダ '## replace.1 ##' を完全に削除しますか?"
- },
- "deletefolder.menuentry": {
- "message": "ごみ箱からフォルダ '## replace.1 ##' を完全に削除"
- },
- "deletefolder.notallowed": {
- "message": "ゴミ箱から削除する前に、フォルダ “##replace.1##” の登録を解除してください。"
- },
- "extensionDescription": {
- "message": "TbSync に Exchange ActiveSync アカウントの同期サポートを追加します (連絡先、タスクとカレンダー)。"
- },
- "extensionName": {
- "message": "Exchange ActiveSync 用プロバイダ"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "アカウント設定"
- },
- "manager.tabs.outOfOffice": {
- "message": "Auto responder"
- },
- "manager.tabs.syncsettings": {
- "message": "オプション"
- },
- "newaccount.add_auto": {
- "message": "設定を自動検出してアカウントを追加"
- },
- "newaccount.add_custom": {
- "message": "アカウントを追加"
- },
- "pref.AccountName": {
- "message": "説明"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync バージョン"
- },
- "pref.DeviceId": {
- "message": "ActiveSync デバイス ID"
- },
- "pref.ServerName": {
- "message": "サーバー アドレス"
- },
- "pref.ServerNameDescription": {
- "message": "例: mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Show folders found in trash"
- },
- "pref.UserName": {
- "message": "ユーザー名"
- },
- "pref.UserNameDescription": {
- "message": "ユーザー名は通常、あなたのアカウントの電子メールアドレスです。"
- },
- "pref.autodetect": {
- "message": "利用可能な最新のバージョン"
- },
- "pref.birthday": {
- "message": "Send birthday information"
- },
- "pref.calendaroptions": {
- "message": "カレンダー設定"
- },
- "pref.contactoptions": {
- "message": "連絡先設定"
- },
- "pref.displayoverride": {
- "message": "表示名を「名」+「姓」で上書き"
- },
- "pref.generaloptions": {
- "message": "一般設定"
- },
- "pref.provision": {
- "message": "プロビジョニングを強制 (Kerio で必要)"
- },
- "pref.seperator.comma": {
- "message": "カンマ"
- },
- "pref.seperator.description": {
- "message": "Separator for multiline address field."
- },
- "pref.seperator.linebreak": {
- "message": "改行"
- },
- "pref.synclimit.1month": {
- "message": "4 週間前まで"
- },
- "pref.synclimit.2weeks": {
- "message": "2 週間前まで"
- },
- "pref.synclimit.3month": {
- "message": "3 ヶ月前まで"
- },
- "pref.synclimit.6month": {
- "message": "6 ヶ月前まで"
- },
- "pref.synclimit.all": {
- "message": "全て"
- },
- "pref.synclimit.description": {
- "message": "同期する期間: "
- },
- "pref.usehttps": {
- "message": "安全な接続を利用する (https を使用して接続)"
- },
- "recyclebin": {
- "message": "ごみ箱"
- },
- "servertype.auto": {
- "message": "自動設定"
- },
- "servertype.custom": {
- "message": "カスタム設定"
- },
- "servertype.description.auto": {
- "message": "多くの ActiveSync サーバーの構成は、電子メールアドレスを提供するだけで検出できます。"
- },
- "servertype.description.custom": {
- "message": "接続するサーバーのアドレスを手動で入力することにより、アカウントを設定します。"
- },
- "servertype.description.office365": {
- "message": "Office 365に接続されたアカウントは、OAuth 2.0 と呼ばれる最新の認証プロセスを使用します。これは、Multi-Factor-Authentication (MFA、多要素認証) もサポートしています。"
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Double click to unlock all predefined server settings."
- },
- "status.401": {
- "message": "認証できません。ユーザー名とパスワードを確認してください (HTTP エラー 401)。"
- },
- "status.403": {
- "message": "サーバーが接続を拒否しました (禁止) (HTTP エラー 403)。"
- },
- "status.404": {
- "message": "ユーザーが見つかりません (HTTP エラー 404)。"
- },
- "status.449": {
- "message": "サーバーがプロビジョニングを要求しています (HTTP エラー 449)。"
- },
- "status.500": {
- "message": "不明なサーバー エラー (HTTP エラー 500)。"
- },
- "status.503": {
- "message": "サービスが利用できません (HTTP エラー 503)。"
- },
- "status.BadItemSkipped": {
- "message": "不良アイテムがスキップされました: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "システムフォルダを削除できません (ステータス 3)"
- },
- "status.FolderDelete.4": {
- "message": "フォルダが見つかりません (ステータス 4)。再同期中"
- },
- "status.FolderDelete.6": {
- "message": "コマンドを完了できません。サーバーでエラーが発生しました (ステータス 6)"
- },
- "status.FolderDelete.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.FolderSync.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.InvalidServerOptions": {
- "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "The EAS Server rejected the last request."
- },
- "status.ServerRejectedSomeItems": {
- "message": "The EAS server did not accept ##replace.1## elements."
- },
- "status.Sync.12": {
- "message": "フォルダの階層構造が変更されました (ステータス 12)。再同期中"
- },
- "status.Sync.3": {
- "message": "Invalid synchronization key (status 3), resyncing"
- },
- "status.Sync.4": {
- "message": "不正なリクエストです (ステータス 4)"
- },
- "status.Sync.5": {
- "message": "一時的なサーバーの問題、または無効なアイテムです (ステータス 5)"
- },
- "status.Sync.6": {
- "message": "無効なアイテムです (ステータス 6)"
- },
- "status.Sync.8": {
- "message": "オブジェクトが見つかりません (ステータス 8)"
- },
- "status.aborted": {
- "message": "同期されていません"
- },
- "status.disabled": {
- "message": "無効"
- },
- "status.empty-response": {
- "message": "Server sends unexpected empty response."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Forbidden calendar item in a task folder (please resort)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Forbidden task item in a calendar folder (please resort)"
- },
- "status.global.101": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
- },
- "status.global.102": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
- },
- "status.global.103": {
- "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
- },
- "status.global.110": {
- "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
- },
- "status.global.clientdenied": {
- "message": "EAS サーバーは <## replace.2 ##> (ステータス ## replace.1 ##) を報告し、TbSync がアカウントにアクセスすることを許可しませんでした。"
- },
- "status.httperror": {
- "message": "コミュニケーション エラー (HTTP ステータス ##replace.1##)。"
- },
- "status.invalid": {
- "message": "Invalid server response (junk)."
- },
- "status.malformed-xml": {
- "message": "XML を解析できません。詳細はイベントログをご確認ください。"
- },
- "status.modified": {
- "message": "ローカルの変更"
- },
- "status.network": {
- "message": "サーバーに接続できません (##replace.1##)。"
- },
- "status.networkerror": {
- "message": "サーバーに接続できません。"
- },
- "status.nosupportedeasversion": {
- "message": "サーバーは ActiveSync v2.5 または v14.0 をサポートしていません (##replace.1## のみ)。TbSync は、この ActiveSync サーバーでは機能しません。"
- },
- "status.notargets": {
- "message": "Aborting Sync, because sync targets could not be created."
- },
- "status.notsupportedeasversion": {
- "message": "サーバーは選択された ActiveSync v##replace.1## をサポートしていません (##replace.2## のみ)。"
- },
- "status.notsyncronized": {
- "message": "Account needs to be synchronized, at least one item is out of sync."
- },
- "status.nouserhost": {
- "message": "Missing username and/or server. Please provide those values."
- },
- "status.pending": {
- "message": "同期待ち"
- },
- "status.policy.2": {
- "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.3": {
- "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.4": {
- "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.5": {
- "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
- },
- "status.provision": {
- "message": "Provisioning failed with status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Response from the server contains no data."
- },
- "status.resync-loop": {
- "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
- },
- "status.security": {
- "message": "安全な接続を確立できませんでした。Thunderbird にインポートせずに、自己署名証明書または信頼できない証明書を使用していますか? (##replace.1##)"
- },
- "status.skipped": {
- "message": "サポートされていません。スキップします。"
- },
- "status.syncing": {
- "message": "同期中"
- },
- "status.timeout": {
- "message": "接続がタイムアウトしました。"
- },
- "status.wbxml-parse-error": {
- "message": "Server sends unreadable response."
- },
- "status.wbxmlerror": {
- "message": "Sync failed. Server responded with status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync プロトコル違反: 必須フィールド <##replace.1##> がサーバー応答から見つかりません。"
- },
- "syncstate.accountdone": {
- "message": "Finished account"
- },
- "syncstate.done": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Processing updated server settings"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Folder deleted"
- },
- "syncstate.eval.response.estimate": {
- "message": "Processing change estimate"
- },
- "syncstate.eval.response.folders": {
- "message": "Processing folder list update"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Processing acknowledgment of local changes"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Processing acknowledgment of local deletes"
- },
- "syncstate.eval.response.options": {
- "message": "Processing server options"
- },
- "syncstate.eval.response.provision": {
- "message": "Processing provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Processing remote changes"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Reverting local changes"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "デバイス情報を送信中"
- },
- "syncstate.eval.response.synckey": {
- "message": "Processing SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Requesting updated server settings"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "フォルダ削除の準備中"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Requesting change estimate"
- },
- "syncstate.prepare.request.folders": {
- "message": "フォルダリストの更新を送信中"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "ローカルの変更を送信中"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "ローカルの削除を送信中"
- },
- "syncstate.prepare.request.options": {
- "message": "Requesting server options"
- },
- "syncstate.prepare.request.provision": {
- "message": "Requesting provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Requesting remote changes"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "ローカルの変更を収集中"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "デバイス情報を送信中"
- },
- "syncstate.prepare.request.synckey": {
- "message": "同期キーをリクエスト中"
- },
- "syncstate.preparing": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Waiting for updated server settings"
- },
- "syncstate.send.request.deletefolder": {
- "message": "フォルダが削除されるのを待機中"
- },
- "syncstate.send.request.estimate": {
- "message": "Waiting for change estimate"
- },
- "syncstate.send.request.folders": {
- "message": "フォルダリストの更新を待機中"
- },
- "syncstate.send.request.localchanges": {
- "message": "ローカルの変更の承認を待機中"
- },
- "syncstate.send.request.localdeletes": {
- "message": "ローカルの削除の承認を待機中"
- },
- "syncstate.send.request.options": {
- "message": "Waiting for server options"
- },
- "syncstate.send.request.provision": {
- "message": "Waiting for provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "リモートの変更を待機中"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Waiting for most recent versions"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "デバイス情報を送信中"
- },
- "syncstate.send.request.synckey": {
- "message": "同期キーを待機中"
- },
- "syncstate.syncing": {
- "message": "同期を初期化中"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "記念日:"
+ },
+ "abCard.AssistantName": {
+ "message": "アシスタント:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "アシスタントの電話番号:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "勤務先電話番号 2:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "勤務先 FAX:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "自動車電話番号:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "勤務先電話番号:"
+ },
+ "abCard.Email3Address": {
+ "message": "電子メール 2:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "自宅電話番号 2:"
+ },
+ "abCard.ManagerName": {
+ "message": "マネージャー:"
+ },
+ "abCard.MiddleName": {
+ "message": "ミドルネーム:"
+ },
+ "abCard.OtherAddress": {
+ "message": "住所:"
+ },
+ "abCard.OtherCity": {
+ "message": "町:"
+ },
+ "abCard.OtherCountry": {
+ "message": "国:"
+ },
+ "abCard.OtherState": {
+ "message": "都道府県:"
+ },
+ "abCard.OtherZip": {
+ "message": "郵便番号:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "無線電話の番号:"
+ },
+ "abCard.Spouse": {
+ "message": "配偶者/パートナー:"
+ },
+ "abCard.header.eas": {
+ "message": "その他の項目 (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "自宅電話番号 3:"
+ },
+ "abCard.header.messaging": {
+ "message": "メッセージング:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "その他のアドレス (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "追加の電話番号:"
+ },
+ "abCard.header.people": {
+ "message": "People:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "勤務先電話番号 3:"
+ },
+ "acl.readonly": {
+ "message": "Read-only server access (revert local changes)"
+ },
+ "acl.readwrite": {
+ "message": "Read from and write to server"
+ },
+ "add.description": {
+ "message": "利用可能なサーバー構成オプションのいずれかを選択し、要求された詳細を入力してください。 "
+ },
+ "add.name": {
+ "message": "アカウント名:"
+ },
+ "add.ok": {
+ "message": "アカウントを追加"
+ },
+ "add.password": {
+ "message": "パスワード:"
+ },
+ "add.server": {
+ "message": "サーバー設定:"
+ },
+ "add.shortdescription": {
+ "message": "アカウント情報"
+ },
+ "add.title": {
+ "message": "Adding an Exchange ActiveSync account to TbSync"
+ },
+ "add.url": {
+ "message": "サーバー アドレス:"
+ },
+ "add.urldescription": {
+ "message": "基本的なサーバーアドレスだけを提供するだけで十分です (例: mail.yourserver.com)。 ただし、完全な URL を提供することもできます (例: https://mail.yourserver.com/Microsoft-Server-ActiveSync)。"
+ },
+ "add.user": {
+ "message": "ユーザー名 (電子メールアドレス):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "global server directory"
+ },
+ "autodiscover.Failed": {
+ "message": "ユーザー <##user##> の自動検出に失敗しました。指定された資格情報が間違っているか、ActiveSyncプロバイダに一時的な問題があるか、自動検出をサポートしていません。"
+ },
+ "autodiscover.NeedEmail": {
+ "message": "自動検出にはユーザー名として有効なメールアドレスが必要です。"
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
+ },
+ "autodiscover.Querying": {
+ "message": "設定を検索中…"
+ },
+ "config.auto": {
+ "message": "ActiveSync サーバー設定 (自動検出)"
+ },
+ "config.custom": {
+ "message": "ActiveSync サーバー設定"
+ },
+ "deletefolder.confirm": {
+ "message": "本当にごみ箱からフォルダ '## replace.1 ##' を完全に削除しますか?"
+ },
+ "deletefolder.menuentry": {
+ "message": "ごみ箱からフォルダ '## replace.1 ##' を完全に削除"
+ },
+ "deletefolder.notallowed": {
+ "message": "ゴミ箱から削除する前に、フォルダ “##replace.1##” の登録を解除してください。"
+ },
+ "extensionDescription": {
+ "message": "TbSync に Exchange ActiveSync アカウントの同期サポートを追加します (連絡先、タスクとカレンダー)。"
+ },
+ "extensionName": {
+ "message": "Exchange ActiveSync 用プロバイダ"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "アカウント設定"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Auto responder"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "オプション"
+ },
+ "newaccount.add_auto": {
+ "message": "設定を自動検出してアカウントを追加"
+ },
+ "newaccount.add_custom": {
+ "message": "アカウントを追加"
+ },
+ "pref.AccountName": {
+ "message": "説明"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync バージョン"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync デバイス ID"
+ },
+ "pref.ServerName": {
+ "message": "サーバー アドレス"
+ },
+ "pref.ServerNameDescription": {
+ "message": "例: mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Show folders found in trash"
+ },
+ "pref.UserName": {
+ "message": "ユーザー名"
+ },
+ "pref.UserNameDescription": {
+ "message": "ユーザー名は通常、あなたのアカウントの電子メールアドレスです。"
+ },
+ "pref.autodetect": {
+ "message": "利用可能な最新のバージョン"
+ },
+ "pref.birthday": {
+ "message": "Send birthday information"
+ },
+ "pref.calendaroptions": {
+ "message": "カレンダー設定"
+ },
+ "pref.contactoptions": {
+ "message": "連絡先設定"
+ },
+ "pref.displayoverride": {
+ "message": "表示名を「名」+「姓」で上書き"
+ },
+ "pref.generaloptions": {
+ "message": "一般設定"
+ },
+ "pref.provision": {
+ "message": "プロビジョニングを強制 (Kerio で必要)"
+ },
+ "pref.seperator.comma": {
+ "message": "カンマ"
+ },
+ "pref.seperator.description": {
+ "message": "Separator for multiline address field."
+ },
+ "pref.seperator.linebreak": {
+ "message": "改行"
+ },
+ "pref.synclimit.1month": {
+ "message": "4 週間前まで"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "2 週間前まで"
+ },
+ "pref.synclimit.3month": {
+ "message": "3 ヶ月前まで"
+ },
+ "pref.synclimit.6month": {
+ "message": "6 ヶ月前まで"
+ },
+ "pref.synclimit.all": {
+ "message": "全て"
+ },
+ "pref.synclimit.description": {
+ "message": "同期する期間: "
+ },
+ "pref.usehttps": {
+ "message": "安全な接続を利用する (https を使用して接続)"
+ },
+ "recyclebin": {
+ "message": "ごみ箱"
+ },
+ "servertype.auto": {
+ "message": "自動設定"
+ },
+ "servertype.custom": {
+ "message": "カスタム設定"
+ },
+ "servertype.description.auto": {
+ "message": "多くの ActiveSync サーバーの構成は、電子メールアドレスを提供するだけで検出できます。"
+ },
+ "servertype.description.custom": {
+ "message": "接続するサーバーのアドレスを手動で入力することにより、アカウントを設定します。"
+ },
+ "servertype.description.office365": {
+ "message": "Office 365に接続されたアカウントは、OAuth 2.0 と呼ばれる最新の認証プロセスを使用します。これは、Multi-Factor-Authentication (MFA、多要素認証) もサポートしています。"
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Double click to unlock all predefined server settings."
+ },
+ "status.401": {
+ "message": "認証できません。ユーザー名とパスワードを確認してください (HTTP エラー 401)。"
+ },
+ "status.403": {
+ "message": "サーバーが接続を拒否しました (禁止) (HTTP エラー 403)。"
+ },
+ "status.404": {
+ "message": "ユーザーが見つかりません (HTTP エラー 404)。"
+ },
+ "status.449": {
+ "message": "サーバーがプロビジョニングを要求しています (HTTP エラー 449)。"
+ },
+ "status.500": {
+ "message": "不明なサーバー エラー (HTTP エラー 500)。"
+ },
+ "status.503": {
+ "message": "サービスが利用できません (HTTP エラー 503)。"
+ },
+ "status.BadItemSkipped": {
+ "message": "不良アイテムがスキップされました: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "システムフォルダを削除できません (ステータス 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "フォルダが見つかりません (ステータス 4)。再同期中"
+ },
+ "status.FolderDelete.6": {
+ "message": "コマンドを完了できません。サーバーでエラーが発生しました (ステータス 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.FolderSync.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.InvalidServerOptions": {
+ "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "The EAS Server rejected the last request."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "The EAS server did not accept ##replace.1## elements."
+ },
+ "status.Sync.12": {
+ "message": "フォルダの階層構造が変更されました (ステータス 12)。再同期中"
+ },
+ "status.Sync.3": {
+ "message": "Invalid synchronization key (status 3), resyncing"
+ },
+ "status.Sync.4": {
+ "message": "不正なリクエストです (ステータス 4)"
+ },
+ "status.Sync.5": {
+ "message": "一時的なサーバーの問題、または無効なアイテムです (ステータス 5)"
+ },
+ "status.Sync.6": {
+ "message": "無効なアイテムです (ステータス 6)"
+ },
+ "status.Sync.8": {
+ "message": "オブジェクトが見つかりません (ステータス 8)"
+ },
+ "status.aborted": {
+ "message": "同期されていません"
+ },
+ "status.disabled": {
+ "message": "無効"
+ },
+ "status.empty-response": {
+ "message": "Server sends unexpected empty response."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Forbidden calendar item in a task folder (please resort)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Forbidden task item in a calendar folder (please resort)"
+ },
+ "status.global.101": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
+ },
+ "status.global.102": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
+ },
+ "status.global.103": {
+ "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
+ },
+ "status.global.110": {
+ "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "EAS サーバーは <## replace.2 ##> (ステータス ## replace.1 ##) を報告し、TbSync がアカウントにアクセスすることを許可しませんでした。"
+ },
+ "status.httperror": {
+ "message": "コミュニケーション エラー (HTTP ステータス ##replace.1##)。"
+ },
+ "status.invalid": {
+ "message": "Invalid server response (junk)."
+ },
+ "status.malformed-xml": {
+ "message": "XML を解析できません。詳細はイベントログをご確認ください。"
+ },
+ "status.modified": {
+ "message": "ローカルの変更"
+ },
+ "status.network": {
+ "message": "サーバーに接続できません (##replace.1##)。"
+ },
+ "status.networkerror": {
+ "message": "サーバーに接続できません。"
+ },
+ "status.nosupportedeasversion": {
+ "message": "サーバーは ActiveSync v2.5 または v14.0 をサポートしていません (##replace.1## のみ)。TbSync は、この ActiveSync サーバーでは機能しません。"
+ },
+ "status.notargets": {
+ "message": "Aborting Sync, because sync targets could not be created."
+ },
+ "status.notsupportedeasversion": {
+ "message": "サーバーは選択された ActiveSync v##replace.1## をサポートしていません (##replace.2## のみ)。"
+ },
+ "status.notsyncronized": {
+ "message": "Account needs to be synchronized, at least one item is out of sync."
+ },
+ "status.nouserhost": {
+ "message": "Missing username and/or server. Please provide those values."
+ },
+ "status.pending": {
+ "message": "同期待ち"
+ },
+ "status.policy.2": {
+ "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.3": {
+ "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.4": {
+ "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.5": {
+ "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.provision": {
+ "message": "Provisioning failed with status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Response from the server contains no data."
+ },
+ "status.resync-loop": {
+ "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
+ },
+ "status.security": {
+ "message": "安全な接続を確立できませんでした。Thunderbird にインポートせずに、自己署名証明書または信頼できない証明書を使用していますか? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "サポートされていません。スキップします。"
+ },
+ "status.syncing": {
+ "message": "同期中"
+ },
+ "status.timeout": {
+ "message": "接続がタイムアウトしました。"
+ },
+ "status.wbxml-parse-error": {
+ "message": "Server sends unreadable response."
+ },
+ "status.wbxmlerror": {
+ "message": "Sync failed. Server responded with status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync プロトコル違反: 必須フィールド <##replace.1##> がサーバー応答から見つかりません。"
+ },
+ "syncstate.accountdone": {
+ "message": "Finished account"
+ },
+ "syncstate.done": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Processing updated server settings"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Folder deleted"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Processing change estimate"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Processing folder list update"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Processing acknowledgment of local changes"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Processing acknowledgment of local deletes"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Processing server options"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Processing provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Processing remote changes"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Reverting local changes"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "デバイス情報を送信中"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Processing SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Requesting updated server settings"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "フォルダ削除の準備中"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Requesting change estimate"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "フォルダリストの更新を送信中"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "ローカルの変更を送信中"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "ローカルの削除を送信中"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Requesting server options"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Requesting provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Requesting remote changes"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "ローカルの変更を収集中"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "デバイス情報を送信中"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "同期キーをリクエスト中"
+ },
+ "syncstate.preparing": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Waiting for updated server settings"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "フォルダが削除されるのを待機中"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Waiting for change estimate"
+ },
+ "syncstate.send.request.folders": {
+ "message": "フォルダリストの更新を待機中"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "ローカルの変更の承認を待機中"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "ローカルの削除の承認を待機中"
+ },
+ "syncstate.send.request.options": {
+ "message": "Waiting for server options"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Waiting for provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "リモートの変更を待機中"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Waiting for most recent versions"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "デバイス情報を送信中"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "同期キーを待機中"
+ },
+ "syncstate.syncing": {
+ "message": "同期を初期化中"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/pl/messages.json eas4tbsync-4.17/_locales/pl/messages.json
--- eas4tbsync-4.11/_locales/pl/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/pl/messages.json 2025-05-15 11:21:20.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Rocznica:"
- },
- "abCard.AssistantName": {
- "message": "Asystent:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Telefon Asystenta:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Alternatywny Telefon Służbowy:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Faks służbowy:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Telefon w Aucie:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Główny Telefon Służbowy:"
- },
- "abCard.Email3Address": {
- "message": "Alternatywny e-mail:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Alternatywny Telefon Domowy:"
- },
- "abCard.ManagerName": {
- "message": "Menedżer:"
- },
- "abCard.MiddleName": {
- "message": "Drugie imię:"
- },
- "abCard.OtherAddress": {
- "message": "Adres:"
- },
- "abCard.OtherCity": {
- "message": "Miasto:"
- },
- "abCard.OtherCountry": {
- "message": "Państwo:"
- },
- "abCard.OtherState": {
- "message": "Województwo:"
- },
- "abCard.OtherZip": {
- "message": "Kod pocztowy:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radiotelefon:"
- },
- "abCard.Spouse": {
- "message": "Małżonek:"
- },
- "abCard.header.eas": {
- "message": "Inne Pola (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Dodatkowe numery domowe:"
- },
- "abCard.header.messaging": {
- "message": "Komunikatory:"
- },
- "abCard.header.otheraddress": {
- "message": "Inne Adresy (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Dodatkowe numery:"
- },
- "abCard.header.people": {
- "message": "Osoby:"
- },
- "abCard.header.worknumbers": {
- "message": "Dodatkowe numery służbowe:"
- },
- "acl.readonly": {
- "message": "Dostęp do serwera tylko do odczytu (cofnij zmiany lokalne)"
- },
- "acl.readwrite": {
- "message": "Odczytuj i zapisuj na serwer"
- },
- "add.description": {
- "message": "Wybierz jedną z dostępnych opcji konfiguracji serwera i wprowadź wymagane dane. "
- },
- "add.name": {
- "message": "Nazwa konta:"
- },
- "add.ok": {
- "message": "Dodaj konto"
- },
- "add.password": {
- "message": "Hasło:"
- },
- "add.server": {
- "message": "Konfiguracja serwera:"
- },
- "add.shortdescription": {
- "message": "Informacje o koncie"
- },
- "add.title": {
- "message": "Dodawanie konta Exchange ActiveSync do TbSync"
- },
- "add.url": {
- "message": "Adres serwera:"
- },
- "add.urldescription": {
- "message": "Powinno wystarczyć podanie tylko podstawowego adresu serwera (np.: mail.twojserwer.com). Jednakże możliwe jest również podanie pełnego adresu URL (np.: https://mail.twojserwer.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Nazwa użytkownika (adres e-mail):"
- },
- "autocomplete.serverdirectory": {
- "message": "globalny katalog serwera"
- },
- "autodiscover.Failed": {
- "message": "Auto-wykrywanie dla użytkownika <##user##> nie powiodło się. Podane dane uwierzytelniające były nieprawidłowe lub dostawca ActiveSync ma tymczasowy problem lub nie obsługuje funkcji automatycznego wykrywania."
- },
- "autodiscover.NeedEmail": {
- "message": "Automatyczne wykrywanie potrzebuje prawidłowego adresu e-mail jako nazwy użytkownika."
- },
- "autodiscover.Ok": {
- "message": "Automatyczne wykrywanie zakończyło się pomyślnie, możesz teraz sprawdzić ustawienia opcjonalne i ustanowić połączenie synchronizacji."
- },
- "autodiscover.Querying": {
- "message": "Wyszukiwanie ustawień…"
- },
- "config.auto": {
- "message": "Konfiguracja serwera ActiveSync (Auto-wykrywanie)"
- },
- "config.custom": {
- "message": "Konfiguracja serwera ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "Czy naprawdę chcesz TRWALE USUNĄĆ folder “##replace.1##” z kosza?"
- },
- "deletefolder.menuentry": {
- "message": "Trwale usuń folder “##replace.1##” z kosza"
- },
- "deletefolder.notallowed": {
- "message": "Anuluj subskrypcję folderu “##replace.1##” przed próbą usunięcia go z kosza."
- },
- "extensionDescription": {
- "message": "Dodaj obsługę synchronizacji kont Exchange ActiveSync do TbSync (kontakty, zadania i kalendarze)."
- },
- "extensionName": {
- "message": "Dostawca dla Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Ustawienia konta"
- },
- "manager.tabs.outOfOffice": {
- "message": "Automatyczna odpowiedź"
- },
- "manager.tabs.syncsettings": {
- "message": "Opcje"
- },
- "newaccount.add_auto": {
- "message": "Wykryj automatycznie ustawienia i dodaj konto"
- },
- "newaccount.add_custom": {
- "message": "Dodaj konto"
- },
- "pref.AccountName": {
- "message": "Opis"
- },
- "pref.ActiveSyncVersion": {
- "message": "Wersja ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID urządzenia ActiveSync"
- },
- "pref.ServerName": {
- "message": "Adres serwera"
- },
- "pref.ServerNameDescription": {
- "message": "np. mail.twojserwer.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Pokaż foldery znalezione w koszu"
- },
- "pref.UserName": {
- "message": "Nazwa użytkownika"
- },
- "pref.UserNameDescription": {
- "message": "Nazwa użytkownika to zazwyczaj adres e-mail Twojego konta."
- },
- "pref.autodetect": {
- "message": "najlepsza dostępna"
- },
- "pref.birthday": {
- "message": "Wyślij informacje o urodzinach"
- },
- "pref.calendaroptions": {
- "message": "Opcje kalendarza"
- },
- "pref.contactoptions": {
- "message": "Opcje kontaktu"
- },
- "pref.displayoverride": {
- "message": "Zastąp nazwę wyświetlaną ciągiem “Imię“ + “Drugie imię”"
- },
- "pref.generaloptions": {
- "message": "Opcje ogólne"
- },
- "pref.provision": {
- "message": "Wymuś provisioning (wymagane przez Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Przecinek"
- },
- "pref.seperator.description": {
- "message": "Separator pola adresu wielowierszowego."
- },
- "pref.seperator.linebreak": {
- "message": "Znak końca linii"
- },
- "pref.synclimit.1month": {
- "message": "z 4 tygodni"
- },
- "pref.synclimit.2weeks": {
- "message": "z 2 tygodni"
- },
- "pref.synclimit.3month": {
- "message": "z 3 miesięcy"
- },
- "pref.synclimit.6month": {
- "message": "z 6 miesięcy"
- },
- "pref.synclimit.all": {
- "message": "wszystko"
- },
- "pref.synclimit.description": {
- "message": "Okres synchronizacji: "
- },
- "pref.usehttps": {
- "message": "Użyj bezpiecznego połączenia (połącz przez https)"
- },
- "recyclebin": {
- "message": "Kosz"
- },
- "servertype.auto": {
- "message": "Automatyczna konfiguracja"
- },
- "servertype.custom": {
- "message": "Konfiguracja niestandardowa"
- },
- "servertype.description.auto": {
- "message": "Konfiguracja dla wielu serwerów ActiveSync może zostać odnaleziona poprzez podanie tylko adresu e-mail."
- },
- "servertype.description.custom": {
- "message": "Skonfiguruj konto, podając ręcznie adres serwera, z którym chcesz się połączyć."
- },
- "servertype.description.office365": {
- "message": "Konta połączone z Office 365 korzystają z nowoczesnego procesu uwierzytelniania o nazwie OAuth 2.0, który obsługuje również uwierzytelnianie wielopoziomowe (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Kliknij dwukrotnie, aby odblokować wszystkie predefiniowane ustawienia serwera."
- },
- "status.401": {
- "message": "Nie można uwierzytelnić, sprawdź nazwę użytkownika i hasło (HTTP Error 401)."
- },
- "status.403": {
- "message": "Serwer odrzucił połączenie (zabronione) (błąd HTTP 403)."
- },
- "status.404": {
- "message": "Użytkownik nie znaleziony (błąd HTTP 404)."
- },
- "status.449": {
- "message": "Server requests provisioning (HTTP Error 449)."
- },
- "status.500": {
- "message": "Nieznany błąd serwera (błąd HTTP 500)."
- },
- "status.503": {
- "message": "Usługa niedostępna (błąd HTTP 503)."
- },
- "status.BadItemSkipped": {
- "message": "Błędny element pominięto: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Nie można usunąć folderu systemowego (status 3)"
- },
- "status.FolderDelete.4": {
- "message": "Folder nie istnieje (status 4), ponowna synchronizacja"
- },
- "status.FolderDelete.6": {
- "message": "Nie można wykonać polecenia, wystąpił błąd na serwerze (status 6)"
- },
- "status.FolderDelete.9": {
- "message": "Nieprawidłowy klucz synchronizacji (status 9), ponowna synchronizacja"
- },
- "status.FolderSync.9": {
- "message": "Nieprawidłowy klucz synchronizacji (status 9), ponowna synchronizacja"
- },
- "status.InvalidServerOptions": {
- "message": "Serwer nie dostarcza informacji o obsługiwanych wersjach ActiveSync. Czy EAS jest zablokowany dla tego użytkownika lub tego klienta (TbSync)? Możesz spróbować ręcznie ustawić wersję ActiveSync."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "Serwer EAS odrzucił ostatnie żądanie."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Serwer EAS nie zaakceptował #replace.1## elementów."
- },
- "status.Sync.12": {
- "message": "Hierarchia folderów zmieniona (status 12), ponowna synchronizacja"
- },
- "status.Sync.3": {
- "message": "Nieprawidłowy klucz synchronizacji (status 3), ponowna synchronizacja"
- },
- "status.Sync.4": {
- "message": "Zniekształcone żądanie (status 4)"
- },
- "status.Sync.5": {
- "message": "Tymczasowe problemy z serwerem lub nieprawidłowy element (status 5)"
- },
- "status.Sync.6": {
- "message": "Nieprawidłowy element (status 6)"
- },
- "status.Sync.8": {
- "message": "Nie znaleziono obiektu (status 8)"
- },
- "status.aborted": {
- "message": "Nie zsynchronizowane"
- },
- "status.disabled": {
- "message": "Wyłączony"
- },
- "status.empty-response": {
- "message": "Serwer wysyła nieoczekiwaną pustą odpowiedź."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Niedozwolony element kalendarza w folderze zadań (please resort)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Niedozwolony element zadania w folderze kalendarza (please resort)"
- },
- "status.global.101": {
- "message": "Żądanie zawiera WBXML, ale nie można go zdekodować do formatu XML (błąd EAS 101)."
- },
- "status.global.102": {
- "message": "Żądanie zawiera WBXML, ale nie można go zdekodować do formatu XML (błąd EAS 102)."
- },
- "status.global.103": {
- "message": "XML podany w żądaniu nie jest zgodny z wymaganiami protokołu (błąd EAS 103)."
- },
- "status.global.110": {
- "message": "Serwer zgłosił błąd wewnętrzny i nie powinniśmy natychmiast ponawiać próby. Automatyczna synchronizacja okresowa została wyłączona na 30 minut (błąd EAS 110)."
- },
- "status.global.clientdenied": {
- "message": "Serwer EAS zgłasza <##replace.2##> (status ##replace.1##) i nie zezwala TbSync na dostęp do Twojego konta."
- },
- "status.httperror": {
- "message": "Błąd komunikacji (status HTTP ##replace.1##)."
- },
- "status.invalid": {
- "message": "Niepoprawna odpowiedź serwera (śmieci)."
- },
- "status.malformed-xml": {
- "message": "Nie można przetworzyć XML. Sprawdź dziennik zdarzeń, aby uzyskać szczegóły."
- },
- "status.modified": {
- "message": "Zmiany lokalne"
- },
- "status.network": {
- "message": "Nie można połączyć z serwerem (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Nie można połączyć z serwerem."
- },
- "status.nosupportedeasversion": {
- "message": "Serwer nie obsługuje ActiveSync v2.5 lub v14.0 (tylko ##replace.1##). TbSync nie będzie działać z tym serwerem ActiveSync."
- },
- "status.notargets": {
- "message": "Przerywam synchronizację, ponieważ nie można utworzyć celów synchronizacji."
- },
- "status.notsupportedeasversion": {
- "message": "Serwer nie wspiera wybranego ActiveSync v##replace.1## (tylko ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Konto musi zostać zsynchronizowane, co najmniej jeden element nie jest zsynchronizowany."
- },
- "status.nouserhost": {
- "message": "Brak nazwy użytkownika i/lub serwera. Proszę podać te wartości."
- },
- "status.pending": {
- "message": "Oczekiwanie na synchronizację"
- },
- "status.policy.2": {
- "message": "Brak zasad dla tego klienta. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
- },
- "status.policy.3": {
- "message": "Nieznana wartość PolicyType. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
- },
- "status.policy.4": {
- "message": "Dane zasad na serwerze są uszkodzone (prawdopodobnie zmienione/sfałszowane). Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
- },
- "status.policy.5": {
- "message": "Klient potwierdza zły klucz zasad. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
- },
- "status.provision": {
- "message": "Niepowodzenie provisioning ze statusem <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Odpowiedź z serwera nie zawiera danych."
- },
- "status.resync-loop": {
- "message": "Wystąpił błąd, którego nie udało się naprawić poprzez ponowne zsynchronizowanie konta. Wyłącz konto i spróbuj ponownie. (Błąd: pętla resynchronizacji)"
- },
- "status.security": {
- "message": "Nie można nawiązać bezpiecznego połączenia. Czy używasz własnego podpisu lub w inny sposób niezaufanego certyfikatu bez importowania go do Thunderbirda? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Jeszcze nie obsługiwane, pominięto"
- },
- "status.syncing": {
- "message": "Synchronizuję"
- },
- "status.timeout": {
- "message": "Przekroczony limit czasu połączenia."
- },
- "status.wbxml-parse-error": {
- "message": "Serwer wysyła nieczytelną odpowiedź."
- },
- "status.wbxmlerror": {
- "message": "Synchronizacja nie powiodła się. Serwer odpowiedział statusem <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Naruszenie protokołu ActiveSync: W odpowiedzi serwera brakuje obowiązkowego pola <##replace.1##>."
- },
- "syncstate.accountdone": {
- "message": "Konto gotowe"
- },
- "syncstate.done": {
- "message": "Przygotowuję następny element do synchronizacji"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Przetwarzanie zaktualizowanych ustawień serwera"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Folder usunięty"
- },
- "syncstate.eval.response.estimate": {
- "message": "Przetwarzanie oszacowanych zmian"
- },
- "syncstate.eval.response.folders": {
- "message": "Przetwarzanie aktualizacji listy folderów"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Przetwarzanie potwierdzenia lokalnych zmian"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Przetwarzanie potwierdzenia usunięcia lokalnego"
- },
- "syncstate.eval.response.options": {
- "message": "Przetwarzanie opcji serwera"
- },
- "syncstate.eval.response.provision": {
- "message": "Przetwarzanie provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Przetwarzanie zdalnych zmian"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Wycofywanie zmian lokalnych"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Wysyłanie informacji o urządzeniu"
- },
- "syncstate.eval.response.synckey": {
- "message": "Przetwarzanie SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Żądanie zaktualizowanych ustawień serwera"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Przygotowanie do usunięcia folderu"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Żądanie oszacowanych zmian"
- },
- "syncstate.prepare.request.folders": {
- "message": "Wysyłanie aktualizacji listy folderów"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Wysyłanie zmian lokalnych"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Wysyłanie usuniętych lokalnie"
- },
- "syncstate.prepare.request.options": {
- "message": "Żądanie opcji serwera"
- },
- "syncstate.prepare.request.provision": {
- "message": "Żądanie provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Żądanie zdalnych zmian"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Zbieranie zmian lokalnych"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Wysyłanie informacji o urządzeniu"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Żądanie SyncKey"
- },
- "syncstate.preparing": {
- "message": "Przygotowuję następny element do synchronizacji"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Oczekiwanie na zaktualizowane ustawienia serwera"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Oczekiwanie na usunięcie folderu"
- },
- "syncstate.send.request.estimate": {
- "message": "Oczekiwanie na oszacowanie zmian"
- },
- "syncstate.send.request.folders": {
- "message": "Oczekiwanie na aktualizację listy folderów"
- },
- "syncstate.send.request.localchanges": {
- "message": "Oczekiwanie na potwierdzenie lokalnych zmian"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Oczekiwanie na potwierdzenie usunięcia lokalnego"
- },
- "syncstate.send.request.options": {
- "message": "Oczekiwanie na opcje serwera"
- },
- "syncstate.send.request.provision": {
- "message": "Oczekiwanie na provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Oczekiwanie na zdalne zmiany"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Oczekiwanie na najnowsze wersje"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Wysyłanie informacji o urządzeniu"
- },
- "syncstate.send.request.synckey": {
- "message": "Oczekiwanie na SyncKey"
- },
- "syncstate.syncing": {
- "message": "Zainicjuj synchronizację"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Rocznica:"
+ },
+ "abCard.AssistantName": {
+ "message": "Asystent:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Telefon Asystenta:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Alternatywny Telefon Służbowy:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Faks służbowy:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Telefon w Aucie:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Główny Telefon Służbowy:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternatywny e-mail:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Alternatywny Telefon Domowy:"
+ },
+ "abCard.ManagerName": {
+ "message": "Menedżer:"
+ },
+ "abCard.MiddleName": {
+ "message": "Drugie imię:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Adres:"
+ },
+ "abCard.OtherCity": {
+ "message": "Miasto:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Państwo:"
+ },
+ "abCard.OtherState": {
+ "message": "Województwo:"
+ },
+ "abCard.OtherZip": {
+ "message": "Kod pocztowy:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radiotelefon:"
+ },
+ "abCard.Spouse": {
+ "message": "Małżonek:"
+ },
+ "abCard.header.eas": {
+ "message": "Inne Pola (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Dodatkowe numery domowe:"
+ },
+ "abCard.header.messaging": {
+ "message": "Komunikatory:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Inne Adresy (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Dodatkowe numery:"
+ },
+ "abCard.header.people": {
+ "message": "Osoby:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Dodatkowe numery służbowe:"
+ },
+ "acl.readonly": {
+ "message": "Dostęp do serwera tylko do odczytu (cofnij zmiany lokalne)"
+ },
+ "acl.readwrite": {
+ "message": "Odczytuj i zapisuj na serwer"
+ },
+ "add.description": {
+ "message": "Wybierz jedną z dostępnych opcji konfiguracji serwera i wprowadź wymagane dane. "
+ },
+ "add.name": {
+ "message": "Nazwa konta:"
+ },
+ "add.ok": {
+ "message": "Dodaj konto"
+ },
+ "add.password": {
+ "message": "Hasło:"
+ },
+ "add.server": {
+ "message": "Konfiguracja serwera:"
+ },
+ "add.shortdescription": {
+ "message": "Informacje o koncie"
+ },
+ "add.title": {
+ "message": "Dodawanie konta Exchange ActiveSync do TbSync"
+ },
+ "add.url": {
+ "message": "Adres serwera:"
+ },
+ "add.urldescription": {
+ "message": "Powinno wystarczyć podanie tylko podstawowego adresu serwera (np.: mail.twojserwer.com). Jednakże możliwe jest również podanie pełnego adresu URL (np.: https://mail.twojserwer.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Nazwa użytkownika (adres e-mail):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "globalny katalog serwera"
+ },
+ "autodiscover.Failed": {
+ "message": "Auto-wykrywanie dla użytkownika <##user##> nie powiodło się. Podane dane uwierzytelniające były nieprawidłowe lub dostawca ActiveSync ma tymczasowy problem lub nie obsługuje funkcji automatycznego wykrywania."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Automatyczne wykrywanie potrzebuje prawidłowego adresu e-mail jako nazwy użytkownika."
+ },
+ "autodiscover.Ok": {
+ "message": "Automatyczne wykrywanie zakończyło się pomyślnie, możesz teraz sprawdzić ustawienia opcjonalne i ustanowić połączenie synchronizacji."
+ },
+ "autodiscover.Querying": {
+ "message": "Wyszukiwanie ustawień…"
+ },
+ "config.auto": {
+ "message": "Konfiguracja serwera ActiveSync (Auto-wykrywanie)"
+ },
+ "config.custom": {
+ "message": "Konfiguracja serwera ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "Czy naprawdę chcesz TRWALE USUNĄĆ folder “##replace.1##” z kosza?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Trwale usuń folder “##replace.1##” z kosza"
+ },
+ "deletefolder.notallowed": {
+ "message": "Anuluj subskrypcję folderu “##replace.1##” przed próbą usunięcia go z kosza."
+ },
+ "extensionDescription": {
+ "message": "Dodaj obsługę synchronizacji kont Exchange ActiveSync do TbSync (kontakty, zadania i kalendarze)."
+ },
+ "extensionName": {
+ "message": "Dostawca dla Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Ustawienia konta"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Automatyczna odpowiedź"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Opcje"
+ },
+ "newaccount.add_auto": {
+ "message": "Wykryj automatycznie ustawienia i dodaj konto"
+ },
+ "newaccount.add_custom": {
+ "message": "Dodaj konto"
+ },
+ "pref.AccountName": {
+ "message": "Opis"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Wersja ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID urządzenia ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Adres serwera"
+ },
+ "pref.ServerNameDescription": {
+ "message": "np. mail.twojserwer.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Pokaż foldery znalezione w koszu"
+ },
+ "pref.UserName": {
+ "message": "Nazwa użytkownika"
+ },
+ "pref.UserNameDescription": {
+ "message": "Nazwa użytkownika to zazwyczaj adres e-mail Twojego konta."
+ },
+ "pref.autodetect": {
+ "message": "najlepsza dostępna"
+ },
+ "pref.birthday": {
+ "message": "Wyślij informacje o urodzinach"
+ },
+ "pref.calendaroptions": {
+ "message": "Opcje kalendarza"
+ },
+ "pref.contactoptions": {
+ "message": "Opcje kontaktu"
+ },
+ "pref.displayoverride": {
+ "message": "Zastąp nazwę wyświetlaną ciągiem “Imię“ + “Drugie imię”"
+ },
+ "pref.generaloptions": {
+ "message": "Opcje ogólne"
+ },
+ "pref.provision": {
+ "message": "Wymuś provisioning (wymagane przez Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Przecinek"
+ },
+ "pref.seperator.description": {
+ "message": "Separator pola adresu wielowierszowego."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Znak końca linii"
+ },
+ "pref.synclimit.1month": {
+ "message": "z 4 tygodni"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "z 2 tygodni"
+ },
+ "pref.synclimit.3month": {
+ "message": "z 3 miesięcy"
+ },
+ "pref.synclimit.6month": {
+ "message": "z 6 miesięcy"
+ },
+ "pref.synclimit.all": {
+ "message": "wszystko"
+ },
+ "pref.synclimit.description": {
+ "message": "Okres synchronizacji: "
+ },
+ "pref.usehttps": {
+ "message": "Użyj bezpiecznego połączenia (połącz przez https)"
+ },
+ "recyclebin": {
+ "message": "Kosz"
+ },
+ "servertype.auto": {
+ "message": "Automatyczna konfiguracja"
+ },
+ "servertype.custom": {
+ "message": "Konfiguracja niestandardowa"
+ },
+ "servertype.description.auto": {
+ "message": "Konfiguracja dla wielu serwerów ActiveSync może zostać odnaleziona poprzez podanie tylko adresu e-mail."
+ },
+ "servertype.description.custom": {
+ "message": "Skonfiguruj konto, podając ręcznie adres serwera, z którym chcesz się połączyć."
+ },
+ "servertype.description.office365": {
+ "message": "Konta połączone z Office 365 korzystają z nowoczesnego procesu uwierzytelniania o nazwie OAuth 2.0, który obsługuje również uwierzytelnianie wielopoziomowe (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Kliknij dwukrotnie, aby odblokować wszystkie predefiniowane ustawienia serwera."
+ },
+ "status.401": {
+ "message": "Nie można uwierzytelnić, sprawdź nazwę użytkownika i hasło (HTTP Error 401)."
+ },
+ "status.403": {
+ "message": "Serwer odrzucił połączenie (zabronione) (błąd HTTP 403)."
+ },
+ "status.404": {
+ "message": "Użytkownik nie znaleziony (błąd HTTP 404)."
+ },
+ "status.449": {
+ "message": "Server requests provisioning (HTTP Error 449)."
+ },
+ "status.500": {
+ "message": "Nieznany błąd serwera (błąd HTTP 500)."
+ },
+ "status.503": {
+ "message": "Usługa niedostępna (błąd HTTP 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Błędny element pominięto: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Nie można usunąć folderu systemowego (status 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Folder nie istnieje (status 4), ponowna synchronizacja"
+ },
+ "status.FolderDelete.6": {
+ "message": "Nie można wykonać polecenia, wystąpił błąd na serwerze (status 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Nieprawidłowy klucz synchronizacji (status 9), ponowna synchronizacja"
+ },
+ "status.FolderSync.9": {
+ "message": "Nieprawidłowy klucz synchronizacji (status 9), ponowna synchronizacja"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Serwer nie dostarcza informacji o obsługiwanych wersjach ActiveSync. Czy EAS jest zablokowany dla tego użytkownika lub tego klienta (TbSync)? Możesz spróbować ręcznie ustawić wersję ActiveSync."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Serwer EAS odrzucił ostatnie żądanie."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Serwer EAS nie zaakceptował #replace.1## elementów."
+ },
+ "status.Sync.12": {
+ "message": "Hierarchia folderów zmieniona (status 12), ponowna synchronizacja"
+ },
+ "status.Sync.3": {
+ "message": "Nieprawidłowy klucz synchronizacji (status 3), ponowna synchronizacja"
+ },
+ "status.Sync.4": {
+ "message": "Zniekształcone żądanie (status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Tymczasowe problemy z serwerem lub nieprawidłowy element (status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Nieprawidłowy element (status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Nie znaleziono obiektu (status 8)"
+ },
+ "status.aborted": {
+ "message": "Nie zsynchronizowane"
+ },
+ "status.disabled": {
+ "message": "Wyłączony"
+ },
+ "status.empty-response": {
+ "message": "Serwer wysyła nieoczekiwaną pustą odpowiedź."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Niedozwolony element kalendarza w folderze zadań (please resort)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Niedozwolony element zadania w folderze kalendarza (please resort)"
+ },
+ "status.global.101": {
+ "message": "Żądanie zawiera WBXML, ale nie można go zdekodować do formatu XML (błąd EAS 101)."
+ },
+ "status.global.102": {
+ "message": "Żądanie zawiera WBXML, ale nie można go zdekodować do formatu XML (błąd EAS 102)."
+ },
+ "status.global.103": {
+ "message": "XML podany w żądaniu nie jest zgodny z wymaganiami protokołu (błąd EAS 103)."
+ },
+ "status.global.110": {
+ "message": "Serwer zgłosił błąd wewnętrzny i nie powinniśmy natychmiast ponawiać próby. Automatyczna synchronizacja okresowa została wyłączona na 30 minut (błąd EAS 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "Serwer EAS zgłasza <##replace.2##> (status ##replace.1##) i nie zezwala TbSync na dostęp do Twojego konta."
+ },
+ "status.httperror": {
+ "message": "Błąd komunikacji (status HTTP ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Niepoprawna odpowiedź serwera (śmieci)."
+ },
+ "status.malformed-xml": {
+ "message": "Nie można przetworzyć XML. Sprawdź dziennik zdarzeń, aby uzyskać szczegóły."
+ },
+ "status.modified": {
+ "message": "Zmiany lokalne"
+ },
+ "status.network": {
+ "message": "Nie można połączyć z serwerem (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Nie można połączyć z serwerem."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Serwer nie obsługuje ActiveSync v2.5 lub v14.0 (tylko ##replace.1##). TbSync nie będzie działać z tym serwerem ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Przerywam synchronizację, ponieważ nie można utworzyć celów synchronizacji."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Serwer nie wspiera wybranego ActiveSync v##replace.1## (tylko ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Konto musi zostać zsynchronizowane, co najmniej jeden element nie jest zsynchronizowany."
+ },
+ "status.nouserhost": {
+ "message": "Brak nazwy użytkownika i/lub serwera. Proszę podać te wartości."
+ },
+ "status.pending": {
+ "message": "Oczekiwanie na synchronizację"
+ },
+ "status.policy.2": {
+ "message": "Brak zasad dla tego klienta. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
+ },
+ "status.policy.3": {
+ "message": "Nieznana wartość PolicyType. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
+ },
+ "status.policy.4": {
+ "message": "Dane zasad na serwerze są uszkodzone (prawdopodobnie zmienione/sfałszowane). Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
+ },
+ "status.policy.5": {
+ "message": "Klient potwierdza zły klucz zasad. Skontaktuj się z administratorem serwera lub wyłącz provisioning dla tego konta."
+ },
+ "status.provision": {
+ "message": "Niepowodzenie provisioning ze statusem <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Odpowiedź z serwera nie zawiera danych."
+ },
+ "status.resync-loop": {
+ "message": "Wystąpił błąd, którego nie udało się naprawić poprzez ponowne zsynchronizowanie konta. Wyłącz konto i spróbuj ponownie. (Błąd: pętla resynchronizacji)"
+ },
+ "status.security": {
+ "message": "Nie można nawiązać bezpiecznego połączenia. Czy używasz własnego podpisu lub w inny sposób niezaufanego certyfikatu bez importowania go do Thunderbirda? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Jeszcze nie obsługiwane, pominięto"
+ },
+ "status.syncing": {
+ "message": "Synchronizuję"
+ },
+ "status.timeout": {
+ "message": "Przekroczony limit czasu połączenia."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Serwer wysyła nieczytelną odpowiedź."
+ },
+ "status.wbxmlerror": {
+ "message": "Synchronizacja nie powiodła się. Serwer odpowiedział statusem <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Naruszenie protokołu ActiveSync: W odpowiedzi serwera brakuje obowiązkowego pola <##replace.1##>."
+ },
+ "syncstate.accountdone": {
+ "message": "Konto gotowe"
+ },
+ "syncstate.done": {
+ "message": "Przygotowuję następny element do synchronizacji"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Przetwarzanie zaktualizowanych ustawień serwera"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Folder usunięty"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Przetwarzanie oszacowanych zmian"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Przetwarzanie aktualizacji listy folderów"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Przetwarzanie potwierdzenia lokalnych zmian"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Przetwarzanie potwierdzenia usunięcia lokalnego"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Przetwarzanie opcji serwera"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Przetwarzanie provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Przetwarzanie zdalnych zmian"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Wycofywanie zmian lokalnych"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Wysyłanie informacji o urządzeniu"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Przetwarzanie SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Żądanie zaktualizowanych ustawień serwera"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Przygotowanie do usunięcia folderu"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Żądanie oszacowanych zmian"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Wysyłanie aktualizacji listy folderów"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Wysyłanie zmian lokalnych"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Wysyłanie usuniętych lokalnie"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Żądanie opcji serwera"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Żądanie provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Żądanie zdalnych zmian"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Zbieranie zmian lokalnych"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Wysyłanie informacji o urządzeniu"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Żądanie SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Przygotowuję następny element do synchronizacji"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Oczekiwanie na zaktualizowane ustawienia serwera"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Oczekiwanie na usunięcie folderu"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Oczekiwanie na oszacowanie zmian"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Oczekiwanie na aktualizację listy folderów"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Oczekiwanie na potwierdzenie lokalnych zmian"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Oczekiwanie na potwierdzenie usunięcia lokalnego"
+ },
+ "syncstate.send.request.options": {
+ "message": "Oczekiwanie na opcje serwera"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Oczekiwanie na provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Oczekiwanie na zdalne zmiany"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Oczekiwanie na najnowsze wersje"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Wysyłanie informacji o urządzeniu"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Oczekiwanie na SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Zainicjuj synchronizację"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/pt_BR/messages.json eas4tbsync-4.17/_locales/pt_BR/messages.json
--- eas4tbsync-4.11/_locales/pt_BR/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/pt_BR/messages.json 2025-05-15 11:21:20.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Aniversário:"
- },
- "abCard.AssistantName": {
- "message": "Assistente:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Telefone Assistente:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Telefone alternativo do trabalho:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Fax de trabalho:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Telefone do carro:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Telefone principal do trabalho:"
- },
- "abCard.Email3Address": {
- "message": "Email alternativo:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Telefone alternativo residencial:"
- },
- "abCard.ManagerName": {
- "message": "Gerenciar:"
- },
- "abCard.MiddleName": {
- "message": "Nome do meio:"
- },
- "abCard.OtherAddress": {
- "message": "Endereço:"
- },
- "abCard.OtherCity": {
- "message": "Cidade:"
- },
- "abCard.OtherCountry": {
- "message": "País:"
- },
- "abCard.OtherState": {
- "message": "Estado:"
- },
- "abCard.OtherZip": {
- "message": "CEP:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Telefone de rádio:"
- },
- "abCard.Spouse": {
- "message": "Esposa:"
- },
- "abCard.header.eas": {
- "message": "Outros campos (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Números residenciais adicionais:"
- },
- "abCard.header.messaging": {
- "message": "Mensagens:"
- },
- "abCard.header.otheraddress": {
- "message": "Outro endereço (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Números adicionais:"
- },
- "abCard.header.people": {
- "message": "Pessoas:"
- },
- "abCard.header.worknumbers": {
- "message": "Números de trabalho adicionais:"
- },
- "acl.readonly": {
- "message": "Acesso ao servidor somente leitura (reverter alterações locais)"
- },
- "acl.readwrite": {
- "message": "Ler e escrever no servidor"
- },
- "add.description": {
- "message": "Selecione uma das opções de configuração do servidor disponíveis e insira os detalhes solicitados."
- },
- "add.name": {
- "message": "Nome da conta:"
- },
- "add.ok": {
- "message": "Adicionar conta"
- },
- "add.password": {
- "message": "Senha:"
- },
- "add.server": {
- "message": "Configuração do servidor:"
- },
- "add.shortdescription": {
- "message": "Informações de conta"
- },
- "add.title": {
- "message": "Adicionando uma conta do Exchange ActiveSync ao TbSync"
- },
- "add.url": {
- "message": "Endereço do servidor:"
- },
- "add.urldescription": {
- "message": "Deve ser suficiente fornecer apenas o endereço básico do servidor (ex.: mail.yourserver.com). No entanto, também é possível fornecer a URL completa (ex.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Usuário:"
- },
- "autocomplete.serverdirectory": {
- "message": "servidor de diretório global"
- },
- "autodiscover.Failed": {
- "message": "Descoberta automática para usuário <##user##> falhou. As credenciais fornecidas estavam erradas ou seu provedor do ActiveSync tem um problema temporário ou não oferece suporte à descoberta automática."
- },
- "autodiscover.NeedEmail": {
- "message": "A descoberta automática precisa de um endereço de email válido"
- },
- "autodiscover.Ok": {
- "message": "Descoberta automática concluída com êxito, agora você pode verificar as configurações opcionais e estabelecer a conexão de sincronização."
- },
- "autodiscover.Querying": {
- "message": "Procurando por configurações..."
- },
- "config.auto": {
- "message": "Configuração do servidor ActiveSync (Descoberta Automática)"
- },
- "config.custom": {
- "message": "Configuração do servidor ActiveSync"
- },
- "deletefolder.confirm": {
- "message": "Você realmente deseja limpar permanentemente a pasta '##replace.1##' da lixeira?"
- },
- "deletefolder.menuentry": {
- "message": "Remover permanentemente a pasta '##replace.1##' da lixeira"
- },
- "deletefolder.notallowed": {
- "message": "Por favor, cancele a subscrição da pasta '##replace.1##' antes de tentar limpá-lo do lixo."
- },
- "extensionDescription": {
- "message": "Adiciona suporte para sincronizar contas do Exchange ActiveSync (contatos, tarefas e calendários) para o TbSync."
- },
- "extensionName": {
- "message": "Provedor Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Configurações da conta"
- },
- "manager.tabs.outOfOffice": {
- "message": "Resposta automática"
- },
- "manager.tabs.syncsettings": {
- "message": "Opções"
- },
- "newaccount.add_auto": {
- "message": "Configurações de descoberta automática e adicionar conta"
- },
- "newaccount.add_custom": {
- "message": "Adicionar conta"
- },
- "pref.AccountName": {
- "message": "Nome da conta"
- },
- "pref.ActiveSyncVersion": {
- "message": "Versão do ActiveSync"
- },
- "pref.DeviceId": {
- "message": "ID Dispositivo ActiveSync"
- },
- "pref.ServerName": {
- "message": "Endereço do servidor"
- },
- "pref.ServerNameDescription": {
- "message": "ex. mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Mostrar pastas encontradas na lixeira"
- },
- "pref.UserName": {
- "message": "Usuário"
- },
- "pref.UserNameDescription": {
- "message": "O nome do usuário geralmente é o endereço de e-mail da sua conta."
- },
- "pref.autodetect": {
- "message": "melhor disponível"
- },
- "pref.birthday": {
- "message": "Enviar informações de aniversário"
- },
- "pref.calendaroptions": {
- "message": "Opções de calendário"
- },
- "pref.contactoptions": {
- "message": "Opções de contato"
- },
- "pref.displayoverride": {
- "message": "Substituir nome de exibição com Nome + Segundo nome"
- },
- "pref.generaloptions": {
- "message": "Opções gerais"
- },
- "pref.provision": {
- "message": "Reforçar provisionamento (requiredo pelo Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Vírgula"
- },
- "pref.seperator.description": {
- "message": "Separador para campo de endereço de múltiplas linhas."
- },
- "pref.seperator.linebreak": {
- "message": "Quebra de linha"
- },
- "pref.synclimit.1month": {
- "message": "a partir de 4 semanas atrás"
- },
- "pref.synclimit.2weeks": {
- "message": "a partir de 2 semanas atrás"
- },
- "pref.synclimit.3month": {
- "message": "a partir de 3 meses atrás"
- },
- "pref.synclimit.6month": {
- "message": "a partir de 6 meses atrás"
- },
- "pref.synclimit.all": {
- "message": "tudo"
- },
- "pref.synclimit.description": {
- "message": "Período de sincronização:"
- },
- "pref.usehttps": {
- "message": "Utilizar conexão segura (conectar via https)"
- },
- "recyclebin": {
- "message": "Lixeira"
- },
- "servertype.auto": {
- "message": "Configuração automática"
- },
- "servertype.custom": {
- "message": "Configuração personalizada"
- },
- "servertype.description.auto": {
- "message": "A configuração para muitos servidores do ActiveSync pode ser descoberta fornecendo apenas seu endereço de e-mail."
- },
- "servertype.description.custom": {
- "message": "Configure sua conta fornecendo manualmente o endereço do servidor que você deseja conectar."
- },
- "servertype.description.office365": {
- "message": "Contas conectadas ao Office 365 utilizam um processo de autenticação moderno chamado OAuth 2.0 que também suporta autenticação multi-Fator (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Clique duas vezes para desbloquear todas as configurações do servidor predefinidas."
- },
- "status.401": {
- "message": "Não foi possível autenticar, verifique o nome de usuário e senha (HTTP Erro 401)."
- },
- "status.403": {
- "message": "Conexão rejeitada pelo servidor (proibido) (HTTP Erro 403)."
- },
- "status.404": {
- "message": "Usuário não encontrado (HTTP Erro 404)."
- },
- "status.449": {
- "message": "O servidor solicita o provisionamento (HTTP Erro 449)."
- },
- "status.500": {
- "message": "Erro de servidor desconhecido (HTTP Erro 500)."
- },
- "status.503": {
- "message": "Serviço indisponível (HTTP Erro 503)."
- },
- "status.BadItemSkipped": {
- "message": "Item inválido ignorado: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Não é possível excluir uma pasta do sistema."
- },
- "status.FolderDelete.4": {
- "message": "?? Folder does not exist (status 4), resyncing ??"
- },
- "status.FolderDelete.6": {
- "message": "O comando não pôde ser concluído, ocorreu um erro no servidor."
- },
- "status.FolderDelete.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.FolderSync.9": {
- "message": "?? Invalid synchronization key (status 9), resyncing ??"
- },
- "status.InvalidServerOptions": {
- "message": "O servidor não fornece informações sobre as versões do ActiveSync com suporte. O EAS está bloqueado para este usuário ou esse cliente (TbSync)? Você pode tentar definir a versão do ActiveSync manualmente."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "O servidor EAS rejeitou a última solicitação."
- },
- "status.ServerRejectedSomeItems": {
- "message": "O servidor EAS não aceitou ##replace.1## elementos."
- },
- "status.Sync.12": {
- "message": "?? Folder hierarchy changed (status 12), resyncing ??"
- },
- "status.Sync.3": {
- "message": "?? Invalid synchronization key (status 3), resyncing ??"
- },
- "status.Sync.4": {
- "message": "?? Malformed request (status 4) ??"
- },
- "status.Sync.5": {
- "message": "?? Temporary server issues or invalid item (status 5) ??"
- },
- "status.Sync.6": {
- "message": "?? Invalid item (status 6) ??"
- },
- "status.Sync.8": {
- "message": "?? Object not found (status 8) ??"
- },
- "status.aborted": {
- "message": "Não sincronizado"
- },
- "status.disabled": {
- "message": "Desativado"
- },
- "status.empty-response": {
- "message": "O servidor enviou uma resposta vazia inesperada."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "?? Forbidden calendar item in a task folder (please resort) ??"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "?? Forbidden task item in a calendar folder (please resort) ??"
- },
- "status.global.101": {
- "message": "A solicitação contém WBXML, mas não pôde ser decodificada em XML (Erro EAS 101)."
- },
- "status.global.102": {
- "message": "A solicitação contém WBXML, mas não pôde ser decodificada em XML (Erro EAS 102)."
- },
- "status.global.103": {
- "message": "O XML fornecido na solicitação não segue os requisitos do protocolo (Erro EAS 103)."
- },
- "status.global.110": {
- "message": "O servidor relatou um erro interno e não devemos tentar novamente imediatamente. A sincronização periódica automática foi desativada por 30 minutos (Erro 110 do EAS)."
- },
- "status.global.clientdenied": {
- "message": "O servidor EAS reporta <##replace.2##> (status ##replace.1##) e não permite que o TbSync acesse sua conta."
- },
- "status.httperror": {
- "message": "Erro de comunicação (HTTP status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Resposta inválida do servidor (lixo)."
- },
- "status.malformed-xml": {
- "message": "Não foi possível analisar XML. Verifique o log de eventos para obter detalhes."
- },
- "status.modified": {
- "message": "Modificações locais"
- },
- "status.network": {
- "message": "Não foi possível conectar ao servidor (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Não foi possível conectar ao servidor."
- },
- "status.nosupportedeasversion": {
- "message": "O servidor não suporta o ActiveSync v2.5 ou v14.0 (somente ##replace.1##). TbSync não funcionará com este servidor ActiveSync."
- },
- "status.notargets": {
- "message": "Anulando a sincronização, porque os destinos de sincronização não puderam ser criados."
- },
- "status.notsupportedeasversion": {
- "message": "O servidor não suporta o ActiveSync selecionado v##replace.1## (somente ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "A conta precisa ser sincronizada, pelo menos, um item está fora de sincronia."
- },
- "status.nouserhost": {
- "message": "Nome de usuário e/ou servidor ausente. Por favor, forneça esses valores."
- },
- "status.pending": {
- "message": "Esperando para ser sincronizado"
- },
- "status.policy.2": {
- "message": "Não há política para este cliente. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
- },
- "status.policy.3": {
- "message": "Valor de PolicyType desconhecido. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
- },
- "status.policy.4": {
- "message": "Os dados da política no servidor estão corrompidos (possivelmente adulterados). Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
- },
- "status.policy.5": {
- "message": "O cliente está reconhecendo a chave de política incorreta. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
- },
- "status.provision": {
- "message": "O provisionamento falhou com o status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "A resposta do servidor não contém dados."
- },
- "status.resync-loop": {
- "message": "Ocorreu um erro do qual não conseguimos recuperar ao reativar a conta. Por favor, desative a conta e tente novamente. (Erro: loop de ressincronização)"
- },
- "status.security": {
- "message": "Não foi possível estabelecer uma conexão segura. Você está usando um certificado autoassinado ou não confiável sem importá-lo para o Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Ainda não suportado, ignorado"
- },
- "status.syncing": {
- "message": "Sincronizando"
- },
- "status.timeout": {
- "message": "Tempo limite de comunicação."
- },
- "status.wbxml-parse-error": {
- "message": "O servidor enviou uma resposta ilegível."
- },
- "status.wbxmlerror": {
- "message": "A sincronização falhou. O servidor respondeu com status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "Violação do protocolo ActiveSync: o campo obrigatório <##replace.1##> está faltando na resposta do servidor."
- },
- "syncstate.accountdone": {
- "message": "Sincronização finalizada"
- },
- "syncstate.done": {
- "message": "Preparando o próximo item para sincronização"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Aguardando as configurações do servidor atualizadas"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Pasta excluída"
- },
- "syncstate.eval.response.estimate": {
- "message": "Processando a estimativa de alterações"
- },
- "syncstate.eval.response.folders": {
- "message": "Processando a atualização da lista de pastas"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Processando reconhecimento de alterações locais"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Processando reconhecimento de exclusões locais"
- },
- "syncstate.eval.response.options": {
- "message": "Processando opções do servidor"
- },
- "syncstate.eval.response.provision": {
- "message": "Processando provisão"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Processando alterações remotas"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Revertendo alterações locais"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Enviando informações do dispositivo"
- },
- "syncstate.eval.response.synckey": {
- "message": "Processando SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Solicitando configurações do servidor atualizadas"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparando-se para excluir pasta"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Solicitando estimativa de alterações"
- },
- "syncstate.prepare.request.folders": {
- "message": "Enviando lista de pastas atualizadas"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Enviando alterações locais"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Enviando exclusões locais"
- },
- "syncstate.prepare.request.options": {
- "message": "Solicitando opções do servidor"
- },
- "syncstate.prepare.request.provision": {
- "message": "Solicitando provisão"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Solicitando alterações remotas"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Coletando alterações locais"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Enviando informações do dispositivo"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Solicitando SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparando o próximo item para sincronização"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Aguardando as configurações do servidor atualizadas"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Aguardando a pasta ser excluída"
- },
- "syncstate.send.request.estimate": {
- "message": "Aguardando a estimativa de alterações"
- },
- "syncstate.send.request.folders": {
- "message": "Aguardando a atualização da lista de pastas"
- },
- "syncstate.send.request.localchanges": {
- "message": "Aguardando confirmação de alterações locais"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Aguardando o reconhecimento de exclusões locais"
- },
- "syncstate.send.request.options": {
- "message": "Aguardando por opções do servidor"
- },
- "syncstate.send.request.provision": {
- "message": "Agurdandando provisão"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Aguardando alterações remotas"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Aguardando as versões mais recentes"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Enviando informações do dispositivo"
- },
- "syncstate.send.request.synckey": {
- "message": "Esperando SyncKey"
- },
- "syncstate.syncing": {
- "message": "Inicializar sincronização"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Aniversário:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistente:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Telefone Assistente:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Telefone alternativo do trabalho:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Fax de trabalho:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Telefone do carro:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Telefone principal do trabalho:"
+ },
+ "abCard.Email3Address": {
+ "message": "Email alternativo:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Telefone alternativo residencial:"
+ },
+ "abCard.ManagerName": {
+ "message": "Gerenciar:"
+ },
+ "abCard.MiddleName": {
+ "message": "Nome do meio:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Endereço:"
+ },
+ "abCard.OtherCity": {
+ "message": "Cidade:"
+ },
+ "abCard.OtherCountry": {
+ "message": "País:"
+ },
+ "abCard.OtherState": {
+ "message": "Estado:"
+ },
+ "abCard.OtherZip": {
+ "message": "CEP:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Telefone de rádio:"
+ },
+ "abCard.Spouse": {
+ "message": "Esposa:"
+ },
+ "abCard.header.eas": {
+ "message": "Outros campos (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Números residenciais adicionais:"
+ },
+ "abCard.header.messaging": {
+ "message": "Mensagens:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Outro endereço (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Números adicionais:"
+ },
+ "abCard.header.people": {
+ "message": "Pessoas:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Números de trabalho adicionais:"
+ },
+ "acl.readonly": {
+ "message": "Acesso ao servidor somente leitura (reverter alterações locais)"
+ },
+ "acl.readwrite": {
+ "message": "Ler e escrever no servidor"
+ },
+ "add.description": {
+ "message": "Selecione uma das opções de configuração do servidor disponíveis e insira os detalhes solicitados."
+ },
+ "add.name": {
+ "message": "Nome da conta:"
+ },
+ "add.ok": {
+ "message": "Adicionar conta"
+ },
+ "add.password": {
+ "message": "Senha:"
+ },
+ "add.server": {
+ "message": "Configuração do servidor:"
+ },
+ "add.shortdescription": {
+ "message": "Informações de conta"
+ },
+ "add.title": {
+ "message": "Adicionando uma conta do Exchange ActiveSync ao TbSync"
+ },
+ "add.url": {
+ "message": "Endereço do servidor:"
+ },
+ "add.urldescription": {
+ "message": "Deve ser suficiente fornecer apenas o endereço básico do servidor (ex.: mail.yourserver.com). No entanto, também é possível fornecer a URL completa (ex.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Usuário:"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "servidor de diretório global"
+ },
+ "autodiscover.Failed": {
+ "message": "Descoberta automática para usuário <##user##> falhou. As credenciais fornecidas estavam erradas ou seu provedor do ActiveSync tem um problema temporário ou não oferece suporte à descoberta automática."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "A descoberta automática precisa de um endereço de email válido"
+ },
+ "autodiscover.Ok": {
+ "message": "Descoberta automática concluída com êxito, agora você pode verificar as configurações opcionais e estabelecer a conexão de sincronização."
+ },
+ "autodiscover.Querying": {
+ "message": "Procurando por configurações..."
+ },
+ "config.auto": {
+ "message": "Configuração do servidor ActiveSync (Descoberta Automática)"
+ },
+ "config.custom": {
+ "message": "Configuração do servidor ActiveSync"
+ },
+ "deletefolder.confirm": {
+ "message": "Você realmente deseja limpar permanentemente a pasta '##replace.1##' da lixeira?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Remover permanentemente a pasta '##replace.1##' da lixeira"
+ },
+ "deletefolder.notallowed": {
+ "message": "Por favor, cancele a subscrição da pasta '##replace.1##' antes de tentar limpá-lo do lixo."
+ },
+ "extensionDescription": {
+ "message": "Adiciona suporte para sincronizar contas do Exchange ActiveSync (contatos, tarefas e calendários) para o TbSync."
+ },
+ "extensionName": {
+ "message": "Provedor Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Configurações da conta"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Resposta automática"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Opções"
+ },
+ "newaccount.add_auto": {
+ "message": "Configurações de descoberta automática e adicionar conta"
+ },
+ "newaccount.add_custom": {
+ "message": "Adicionar conta"
+ },
+ "pref.AccountName": {
+ "message": "Nome da conta"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Versão do ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "ID Dispositivo ActiveSync"
+ },
+ "pref.ServerName": {
+ "message": "Endereço do servidor"
+ },
+ "pref.ServerNameDescription": {
+ "message": "ex. mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Mostrar pastas encontradas na lixeira"
+ },
+ "pref.UserName": {
+ "message": "Usuário"
+ },
+ "pref.UserNameDescription": {
+ "message": "O nome do usuário geralmente é o endereço de e-mail da sua conta."
+ },
+ "pref.autodetect": {
+ "message": "melhor disponível"
+ },
+ "pref.birthday": {
+ "message": "Enviar informações de aniversário"
+ },
+ "pref.calendaroptions": {
+ "message": "Opções de calendário"
+ },
+ "pref.contactoptions": {
+ "message": "Opções de contato"
+ },
+ "pref.displayoverride": {
+ "message": "Substituir nome de exibição com Nome + Segundo nome"
+ },
+ "pref.generaloptions": {
+ "message": "Opções gerais"
+ },
+ "pref.provision": {
+ "message": "Reforçar provisionamento (requiredo pelo Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Vírgula"
+ },
+ "pref.seperator.description": {
+ "message": "Separador para campo de endereço de múltiplas linhas."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Quebra de linha"
+ },
+ "pref.synclimit.1month": {
+ "message": "a partir de 4 semanas atrás"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "a partir de 2 semanas atrás"
+ },
+ "pref.synclimit.3month": {
+ "message": "a partir de 3 meses atrás"
+ },
+ "pref.synclimit.6month": {
+ "message": "a partir de 6 meses atrás"
+ },
+ "pref.synclimit.all": {
+ "message": "tudo"
+ },
+ "pref.synclimit.description": {
+ "message": "Período de sincronização:"
+ },
+ "pref.usehttps": {
+ "message": "Utilizar conexão segura (conectar via https)"
+ },
+ "recyclebin": {
+ "message": "Lixeira"
+ },
+ "servertype.auto": {
+ "message": "Configuração automática"
+ },
+ "servertype.custom": {
+ "message": "Configuração personalizada"
+ },
+ "servertype.description.auto": {
+ "message": "A configuração para muitos servidores do ActiveSync pode ser descoberta fornecendo apenas seu endereço de e-mail."
+ },
+ "servertype.description.custom": {
+ "message": "Configure sua conta fornecendo manualmente o endereço do servidor que você deseja conectar."
+ },
+ "servertype.description.office365": {
+ "message": "Contas conectadas ao Office 365 utilizam um processo de autenticação moderno chamado OAuth 2.0 que também suporta autenticação multi-Fator (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Clique duas vezes para desbloquear todas as configurações do servidor predefinidas."
+ },
+ "status.401": {
+ "message": "Não foi possível autenticar, verifique o nome de usuário e senha (HTTP Erro 401)."
+ },
+ "status.403": {
+ "message": "Conexão rejeitada pelo servidor (proibido) (HTTP Erro 403)."
+ },
+ "status.404": {
+ "message": "Usuário não encontrado (HTTP Erro 404)."
+ },
+ "status.449": {
+ "message": "O servidor solicita o provisionamento (HTTP Erro 449)."
+ },
+ "status.500": {
+ "message": "Erro de servidor desconhecido (HTTP Erro 500)."
+ },
+ "status.503": {
+ "message": "Serviço indisponível (HTTP Erro 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Item inválido ignorado: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Não é possível excluir uma pasta do sistema."
+ },
+ "status.FolderDelete.4": {
+ "message": "?? Folder does not exist (status 4), resyncing ??"
+ },
+ "status.FolderDelete.6": {
+ "message": "O comando não pôde ser concluído, ocorreu um erro no servidor."
+ },
+ "status.FolderDelete.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.FolderSync.9": {
+ "message": "?? Invalid synchronization key (status 9), resyncing ??"
+ },
+ "status.InvalidServerOptions": {
+ "message": "O servidor não fornece informações sobre as versões do ActiveSync com suporte. O EAS está bloqueado para este usuário ou esse cliente (TbSync)? Você pode tentar definir a versão do ActiveSync manualmente."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "O servidor EAS rejeitou a última solicitação."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "O servidor EAS não aceitou ##replace.1## elementos."
+ },
+ "status.Sync.12": {
+ "message": "?? Folder hierarchy changed (status 12), resyncing ??"
+ },
+ "status.Sync.3": {
+ "message": "?? Invalid synchronization key (status 3), resyncing ??"
+ },
+ "status.Sync.4": {
+ "message": "?? Malformed request (status 4) ??"
+ },
+ "status.Sync.5": {
+ "message": "?? Temporary server issues or invalid item (status 5) ??"
+ },
+ "status.Sync.6": {
+ "message": "?? Invalid item (status 6) ??"
+ },
+ "status.Sync.8": {
+ "message": "?? Object not found (status 8) ??"
+ },
+ "status.aborted": {
+ "message": "Não sincronizado"
+ },
+ "status.disabled": {
+ "message": "Desativado"
+ },
+ "status.empty-response": {
+ "message": "O servidor enviou uma resposta vazia inesperada."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "?? Forbidden calendar item in a task folder (please resort) ??"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "?? Forbidden task item in a calendar folder (please resort) ??"
+ },
+ "status.global.101": {
+ "message": "A solicitação contém WBXML, mas não pôde ser decodificada em XML (Erro EAS 101)."
+ },
+ "status.global.102": {
+ "message": "A solicitação contém WBXML, mas não pôde ser decodificada em XML (Erro EAS 102)."
+ },
+ "status.global.103": {
+ "message": "O XML fornecido na solicitação não segue os requisitos do protocolo (Erro EAS 103)."
+ },
+ "status.global.110": {
+ "message": "O servidor relatou um erro interno e não devemos tentar novamente imediatamente. A sincronização periódica automática foi desativada por 30 minutos (Erro 110 do EAS)."
+ },
+ "status.global.clientdenied": {
+ "message": "O servidor EAS reporta <##replace.2##> (status ##replace.1##) e não permite que o TbSync acesse sua conta."
+ },
+ "status.httperror": {
+ "message": "Erro de comunicação (HTTP status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Resposta inválida do servidor (lixo)."
+ },
+ "status.malformed-xml": {
+ "message": "Não foi possível analisar XML. Verifique o log de eventos para obter detalhes."
+ },
+ "status.modified": {
+ "message": "Modificações locais"
+ },
+ "status.network": {
+ "message": "Não foi possível conectar ao servidor (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Não foi possível conectar ao servidor."
+ },
+ "status.nosupportedeasversion": {
+ "message": "O servidor não suporta o ActiveSync v2.5 ou v14.0 (somente ##replace.1##). TbSync não funcionará com este servidor ActiveSync."
+ },
+ "status.notargets": {
+ "message": "Anulando a sincronização, porque os destinos de sincronização não puderam ser criados."
+ },
+ "status.notsupportedeasversion": {
+ "message": "O servidor não suporta o ActiveSync selecionado v##replace.1## (somente ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "A conta precisa ser sincronizada, pelo menos, um item está fora de sincronia."
+ },
+ "status.nouserhost": {
+ "message": "Nome de usuário e/ou servidor ausente. Por favor, forneça esses valores."
+ },
+ "status.pending": {
+ "message": "Esperando para ser sincronizado"
+ },
+ "status.policy.2": {
+ "message": "Não há política para este cliente. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
+ },
+ "status.policy.3": {
+ "message": "Valor de PolicyType desconhecido. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
+ },
+ "status.policy.4": {
+ "message": "Os dados da política no servidor estão corrompidos (possivelmente adulterados). Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
+ },
+ "status.policy.5": {
+ "message": "O cliente está reconhecendo a chave de política incorreta. Entre em contato com o administrador do servidor ou desabilite o provisionamento para essa conta."
+ },
+ "status.provision": {
+ "message": "O provisionamento falhou com o status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "A resposta do servidor não contém dados."
+ },
+ "status.resync-loop": {
+ "message": "Ocorreu um erro do qual não conseguimos recuperar ao reativar a conta. Por favor, desative a conta e tente novamente. (Erro: loop de ressincronização)"
+ },
+ "status.security": {
+ "message": "Não foi possível estabelecer uma conexão segura. Você está usando um certificado autoassinado ou não confiável sem importá-lo para o Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Ainda não suportado, ignorado"
+ },
+ "status.syncing": {
+ "message": "Sincronizando"
+ },
+ "status.timeout": {
+ "message": "Tempo limite de comunicação."
+ },
+ "status.wbxml-parse-error": {
+ "message": "O servidor enviou uma resposta ilegível."
+ },
+ "status.wbxmlerror": {
+ "message": "A sincronização falhou. O servidor respondeu com status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "Violação do protocolo ActiveSync: o campo obrigatório <##replace.1##> está faltando na resposta do servidor."
+ },
+ "syncstate.accountdone": {
+ "message": "Sincronização finalizada"
+ },
+ "syncstate.done": {
+ "message": "Preparando o próximo item para sincronização"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Aguardando as configurações do servidor atualizadas"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Pasta excluída"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Processando a estimativa de alterações"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Processando a atualização da lista de pastas"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Processando reconhecimento de alterações locais"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Processando reconhecimento de exclusões locais"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Processando opções do servidor"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Processando provisão"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Processando alterações remotas"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Revertendo alterações locais"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Enviando informações do dispositivo"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Processando SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Solicitando configurações do servidor atualizadas"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparando-se para excluir pasta"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Solicitando estimativa de alterações"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Enviando lista de pastas atualizadas"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Enviando alterações locais"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Enviando exclusões locais"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Solicitando opções do servidor"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Solicitando provisão"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Solicitando alterações remotas"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Coletando alterações locais"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Enviando informações do dispositivo"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Solicitando SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparando o próximo item para sincronização"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Aguardando as configurações do servidor atualizadas"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Aguardando a pasta ser excluída"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Aguardando a estimativa de alterações"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Aguardando a atualização da lista de pastas"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Aguardando confirmação de alterações locais"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Aguardando o reconhecimento de exclusões locais"
+ },
+ "syncstate.send.request.options": {
+ "message": "Aguardando por opções do servidor"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Agurdandando provisão"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Aguardando alterações remotas"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Aguardando as versões mais recentes"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Enviando informações do dispositivo"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Esperando SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Inicializar sincronização"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/ro/messages.json eas4tbsync-4.17/_locales/ro/messages.json
--- eas4tbsync-4.11/_locales/ro/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/ro/messages.json 2025-05-15 11:21:20.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "Anniversary:"
- },
- "abCard.AssistantName": {
- "message": "Assistant:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Assistant Phone:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Work Alternative Phone:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Work Fax:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Car Phone:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Work Main Phone:"
- },
- "abCard.Email3Address": {
- "message": "Alternative Email:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Home Alternative Phone:"
- },
- "abCard.ManagerName": {
- "message": "Manager:"
- },
- "abCard.MiddleName": {
- "message": "Middle name:"
- },
- "abCard.OtherAddress": {
- "message": "Address:"
- },
- "abCard.OtherCity": {
- "message": "City:"
- },
- "abCard.OtherCountry": {
- "message": "Country:"
- },
- "abCard.OtherState": {
- "message": "State:"
- },
- "abCard.OtherZip": {
- "message": "ZIP Code:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Radio Phone:"
- },
- "abCard.Spouse": {
- "message": "Spouse:"
- },
- "abCard.header.eas": {
- "message": "Other Fields (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Additional home numbers:"
- },
- "abCard.header.messaging": {
- "message": "Messaging:"
- },
- "abCard.header.otheraddress": {
- "message": "Other Address (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Additional numbers:"
- },
- "abCard.header.people": {
- "message": "People:"
- },
- "abCard.header.worknumbers": {
- "message": "Additional work numbers:"
- },
- "acl.readonly": {
- "message": "Read-only server access (revert local changes)"
- },
- "acl.readwrite": {
- "message": "Read from and write to server"
- },
- "add.description": {
- "message": "Please select one of the available server configuration options and enter the requested details. "
- },
- "add.name": {
- "message": "Account name:"
- },
- "add.ok": {
- "message": "Add account"
- },
- "add.password": {
- "message": "Password:"
- },
- "add.server": {
- "message": "Server configuration:"
- },
- "add.shortdescription": {
- "message": "Account information"
- },
- "add.title": {
- "message": "Adding an Exchange ActiveSync account to TbSync"
- },
- "add.url": {
- "message": "Server address:"
- },
- "add.urldescription": {
- "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "User name (email address):"
- },
- "autocomplete.serverdirectory": {
- "message": "global server directory"
- },
- "autodiscover.Failed": {
- "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
- },
- "autodiscover.NeedEmail": {
- "message": "Autodiscover needs a valid email address as user name."
- },
- "autodiscover.Ok": {
- "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
- },
- "autodiscover.Querying": {
- "message": "Searching for settings…"
- },
- "config.auto": {
- "message": "ActiveSync server configuration (Autodiscover)"
- },
- "config.custom": {
- "message": "ActiveSync server configuration"
- },
- "deletefolder.confirm": {
- "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
- },
- "deletefolder.menuentry": {
- "message": "Permanently purge folder “##replace.1##” from trash"
- },
- "deletefolder.notallowed": {
- "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
- },
- "extensionDescription": {
- "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
- },
- "extensionName": {
- "message": "Provider for Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Account settings"
- },
- "manager.tabs.outOfOffice": {
- "message": "Auto responder"
- },
- "manager.tabs.syncsettings": {
- "message": "Options"
- },
- "newaccount.add_auto": {
- "message": "Autodiscover settings and add account"
- },
- "newaccount.add_custom": {
- "message": "Add account"
- },
- "pref.AccountName": {
- "message": "Description"
- },
- "pref.ActiveSyncVersion": {
- "message": "ActiveSync version"
- },
- "pref.DeviceId": {
- "message": "ActiveSync device ID"
- },
- "pref.ServerName": {
- "message": "Server address"
- },
- "pref.ServerNameDescription": {
- "message": "e.g. mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Show folders found in trash"
- },
- "pref.UserName": {
- "message": "User name"
- },
- "pref.UserNameDescription": {
- "message": "User name is usually the email address of your account."
- },
- "pref.autodetect": {
- "message": "best available"
- },
- "pref.birthday": {
- "message": "Send birthday information"
- },
- "pref.calendaroptions": {
- "message": "Calendar options"
- },
- "pref.contactoptions": {
- "message": "Contact options"
- },
- "pref.displayoverride": {
- "message": "Override Display Name with “First Name” + “Second Name”"
- },
- "pref.generaloptions": {
- "message": "General options"
- },
- "pref.provision": {
- "message": "Enforce provisioning (required by Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Comma"
- },
- "pref.seperator.description": {
- "message": "Separator for multiline address field."
- },
- "pref.seperator.linebreak": {
- "message": "Line break"
- },
- "pref.synclimit.1month": {
- "message": "from 4 weeks ago"
- },
- "pref.synclimit.2weeks": {
- "message": "from 2 weeks ago"
- },
- "pref.synclimit.3month": {
- "message": "from 3 months ago"
- },
- "pref.synclimit.6month": {
- "message": "from 6 months ago"
- },
- "pref.synclimit.all": {
- "message": "everything"
- },
- "pref.synclimit.description": {
- "message": "Synchronization period: "
- },
- "pref.usehttps": {
- "message": "Use secure connection (connect via https)"
- },
- "recyclebin": {
- "message": "Trash"
- },
- "servertype.auto": {
- "message": "Automatic configuration"
- },
- "servertype.custom": {
- "message": "Custom configuration"
- },
- "servertype.description.auto": {
- "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
- },
- "servertype.description.custom": {
- "message": "Setup your account by manually providing the address of the server you want to connect."
- },
- "servertype.description.office365": {
- "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Double click to unlock all predefined server settings."
- },
- "status.401": {
- "message": "Could not authenticate, check username and password (HTTP Error 401)."
- },
- "status.403": {
- "message": "Server rejected connection (forbidden) (HTTP Error 403)."
- },
- "status.404": {
- "message": "User not found (HTTP Error 404)."
- },
- "status.449": {
- "message": "Server requests provisioning (HTTP Error 449)."
- },
- "status.500": {
- "message": "Unknown Server Error (HTTP Error 500)."
- },
- "status.503": {
- "message": "Service unavailable (HTTP Error 503)."
- },
- "status.BadItemSkipped": {
- "message": "Bad Item Skipped: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Cannot delete a system folder (status 3)"
- },
- "status.FolderDelete.4": {
- "message": "Folder does not exist (status 4), resyncing"
- },
- "status.FolderDelete.6": {
- "message": "Command could not be completed, an error occurred on the server (status 6)"
- },
- "status.FolderDelete.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.FolderSync.9": {
- "message": "Invalid synchronization key (status 9), resyncing"
- },
- "status.InvalidServerOptions": {
- "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
- },
- "status.OK": {
- "message": "OK"
- },
- "status.ServerRejectedRequest": {
- "message": "The EAS Server rejected the last request."
- },
- "status.ServerRejectedSomeItems": {
- "message": "The EAS server did not accept ##replace.1## elements."
- },
- "status.Sync.12": {
- "message": "Folder hierarchy changed (status 12), resyncing"
- },
- "status.Sync.3": {
- "message": "Invalid synchronization key (status 3), resyncing"
- },
- "status.Sync.4": {
- "message": "Malformed request (status 4)"
- },
- "status.Sync.5": {
- "message": "Temporary server issues or invalid item (status 5)"
- },
- "status.Sync.6": {
- "message": "Invalid item (status 6)"
- },
- "status.Sync.8": {
- "message": "Object not found (status 8)"
- },
- "status.aborted": {
- "message": "Not synchronized"
- },
- "status.disabled": {
- "message": "Disabled"
- },
- "status.empty-response": {
- "message": "Server sends unexpected empty response."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Forbidden calendar item in a task folder (please resort)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Forbidden task item in a calendar folder (please resort)"
- },
- "status.global.101": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
- },
- "status.global.102": {
- "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
- },
- "status.global.103": {
- "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
- },
- "status.global.110": {
- "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
- },
- "status.global.clientdenied": {
- "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
- },
- "status.httperror": {
- "message": "Communication error (HTTP status ##replace.1##)."
- },
- "status.invalid": {
- "message": "Invalid server response (junk)."
- },
- "status.malformed-xml": {
- "message": "Could not parse XML. Check event log for details."
- },
- "status.modified": {
- "message": "Local modifications"
- },
- "status.network": {
- "message": "Could not connect to server (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Could not connect to server."
- },
- "status.nosupportedeasversion": {
- "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
- },
- "status.notargets": {
- "message": "Aborting Sync, because sync targets could not be created."
- },
- "status.notsupportedeasversion": {
- "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Account needs to be synchronized, at least one item is out of sync."
- },
- "status.nouserhost": {
- "message": "Missing username and/or server. Please provide those values."
- },
- "status.pending": {
- "message": "Waiting to be synchronized"
- },
- "status.policy.2": {
- "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.3": {
- "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.4": {
- "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
- },
- "status.policy.5": {
- "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
- },
- "status.provision": {
- "message": "Provisioning failed with status <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Response from the server contains no data."
- },
- "status.resync-loop": {
- "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
- },
- "status.security": {
- "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Not yet supported, skipped"
- },
- "status.syncing": {
- "message": "Synchronizing"
- },
- "status.timeout": {
- "message": "Communication timeout."
- },
- "status.wbxml-parse-error": {
- "message": "Server sends unreadable response."
- },
- "status.wbxmlerror": {
- "message": "Sync failed. Server responded with status <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
- },
- "syncstate.accountdone": {
- "message": "Finished account"
- },
- "syncstate.done": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Processing updated server settings"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Folder deleted"
- },
- "syncstate.eval.response.estimate": {
- "message": "Processing change estimate"
- },
- "syncstate.eval.response.folders": {
- "message": "Processing folder list update"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Processing acknowledgment of local changes"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Processing acknowledgment of local deletes"
- },
- "syncstate.eval.response.options": {
- "message": "Processing server options"
- },
- "syncstate.eval.response.provision": {
- "message": "Processing provision"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Processing remote changes"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Reverting local changes"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.eval.response.synckey": {
- "message": "Processing SyncKey"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Requesting updated server settings"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Preparing to delete folder"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Requesting change estimate"
- },
- "syncstate.prepare.request.folders": {
- "message": "Sending folder list update"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Sending local changes"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Sending local deletes"
- },
- "syncstate.prepare.request.options": {
- "message": "Requesting server options"
- },
- "syncstate.prepare.request.provision": {
- "message": "Requesting provision"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Requesting remote changes"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Collecting local changes"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Requesting SyncKey"
- },
- "syncstate.preparing": {
- "message": "Preparing next item for synchronization"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Waiting for updated server settings"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Waiting for folder to be deleted"
- },
- "syncstate.send.request.estimate": {
- "message": "Waiting for change estimate"
- },
- "syncstate.send.request.folders": {
- "message": "Waiting for folder list update"
- },
- "syncstate.send.request.localchanges": {
- "message": "Waiting for acknowledgment of local changes"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Waiting for acknowledgment of local deletes"
- },
- "syncstate.send.request.options": {
- "message": "Waiting for server options"
- },
- "syncstate.send.request.provision": {
- "message": "Waiting for provision"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Waiting for remote changes"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Waiting for most recent versions"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Sending device information"
- },
- "syncstate.send.request.synckey": {
- "message": "Waiting for SyncKey"
- },
- "syncstate.syncing": {
- "message": "Initialize synchronization"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "Anniversary:"
+ },
+ "abCard.AssistantName": {
+ "message": "Assistant:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Assistant Phone:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Work Alternative Phone:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Work Fax:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Car Phone:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Work Main Phone:"
+ },
+ "abCard.Email3Address": {
+ "message": "Alternative Email:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Home Alternative Phone:"
+ },
+ "abCard.ManagerName": {
+ "message": "Manager:"
+ },
+ "abCard.MiddleName": {
+ "message": "Middle name:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Address:"
+ },
+ "abCard.OtherCity": {
+ "message": "City:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Country:"
+ },
+ "abCard.OtherState": {
+ "message": "State:"
+ },
+ "abCard.OtherZip": {
+ "message": "ZIP Code:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Radio Phone:"
+ },
+ "abCard.Spouse": {
+ "message": "Spouse:"
+ },
+ "abCard.header.eas": {
+ "message": "Other Fields (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Additional home numbers:"
+ },
+ "abCard.header.messaging": {
+ "message": "Messaging:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Other Address (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Additional numbers:"
+ },
+ "abCard.header.people": {
+ "message": "People:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Additional work numbers:"
+ },
+ "acl.readonly": {
+ "message": "Read-only server access (revert local changes)"
+ },
+ "acl.readwrite": {
+ "message": "Read from and write to server"
+ },
+ "add.description": {
+ "message": "Please select one of the available server configuration options and enter the requested details. "
+ },
+ "add.name": {
+ "message": "Account name:"
+ },
+ "add.ok": {
+ "message": "Add account"
+ },
+ "add.password": {
+ "message": "Password:"
+ },
+ "add.server": {
+ "message": "Server configuration:"
+ },
+ "add.shortdescription": {
+ "message": "Account information"
+ },
+ "add.title": {
+ "message": "Adding an Exchange ActiveSync account to TbSync"
+ },
+ "add.url": {
+ "message": "Server address:"
+ },
+ "add.urldescription": {
+ "message": "It should be sufficient to provide just the basic server address (e.g.: mail.yourserver.com). However, it is also possible to provide the full URL (e.g.: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "User name (email address):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "global server directory"
+ },
+ "autodiscover.Failed": {
+ "message": "Autodiscover for user <##user##> failed. Either the provided credentials were wrong or your ActiveSync provider has a temporary issue, or does not support Autodiscover."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Autodiscover needs a valid email address as user name."
+ },
+ "autodiscover.Ok": {
+ "message": "Autodiscover completed successfully, you can now check the optional settings and establish the synchronization connection."
+ },
+ "autodiscover.Querying": {
+ "message": "Searching for settings…"
+ },
+ "config.auto": {
+ "message": "ActiveSync server configuration (Autodiscover)"
+ },
+ "config.custom": {
+ "message": "ActiveSync server configuration"
+ },
+ "deletefolder.confirm": {
+ "message": "Do you really want to PERMANENTLY PURGE folder “##replace.1##” from trash?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Permanently purge folder “##replace.1##” from trash"
+ },
+ "deletefolder.notallowed": {
+ "message": "Please unsubscribe folder “##replace.1##” before trying to purge it from trash."
+ },
+ "extensionDescription": {
+ "message": "Add sync support for Exchange ActiveSync accounts to TbSync (contacts, tasks and calendars)."
+ },
+ "extensionName": {
+ "message": "Provider for Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Account settings"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Auto responder"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Options"
+ },
+ "newaccount.add_auto": {
+ "message": "Autodiscover settings and add account"
+ },
+ "newaccount.add_custom": {
+ "message": "Add account"
+ },
+ "pref.AccountName": {
+ "message": "Description"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "ActiveSync version"
+ },
+ "pref.DeviceId": {
+ "message": "ActiveSync device ID"
+ },
+ "pref.ServerName": {
+ "message": "Server address"
+ },
+ "pref.ServerNameDescription": {
+ "message": "e.g. mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Show folders found in trash"
+ },
+ "pref.UserName": {
+ "message": "User name"
+ },
+ "pref.UserNameDescription": {
+ "message": "User name is usually the email address of your account."
+ },
+ "pref.autodetect": {
+ "message": "best available"
+ },
+ "pref.birthday": {
+ "message": "Send birthday information"
+ },
+ "pref.calendaroptions": {
+ "message": "Calendar options"
+ },
+ "pref.contactoptions": {
+ "message": "Contact options"
+ },
+ "pref.displayoverride": {
+ "message": "Override Display Name with “First Name” + “Second Name”"
+ },
+ "pref.generaloptions": {
+ "message": "General options"
+ },
+ "pref.provision": {
+ "message": "Enforce provisioning (required by Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Comma"
+ },
+ "pref.seperator.description": {
+ "message": "Separator for multiline address field."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Line break"
+ },
+ "pref.synclimit.1month": {
+ "message": "from 4 weeks ago"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "from 2 weeks ago"
+ },
+ "pref.synclimit.3month": {
+ "message": "from 3 months ago"
+ },
+ "pref.synclimit.6month": {
+ "message": "from 6 months ago"
+ },
+ "pref.synclimit.all": {
+ "message": "everything"
+ },
+ "pref.synclimit.description": {
+ "message": "Synchronization period: "
+ },
+ "pref.usehttps": {
+ "message": "Use secure connection (connect via https)"
+ },
+ "recyclebin": {
+ "message": "Trash"
+ },
+ "servertype.auto": {
+ "message": "Automatic configuration"
+ },
+ "servertype.custom": {
+ "message": "Custom configuration"
+ },
+ "servertype.description.auto": {
+ "message": "The configuration for many ActiveSync servers can be discovered by providing just your email address."
+ },
+ "servertype.description.custom": {
+ "message": "Setup your account by manually providing the address of the server you want to connect."
+ },
+ "servertype.description.office365": {
+ "message": "Accounts connected to Office 365 use a modern authentication process called OAuth 2.0 which also supports Multi-Factor-Authentication (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Double click to unlock all predefined server settings."
+ },
+ "status.401": {
+ "message": "Could not authenticate, check username and password (HTTP Error 401)."
+ },
+ "status.403": {
+ "message": "Server rejected connection (forbidden) (HTTP Error 403)."
+ },
+ "status.404": {
+ "message": "User not found (HTTP Error 404)."
+ },
+ "status.449": {
+ "message": "Server requests provisioning (HTTP Error 449)."
+ },
+ "status.500": {
+ "message": "Unknown Server Error (HTTP Error 500)."
+ },
+ "status.503": {
+ "message": "Service unavailable (HTTP Error 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Bad Item Skipped: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Cannot delete a system folder (status 3)"
+ },
+ "status.FolderDelete.4": {
+ "message": "Folder does not exist (status 4), resyncing"
+ },
+ "status.FolderDelete.6": {
+ "message": "Command could not be completed, an error occurred on the server (status 6)"
+ },
+ "status.FolderDelete.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.FolderSync.9": {
+ "message": "Invalid synchronization key (status 9), resyncing"
+ },
+ "status.InvalidServerOptions": {
+ "message": "The server does not provide information about the supported ActiveSync versions. Is EAS blocked for this user or this client (TbSync)? You could try to set the ActiveSync version manually."
+ },
+ "status.OK": {
+ "message": "OK"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "The EAS Server rejected the last request."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "The EAS server did not accept ##replace.1## elements."
+ },
+ "status.Sync.12": {
+ "message": "Folder hierarchy changed (status 12), resyncing"
+ },
+ "status.Sync.3": {
+ "message": "Invalid synchronization key (status 3), resyncing"
+ },
+ "status.Sync.4": {
+ "message": "Malformed request (status 4)"
+ },
+ "status.Sync.5": {
+ "message": "Temporary server issues or invalid item (status 5)"
+ },
+ "status.Sync.6": {
+ "message": "Invalid item (status 6)"
+ },
+ "status.Sync.8": {
+ "message": "Object not found (status 8)"
+ },
+ "status.aborted": {
+ "message": "Not synchronized"
+ },
+ "status.disabled": {
+ "message": "Disabled"
+ },
+ "status.empty-response": {
+ "message": "Server sends unexpected empty response."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Forbidden calendar item in a task folder (please resort)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Forbidden task item in a calendar folder (please resort)"
+ },
+ "status.global.101": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 101)."
+ },
+ "status.global.102": {
+ "message": "The request contains WBXML but it could not be decoded into XML (EAS Error 102)."
+ },
+ "status.global.103": {
+ "message": "The XML provided in the request does not follow the protocol requirements (EAS Error 103)."
+ },
+ "status.global.110": {
+ "message": "The server reported an internal error and we should not retry immediately. Automatic periodic sync has been disabled for 30 minutes (EAS Error 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "The EAS server reports <##replace.2##> (status ##replace.1##) and does not allow TbSync to access your account."
+ },
+ "status.httperror": {
+ "message": "Communication error (HTTP status ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Invalid server response (junk)."
+ },
+ "status.malformed-xml": {
+ "message": "Could not parse XML. Check event log for details."
+ },
+ "status.modified": {
+ "message": "Local modifications"
+ },
+ "status.network": {
+ "message": "Could not connect to server (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Could not connect to server."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Server does not support ActiveSync v2.5 or v14.0 (only ##replace.1##). TbSync will not work with this ActiveSync server."
+ },
+ "status.notargets": {
+ "message": "Aborting Sync, because sync targets could not be created."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Server does not support selected ActiveSync v##replace.1## (only ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Account needs to be synchronized, at least one item is out of sync."
+ },
+ "status.nouserhost": {
+ "message": "Missing username and/or server. Please provide those values."
+ },
+ "status.pending": {
+ "message": "Waiting to be synchronized"
+ },
+ "status.policy.2": {
+ "message": "There is no policy for this client. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.3": {
+ "message": "Unknown PolicyType value. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.4": {
+ "message": "The policy data on the server is corrupted (possibly tampered with). Contact your server administrator or disable provisioning for this account."
+ },
+ "status.policy.5": {
+ "message": "The client is acknowledging the wrong policy key. Contact your server administrator or disable provisioning for this account."
+ },
+ "status.provision": {
+ "message": "Provisioning failed with status <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Response from the server contains no data."
+ },
+ "status.resync-loop": {
+ "message": "There was an error from which we could not recover by resyncing the account. Please disable the account and try again. (Error: resync loop)"
+ },
+ "status.security": {
+ "message": "Could not establish a secure connection. Are you using a self-signed or otherwise untrusted certificate without importing it into Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Not yet supported, skipped"
+ },
+ "status.syncing": {
+ "message": "Synchronizing"
+ },
+ "status.timeout": {
+ "message": "Communication timeout."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Server sends unreadable response."
+ },
+ "status.wbxmlerror": {
+ "message": "Sync failed. Server responded with status <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync protocol violation: Mandatory field <##replace.1##> is missing from server response."
+ },
+ "syncstate.accountdone": {
+ "message": "Finished account"
+ },
+ "syncstate.done": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Processing updated server settings"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Folder deleted"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Processing change estimate"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Processing folder list update"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Processing acknowledgment of local changes"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Processing acknowledgment of local deletes"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Processing server options"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Processing provision"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Processing remote changes"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Reverting local changes"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Processing SyncKey"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Requesting updated server settings"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Preparing to delete folder"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Requesting change estimate"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Sending folder list update"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Sending local changes"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Sending local deletes"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Requesting server options"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Requesting provision"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Requesting remote changes"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Collecting local changes"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Requesting SyncKey"
+ },
+ "syncstate.preparing": {
+ "message": "Preparing next item for synchronization"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Waiting for updated server settings"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Waiting for folder to be deleted"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Waiting for change estimate"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Waiting for folder list update"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Waiting for acknowledgment of local changes"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Waiting for acknowledgment of local deletes"
+ },
+ "syncstate.send.request.options": {
+ "message": "Waiting for server options"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Waiting for provision"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Waiting for remote changes"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Waiting for most recent versions"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Sending device information"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Waiting for SyncKey"
+ },
+ "syncstate.syncing": {
+ "message": "Initialize synchronization"
+ }
+}
diff -Nru eas4tbsync-4.11/_locales/ru/messages.json eas4tbsync-4.17/_locales/ru/messages.json
--- eas4tbsync-4.11/_locales/ru/messages.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/_locales/ru/messages.json 2025-05-15 11:21:20.000000000 +0000
@@ -1,566 +1,566 @@
-{
- "abCard.Anniversary": {
- "message": "День рождения:"
- },
- "abCard.AssistantName": {
- "message": "Помощник:"
- },
- "abCard.AssistantPhoneNumber": {
- "message": "Телефон помощника:"
- },
- "abCard.Business2PhoneNumber": {
- "message": "Рабочий телефон 2:"
- },
- "abCard.BusinessFaxNumber": {
- "message": "Рабочий факс:"
- },
- "abCard.CarPhoneNumber": {
- "message": "Автомобильный телефон:"
- },
- "abCard.CompanyMainPhone": {
- "message": "Основной рабочий телефон:"
- },
- "abCard.Email3Address": {
- "message": "Запасной Email:"
- },
- "abCard.Home2PhoneNumber": {
- "message": "Домашний телефон 2:"
- },
- "abCard.ManagerName": {
- "message": "Руководитель:"
- },
- "abCard.MiddleName": {
- "message": "Отчество:"
- },
- "abCard.OtherAddress": {
- "message": "Адрес:"
- },
- "abCard.OtherCity": {
- "message": "Город:"
- },
- "abCard.OtherCountry": {
- "message": "Страна:"
- },
- "abCard.OtherState": {
- "message": "Область:"
- },
- "abCard.OtherZip": {
- "message": "Почтовый индекс:"
- },
- "abCard.RadioPhoneNumber": {
- "message": "Радиотелефон:"
- },
- "abCard.Spouse": {
- "message": "Супруг:"
- },
- "abCard.header.eas": {
- "message": "Другие поля (EAS)"
- },
- "abCard.header.homenumbers": {
- "message": "Дополнительные домашние номера:"
- },
- "abCard.header.messaging": {
- "message": "Мессенджер:"
- },
- "abCard.header.otheraddress": {
- "message": "Другой адрес (EAS)"
- },
- "abCard.header.othernumbers": {
- "message": "Дополнительные номера:"
- },
- "abCard.header.people": {
- "message": "Люди:"
- },
- "abCard.header.worknumbers": {
- "message": "Дополнительные рабочие номера:"
- },
- "acl.readonly": {
- "message": "Доступ к серверу только для чтения (отменить локальные изменения)"
- },
- "acl.readwrite": {
- "message": "Читать и писать на сервер"
- },
- "add.description": {
- "message": "Пожалуйста, выберите один из доступных параметров конфигурации сервера и введите требуемую информацию. "
- },
- "add.name": {
- "message": "Имя аккаунта:"
- },
- "add.ok": {
- "message": "Добавить аккаунт"
- },
- "add.password": {
- "message": "Пароль:"
- },
- "add.server": {
- "message": "Конфигурация сервера:"
- },
- "add.shortdescription": {
- "message": "Информация об учетной записи"
- },
- "add.title": {
- "message": "Добавить Exchange ActiveSync аккаунт для TbSync"
- },
- "add.url": {
- "message": "Адрес сервера:"
- },
- "add.urldescription": {
- "message": "Достаточно указать только базовый адрес сервера (например: mail.yourserver.com). Однако также можно указать полный URL-адрес (например: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
- },
- "add.user": {
- "message": "Имя пользователя (email адрес):"
- },
- "autocomplete.serverdirectory": {
- "message": "глобальный каталог сервера"
- },
- "autodiscover.Failed": {
- "message": "Автообнаружение для пользователя <##user##> не удалось. Либо предоставленные учетные данные были неправильными, либо у вашего провайдера ActiveSync была временная проблема, или не поддерживается автообнаружение."
- },
- "autodiscover.NeedEmail": {
- "message": "Автообнаружению нужен действительный адрес электронной почты в качестве имени пользователя."
- },
- "autodiscover.Ok": {
- "message": "Автообнаружение успешно завершено, теперь вы можете проверить дополнительные настройки и установить соединение синхронизации."
- },
- "autodiscover.Querying": {
- "message": "Поиск настроек…"
- },
- "config.auto": {
- "message": "ActiveSync конфигурация сервера (Автообнаружение)"
- },
- "config.custom": {
- "message": "ActiveSync конфигурация сервера"
- },
- "deletefolder.confirm": {
- "message": "Вы действительно хотите ПЕРМАНЕНТНО ВЫЧИСТИТЬ папку “##replace.1##” из корзины?"
- },
- "deletefolder.menuentry": {
- "message": "Перманентно вычистить папку “##replace.1##” из корзины"
- },
- "deletefolder.notallowed": {
- "message": "Откажитесь от подписки папки “##replace.1##” прежде чем пытаться очистить ее от мусора."
- },
- "extensionDescription": {
- "message": "Добавляет в TbSync поддержку синхронизации для учетных записей Exchange через базирующийся на http/https протокол ActiveSync (контакты, задачи и календари)."
- },
- "extensionName": {
- "message": "Provider for Exchange ActiveSync"
- },
- "helplink.BadItemSkipped": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
- },
- "helplink.global.clientdenied": {
- "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
- },
- "helplink.security": {
- "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
- },
- "manager.tabs.accountsettings": {
- "message": "Настройки аккаунта"
- },
- "manager.tabs.outOfOffice": {
- "message": "Автоответчик"
- },
- "manager.tabs.syncsettings": {
- "message": "Настройки синхронизации"
- },
- "newaccount.add_auto": {
- "message": "Настройки автообнаружения и добавление аккаунта"
- },
- "newaccount.add_custom": {
- "message": "Добавить аккаунт"
- },
- "pref.AccountName": {
- "message": "Имя аккаунта"
- },
- "pref.ActiveSyncVersion": {
- "message": "Версия ActiveSync"
- },
- "pref.DeviceId": {
- "message": "Идентификатор устройства"
- },
- "pref.ServerName": {
- "message": "Адрес сервера"
- },
- "pref.ServerNameDescription": {
- "message": "например: mail.yourserver.com"
- },
- "pref.ShowTrashedFolders": {
- "message": "Показывать папки, найденные в корзине"
- },
- "pref.UserName": {
- "message": "Имя пользователя"
- },
- "pref.UserNameDescription": {
- "message": "Имя пользователя обычно является адресом электронной почты вашей учетной записи."
- },
- "pref.autodetect": {
- "message": "лучшее из доступных"
- },
- "pref.birthday": {
- "message": "Отправить информацию о днях рождения"
- },
- "pref.calendaroptions": {
- "message": "Параметры календаря"
- },
- "pref.contactoptions": {
- "message": "Параметры контакта"
- },
- "pref.displayoverride": {
- "message": "Переопределить отображаемое имя с помощью “Имя” + “Фамилия”"
- },
- "pref.generaloptions": {
- "message": "Общие параметры"
- },
- "pref.provision": {
- "message": "Заставить поддерживать (требуется для Kerio)"
- },
- "pref.seperator.comma": {
- "message": "Запятая"
- },
- "pref.seperator.description": {
- "message": "Сепаратор для многострочного поля адреса."
- },
- "pref.seperator.linebreak": {
- "message": "Разрыв строки"
- },
- "pref.synclimit.1month": {
- "message": "от 4 недель назад"
- },
- "pref.synclimit.2weeks": {
- "message": "от 2 недель назад"
- },
- "pref.synclimit.3month": {
- "message": "от 3 месяцев назад"
- },
- "pref.synclimit.6month": {
- "message": "от 6 месяцев назад"
- },
- "pref.synclimit.all": {
- "message": "все"
- },
- "pref.synclimit.description": {
- "message": "Период синхронизации:"
- },
- "pref.usehttps": {
- "message": "Использовать безопасное соединение (соединение через https)"
- },
- "recyclebin": {
- "message": "Корзина"
- },
- "servertype.auto": {
- "message": "Автоматическая настройка"
- },
- "servertype.custom": {
- "message": "Ручная настройка"
- },
- "servertype.description.auto": {
- "message": "Для определения конфигурации множества серверов ActiveSync достаточно указать только адрес Вашей электронной почты."
- },
- "servertype.description.custom": {
- "message": "Настройте Вашу учетную запись, вручную указав адрес сервера, к которому Вы хотите подключиться."
- },
- "servertype.description.office365": {
- "message": "Учетные записи, подключенные к Office 365, используют современный процесс аутентификации под названием OAuth 2.0, который также поддерживает многофакторную аутентификацию (MFA)."
- },
- "servertype.office365": {
- "message": "Microsoft Office 365"
- },
- "servertype.unlock": {
- "message": "Дважды щелкните, чтобы разблокировать все предопределенные настройки сервера."
- },
- "status.401": {
- "message": "Не удалось аутентифицировать, проверить имя пользователя и пароль. (HTTP Ошибка 401)."
- },
- "status.403": {
- "message": "Сервер отклонил соединение (запрещено) (HTTP Ошибка 403)."
- },
- "status.404": {
- "message": "Пользователь не найден (HTTP Ошибка 404)."
- },
- "status.449": {
- "message": "Серверные запросы дублируются (HTTP Ошибка 449)."
- },
- "status.500": {
- "message": "Неизвестная ошибка сервера (HTTP Ошибка 500)."
- },
- "status.503": {
- "message": "Сервис недоступен (HTTP Ошибка 503)."
- },
- "status.BadItemSkipped": {
- "message": "Плохой элемент пропущен: ##replace.1##"
- },
- "status.FolderDelete.3": {
- "message": "Не удается удалить системную папку."
- },
- "status.FolderDelete.4": {
- "message": "Папка не существует (статус 4), повторная синхронизация"
- },
- "status.FolderDelete.6": {
- "message": "Команда не может быть выполнена, на сервере возникла ошибка."
- },
- "status.FolderDelete.9": {
- "message": "Неверный ключ синхронизации (статус 9), повторная синхронизация"
- },
- "status.FolderSync.9": {
- "message": "Неверный ключ синхронизации (статус 9), повторная синхронизация"
- },
- "status.InvalidServerOptions": {
- "message": "Сервер не предоставляет информацию о поддерживаемых версиях ActiveSync. EAS блокирован для этого пользователя или этого клиента (TbSync)? Вы можете попробовать установить версию ActiveSync вручную."
- },
- "status.OK": {
- "message": "Готово"
- },
- "status.ServerRejectedRequest": {
- "message": "Сервер EAS отклонил наш последний запрос."
- },
- "status.ServerRejectedSomeItems": {
- "message": "Сервер EAS не принял элементы ##replace.1##."
- },
- "status.Sync.12": {
- "message": "Изменена иерархия папок (статус 12), повторная синхронизация"
- },
- "status.Sync.3": {
- "message": "Неверный ключ синхронизации (статус 3), повторная синхронизация"
- },
- "status.Sync.4": {
- "message": "Неверный запрос (статус 4)"
- },
- "status.Sync.5": {
- "message": "Временные проблемы с сервером или недопустимый элемент (статус 5)"
- },
- "status.Sync.6": {
- "message": "Недопустимый элемент (статус 6)"
- },
- "status.Sync.8": {
- "message": "Объект не найден (статус 8)"
- },
- "status.aborted": {
- "message": "Не синхронизировано"
- },
- "status.disabled": {
- "message": "Аккаунт не включен, синхронизация отключена."
- },
- "status.empty-response": {
- "message": "Сервер отправляет неожиданный пустой ответ."
- },
- "status.forbiddenCalendarItemInTasksFolder": {
- "message": "Запрещенный элемент календаря в папке задач (пожалуйста, исправьте)"
- },
- "status.forbiddenTasksItemInCalendarFolder": {
- "message": "Запрещенный элемент задачи в папке календаря (пожалуйста, исправьте)"
- },
- "status.global.101": {
- "message": "Запрос содержит WBXML но он не может быть декодирован в XML (EAS Ошибка 101)."
- },
- "status.global.102": {
- "message": "Запрос содержит WBXML но он не может быть декодирован в XML (EAS Ошибка 102)."
- },
- "status.global.103": {
- "message": "XML, указанный в запросе, не соответствует требованиям протокола (EAS Ошибка 103)."
- },
- "status.global.110": {
- "message": "Сервер сообщил о внутренней ошибке, и мы не должны немедленно повторять попытку. Автоматическая периодическая синхронизация была отключена на 30 минут (Ошибка EAS 110)."
- },
- "status.global.clientdenied": {
- "message": "Отчеты сервера EAS <##replace.2##> (статус ##replace.1##) и не позволяют TbSync доступ к вашему аккаунту."
- },
- "status.httperror": {
- "message": "Ошибка связи (HTTP статус ##replace.1##)."
- },
- "status.invalid": {
- "message": "Недопустимый ответ сервера (мусор в обмене)."
- },
- "status.malformed-xml": {
- "message": "Не удалось разобрать XML. Проверьте журнал событий для деталей."
- },
- "status.modified": {
- "message": "Локальные изменения"
- },
- "status.network": {
- "message": "Не удалось подключиться к серверу (##replace.1##)."
- },
- "status.networkerror": {
- "message": "Не удалось подключиться к серверу."
- },
- "status.nosupportedeasversion": {
- "message": "Сервер не поддерживает ActiveSync v2.5 или v14.0 (только ##replace.1##). TbSync не будет работать с этим ActiveSync сервером."
- },
- "status.notargets": {
- "message": "Отмена синхронизации, поскольку цели синхронизации не могут быть созданы."
- },
- "status.notsupportedeasversion": {
- "message": "Сервер не поддерживает выбранный ActiveSync v##replace.1## (только ##replace.2##)."
- },
- "status.notsyncronized": {
- "message": "Аккаунт должен быть синхронизирован, по крайней мере один элемент не синхронизирован."
- },
- "status.nouserhost": {
- "message": "Отсутствует имя пользователя и/или сервера. Укажите эти значения."
- },
- "status.pending": {
- "message": "Ожидание пока синхронизируется"
- },
- "status.policy.2": {
- "message": "Для этого клиента нет политики. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
- },
- "status.policy.3": {
- "message": "Неизвестное значение политики для этого клиента. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
- },
- "status.policy.4": {
- "message": "Данные политики на сервере повреждены (возможно, подделаны). Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
- },
- "status.policy.5": {
- "message": "Клиент обнаружил неправильный ключ политики. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
- },
- "status.provision": {
- "message": "Резервирование не удалось со статусом <##replace.1##>"
- },
- "status.response-contains-no-data": {
- "message": "Ответ от сервера не содержит данных."
- },
- "status.resync-loop": {
- "message": "Произошла ошибка, из-за которой не удалось пересинхронизировать аккаунт. Отключите аккаунт и повторите попытку. (Ошибка: повторная синхронизация)"
- },
- "status.security": {
- "message": "Не удалось установить безопасное соединение. Вы используете самоподписанный или ненадежный сертификат без импорта его в Thunderbird? (##replace.1##)"
- },
- "status.skipped": {
- "message": "Пока не поддерживается, пропущено"
- },
- "status.syncing": {
- "message": "Синхронизация"
- },
- "status.timeout": {
- "message": "Тайм-аут связи."
- },
- "status.wbxml-parse-error": {
- "message": "Сервер отправляет нечитаемый ответ."
- },
- "status.wbxmlerror": {
- "message": "Ошибка синхронизации. Сервер ответил статусом <##replace.1##>."
- },
- "status.wbxmlmissingfield": {
- "message": "ActiveSync протокол нарушен: Обязательное поле <##replace.1##> отсутствует в ответе сервера."
- },
- "syncstate.accountdone": {
- "message": "Завершенный аккаунт"
- },
- "syncstate.done": {
- "message": "Подготовка следующего элемента для синхронизации"
- },
- "syncstate.eval.response.autodiscover": {
- "message": "Обработка обновленных настроек сервера"
- },
- "syncstate.eval.response.deletefolder": {
- "message": "Папка удалена"
- },
- "syncstate.eval.response.estimate": {
- "message": "Обработка оценки изменений"
- },
- "syncstate.eval.response.folders": {
- "message": "Обработка обновления листа папок"
- },
- "syncstate.eval.response.localchanges": {
- "message": "Обработка подтверждения локальных изменений"
- },
- "syncstate.eval.response.localdeletes": {
- "message": "Обработка подтверждения локальных удалений"
- },
- "syncstate.eval.response.options": {
- "message": "Обработка настроек сервера"
- },
- "syncstate.eval.response.provision": {
- "message": "Обработка резервирования"
- },
- "syncstate.eval.response.remotechanges": {
- "message": "Обработка удаленных изменений"
- },
- "syncstate.eval.response.revertlocalchanges": {
- "message": "Откат локальных изменений"
- },
- "syncstate.eval.response.setdeviceinfo": {
- "message": "Обработка информации об устройстве"
- },
- "syncstate.eval.response.synckey": {
- "message": "Обработка элементов синхронизации"
- },
- "syncstate.prepare.request.autodiscover": {
- "message": "Запрос обновленных настроек сервера"
- },
- "syncstate.prepare.request.deletefolder": {
- "message": "Подготовка к удалению папки"
- },
- "syncstate.prepare.request.estimate": {
- "message": "Запрос оценки изменения"
- },
- "syncstate.prepare.request.folders": {
- "message": "Отправка обновления листа папок"
- },
- "syncstate.prepare.request.localchanges": {
- "message": "Отправка локальных изменений"
- },
- "syncstate.prepare.request.localdeletes": {
- "message": "Отправка локальных удалений"
- },
- "syncstate.prepare.request.options": {
- "message": "Запрос настроек сервера"
- },
- "syncstate.prepare.request.provision": {
- "message": "Запрос для резервирования"
- },
- "syncstate.prepare.request.remotechanges": {
- "message": "Запрос удаленных изменений"
- },
- "syncstate.prepare.request.revertlocalchanges": {
- "message": "Сбор локальных изменений"
- },
- "syncstate.prepare.request.setdeviceinfo": {
- "message": "Обработка информации об устройстве"
- },
- "syncstate.prepare.request.synckey": {
- "message": "Запрос элементов синхронизации"
- },
- "syncstate.preparing": {
- "message": "Подготовка следующего элемента для синхронизации"
- },
- "syncstate.send.request.autodiscover": {
- "message": "Ожидание обновленных настроек сервера"
- },
- "syncstate.send.request.deletefolder": {
- "message": "Ожидание удаления папки"
- },
- "syncstate.send.request.estimate": {
- "message": "Ожидание оценки изменений"
- },
- "syncstate.send.request.folders": {
- "message": "Ожидание обновления листа папок"
- },
- "syncstate.send.request.localchanges": {
- "message": "Ожидание подтверждения локальных изменений"
- },
- "syncstate.send.request.localdeletes": {
- "message": "Ожидание подтверждения локальных удалений"
- },
- "syncstate.send.request.options": {
- "message": "Ожидание настроек сервера"
- },
- "syncstate.send.request.provision": {
- "message": "Ожидание резервирования"
- },
- "syncstate.send.request.remotechanges": {
- "message": "Ожидание удаленных изменений"
- },
- "syncstate.send.request.revertlocalchanges": {
- "message": "Ожидание самых последних версий"
- },
- "syncstate.send.request.setdeviceinfo": {
- "message": "Обработка информации об устройстве"
- },
- "syncstate.send.request.synckey": {
- "message": "Ожидание элементов синхронизации"
- },
- "syncstate.syncing": {
- "message": "Инициализация синхронизации"
- }
-}
+{
+ "abCard.Anniversary": {
+ "message": "День рождения:"
+ },
+ "abCard.AssistantName": {
+ "message": "Помощник:"
+ },
+ "abCard.AssistantPhoneNumber": {
+ "message": "Телефон помощника:"
+ },
+ "abCard.Business2PhoneNumber": {
+ "message": "Рабочий телефон 2:"
+ },
+ "abCard.BusinessFaxNumber": {
+ "message": "Рабочий факс:"
+ },
+ "abCard.CarPhoneNumber": {
+ "message": "Автомобильный телефон:"
+ },
+ "abCard.CompanyMainPhone": {
+ "message": "Основной рабочий телефон:"
+ },
+ "abCard.Email3Address": {
+ "message": "Запасной Email:"
+ },
+ "abCard.Home2PhoneNumber": {
+ "message": "Домашний телефон 2:"
+ },
+ "abCard.ManagerName": {
+ "message": "Руководитель:"
+ },
+ "abCard.MiddleName": {
+ "message": "Отчество:"
+ },
+ "abCard.OtherAddress": {
+ "message": "Адрес:"
+ },
+ "abCard.OtherCity": {
+ "message": "Город:"
+ },
+ "abCard.OtherCountry": {
+ "message": "Страна:"
+ },
+ "abCard.OtherState": {
+ "message": "Область:"
+ },
+ "abCard.OtherZip": {
+ "message": "Почтовый индекс:"
+ },
+ "abCard.RadioPhoneNumber": {
+ "message": "Радиотелефон:"
+ },
+ "abCard.Spouse": {
+ "message": "Супруг:"
+ },
+ "abCard.header.eas": {
+ "message": "Другие поля (EAS)"
+ },
+ "abCard.header.homenumbers": {
+ "message": "Дополнительные домашние номера:"
+ },
+ "abCard.header.messaging": {
+ "message": "Мессенджер:"
+ },
+ "abCard.header.otheraddress": {
+ "message": "Другой адрес (EAS)"
+ },
+ "abCard.header.othernumbers": {
+ "message": "Дополнительные номера:"
+ },
+ "abCard.header.people": {
+ "message": "Люди:"
+ },
+ "abCard.header.worknumbers": {
+ "message": "Дополнительные рабочие номера:"
+ },
+ "acl.readonly": {
+ "message": "Доступ к серверу только для чтения (отменить локальные изменения)"
+ },
+ "acl.readwrite": {
+ "message": "Читать и писать на сервер"
+ },
+ "add.description": {
+ "message": "Пожалуйста, выберите один из доступных параметров конфигурации сервера и введите требуемую информацию. "
+ },
+ "add.name": {
+ "message": "Имя аккаунта:"
+ },
+ "add.ok": {
+ "message": "Добавить аккаунт"
+ },
+ "add.password": {
+ "message": "Пароль:"
+ },
+ "add.server": {
+ "message": "Конфигурация сервера:"
+ },
+ "add.shortdescription": {
+ "message": "Информация об учетной записи"
+ },
+ "add.title": {
+ "message": "Добавить Exchange ActiveSync аккаунт для TbSync"
+ },
+ "add.url": {
+ "message": "Адрес сервера:"
+ },
+ "add.urldescription": {
+ "message": "Достаточно указать только базовый адрес сервера (например: mail.yourserver.com). Однако также можно указать полный URL-адрес (например: https://mail.yourserver.com/Microsoft-Server-ActiveSync)."
+ },
+ "add.user": {
+ "message": "Имя пользователя (email адрес):"
+ },
+ "autocomplete.serverdirectory": {
+ "message": "глобальный каталог сервера"
+ },
+ "autodiscover.Failed": {
+ "message": "Автообнаружение для пользователя <##user##> не удалось. Либо предоставленные учетные данные были неправильными, либо у вашего провайдера ActiveSync была временная проблема, или не поддерживается автообнаружение."
+ },
+ "autodiscover.NeedEmail": {
+ "message": "Автообнаружению нужен действительный адрес электронной почты в качестве имени пользователя."
+ },
+ "autodiscover.Ok": {
+ "message": "Автообнаружение успешно завершено, теперь вы можете проверить дополнительные настройки и установить соединение синхронизации."
+ },
+ "autodiscover.Querying": {
+ "message": "Поиск настроек…"
+ },
+ "config.auto": {
+ "message": "ActiveSync конфигурация сервера (Автообнаружение)"
+ },
+ "config.custom": {
+ "message": "ActiveSync конфигурация сервера"
+ },
+ "deletefolder.confirm": {
+ "message": "Вы действительно хотите ПЕРМАНЕНТНО ВЫЧИСТИТЬ папку “##replace.1##” из корзины?"
+ },
+ "deletefolder.menuentry": {
+ "message": "Перманентно вычистить папку “##replace.1##” из корзины"
+ },
+ "deletefolder.notallowed": {
+ "message": "Откажитесь от подписки папки “##replace.1##” прежде чем пытаться очистить ее от мусора."
+ },
+ "extensionDescription": {
+ "message": "Добавляет в TbSync поддержку синхронизации для учетных записей Exchange через базирующийся на http/https протокол ActiveSync (контакты, задачи и календари)."
+ },
+ "extensionName": {
+ "message": "Provider for Exchange ActiveSync"
+ },
+ "helplink.BadItemSkipped": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/Error:-Bad-item-skipped"
+ },
+ "helplink.global.clientdenied": {
+ "message": "https://github.com/jobisoft/EAS-4-TbSync/wiki/What-if-TbSync-is-blocked-by-my-server%3F"
+ },
+ "helplink.security": {
+ "message": "https://github.com/jobisoft/TbSync/wiki/How-to-use-TbSync-with-self-signed-or-otherwise-untrusted-certificates%3F"
+ },
+ "manager.tabs.accountsettings": {
+ "message": "Настройки аккаунта"
+ },
+ "manager.tabs.outOfOffice": {
+ "message": "Автоответчик"
+ },
+ "manager.tabs.syncsettings": {
+ "message": "Настройки синхронизации"
+ },
+ "newaccount.add_auto": {
+ "message": "Настройки автообнаружения и добавление аккаунта"
+ },
+ "newaccount.add_custom": {
+ "message": "Добавить аккаунт"
+ },
+ "pref.AccountName": {
+ "message": "Имя аккаунта"
+ },
+ "pref.ActiveSyncVersion": {
+ "message": "Версия ActiveSync"
+ },
+ "pref.DeviceId": {
+ "message": "Идентификатор устройства"
+ },
+ "pref.ServerName": {
+ "message": "Адрес сервера"
+ },
+ "pref.ServerNameDescription": {
+ "message": "например: mail.yourserver.com"
+ },
+ "pref.ShowTrashedFolders": {
+ "message": "Показывать папки, найденные в корзине"
+ },
+ "pref.UserName": {
+ "message": "Имя пользователя"
+ },
+ "pref.UserNameDescription": {
+ "message": "Имя пользователя обычно является адресом электронной почты вашей учетной записи."
+ },
+ "pref.autodetect": {
+ "message": "лучшее из доступных"
+ },
+ "pref.birthday": {
+ "message": "Отправить информацию о днях рождения"
+ },
+ "pref.calendaroptions": {
+ "message": "Параметры календаря"
+ },
+ "pref.contactoptions": {
+ "message": "Параметры контакта"
+ },
+ "pref.displayoverride": {
+ "message": "Переопределить отображаемое имя с помощью “Имя” + “Фамилия”"
+ },
+ "pref.generaloptions": {
+ "message": "Общие параметры"
+ },
+ "pref.provision": {
+ "message": "Заставить поддерживать (требуется для Kerio)"
+ },
+ "pref.seperator.comma": {
+ "message": "Запятая"
+ },
+ "pref.seperator.description": {
+ "message": "Сепаратор для многострочного поля адреса."
+ },
+ "pref.seperator.linebreak": {
+ "message": "Разрыв строки"
+ },
+ "pref.synclimit.1month": {
+ "message": "от 4 недель назад"
+ },
+ "pref.synclimit.2weeks": {
+ "message": "от 2 недель назад"
+ },
+ "pref.synclimit.3month": {
+ "message": "от 3 месяцев назад"
+ },
+ "pref.synclimit.6month": {
+ "message": "от 6 месяцев назад"
+ },
+ "pref.synclimit.all": {
+ "message": "все"
+ },
+ "pref.synclimit.description": {
+ "message": "Период синхронизации:"
+ },
+ "pref.usehttps": {
+ "message": "Использовать безопасное соединение (соединение через https)"
+ },
+ "recyclebin": {
+ "message": "Корзина"
+ },
+ "servertype.auto": {
+ "message": "Автоматическая настройка"
+ },
+ "servertype.custom": {
+ "message": "Ручная настройка"
+ },
+ "servertype.description.auto": {
+ "message": "Для определения конфигурации множества серверов ActiveSync достаточно указать только адрес Вашей электронной почты."
+ },
+ "servertype.description.custom": {
+ "message": "Настройте Вашу учетную запись, вручную указав адрес сервера, к которому Вы хотите подключиться."
+ },
+ "servertype.description.office365": {
+ "message": "Учетные записи, подключенные к Office 365, используют современный процесс аутентификации под названием OAuth 2.0, который также поддерживает многофакторную аутентификацию (MFA)."
+ },
+ "servertype.office365": {
+ "message": "Microsoft Office 365"
+ },
+ "servertype.unlock": {
+ "message": "Дважды щелкните, чтобы разблокировать все предопределенные настройки сервера."
+ },
+ "status.401": {
+ "message": "Не удалось аутентифицировать, проверить имя пользователя и пароль. (HTTP Ошибка 401)."
+ },
+ "status.403": {
+ "message": "Сервер отклонил соединение (запрещено) (HTTP Ошибка 403)."
+ },
+ "status.404": {
+ "message": "Пользователь не найден (HTTP Ошибка 404)."
+ },
+ "status.449": {
+ "message": "Серверные запросы дублируются (HTTP Ошибка 449)."
+ },
+ "status.500": {
+ "message": "Неизвестная ошибка сервера (HTTP Ошибка 500)."
+ },
+ "status.503": {
+ "message": "Сервис недоступен (HTTP Ошибка 503)."
+ },
+ "status.BadItemSkipped": {
+ "message": "Плохой элемент пропущен: ##replace.1##"
+ },
+ "status.FolderDelete.3": {
+ "message": "Не удается удалить системную папку."
+ },
+ "status.FolderDelete.4": {
+ "message": "Папка не существует (статус 4), повторная синхронизация"
+ },
+ "status.FolderDelete.6": {
+ "message": "Команда не может быть выполнена, на сервере возникла ошибка."
+ },
+ "status.FolderDelete.9": {
+ "message": "Неверный ключ синхронизации (статус 9), повторная синхронизация"
+ },
+ "status.FolderSync.9": {
+ "message": "Неверный ключ синхронизации (статус 9), повторная синхронизация"
+ },
+ "status.InvalidServerOptions": {
+ "message": "Сервер не предоставляет информацию о поддерживаемых версиях ActiveSync. EAS блокирован для этого пользователя или этого клиента (TbSync)? Вы можете попробовать установить версию ActiveSync вручную."
+ },
+ "status.OK": {
+ "message": "Готово"
+ },
+ "status.ServerRejectedRequest": {
+ "message": "Сервер EAS отклонил наш последний запрос."
+ },
+ "status.ServerRejectedSomeItems": {
+ "message": "Сервер EAS не принял элементы ##replace.1##."
+ },
+ "status.Sync.12": {
+ "message": "Изменена иерархия папок (статус 12), повторная синхронизация"
+ },
+ "status.Sync.3": {
+ "message": "Неверный ключ синхронизации (статус 3), повторная синхронизация"
+ },
+ "status.Sync.4": {
+ "message": "Неверный запрос (статус 4)"
+ },
+ "status.Sync.5": {
+ "message": "Временные проблемы с сервером или недопустимый элемент (статус 5)"
+ },
+ "status.Sync.6": {
+ "message": "Недопустимый элемент (статус 6)"
+ },
+ "status.Sync.8": {
+ "message": "Объект не найден (статус 8)"
+ },
+ "status.aborted": {
+ "message": "Не синхронизировано"
+ },
+ "status.disabled": {
+ "message": "Аккаунт не включен, синхронизация отключена."
+ },
+ "status.empty-response": {
+ "message": "Сервер отправляет неожиданный пустой ответ."
+ },
+ "status.forbiddenCalendarItemInTasksFolder": {
+ "message": "Запрещенный элемент календаря в папке задач (пожалуйста, исправьте)"
+ },
+ "status.forbiddenTasksItemInCalendarFolder": {
+ "message": "Запрещенный элемент задачи в папке календаря (пожалуйста, исправьте)"
+ },
+ "status.global.101": {
+ "message": "Запрос содержит WBXML но он не может быть декодирован в XML (EAS Ошибка 101)."
+ },
+ "status.global.102": {
+ "message": "Запрос содержит WBXML но он не может быть декодирован в XML (EAS Ошибка 102)."
+ },
+ "status.global.103": {
+ "message": "XML, указанный в запросе, не соответствует требованиям протокола (EAS Ошибка 103)."
+ },
+ "status.global.110": {
+ "message": "Сервер сообщил о внутренней ошибке, и мы не должны немедленно повторять попытку. Автоматическая периодическая синхронизация была отключена на 30 минут (Ошибка EAS 110)."
+ },
+ "status.global.clientdenied": {
+ "message": "Отчеты сервера EAS <##replace.2##> (статус ##replace.1##) и не позволяют TbSync доступ к вашему аккаунту."
+ },
+ "status.httperror": {
+ "message": "Ошибка связи (HTTP статус ##replace.1##)."
+ },
+ "status.invalid": {
+ "message": "Недопустимый ответ сервера (мусор в обмене)."
+ },
+ "status.malformed-xml": {
+ "message": "Не удалось разобрать XML. Проверьте журнал событий для деталей."
+ },
+ "status.modified": {
+ "message": "Локальные изменения"
+ },
+ "status.network": {
+ "message": "Не удалось подключиться к серверу (##replace.1##)."
+ },
+ "status.networkerror": {
+ "message": "Не удалось подключиться к серверу."
+ },
+ "status.nosupportedeasversion": {
+ "message": "Сервер не поддерживает ActiveSync v2.5 или v14.0 (только ##replace.1##). TbSync не будет работать с этим ActiveSync сервером."
+ },
+ "status.notargets": {
+ "message": "Отмена синхронизации, поскольку цели синхронизации не могут быть созданы."
+ },
+ "status.notsupportedeasversion": {
+ "message": "Сервер не поддерживает выбранный ActiveSync v##replace.1## (только ##replace.2##)."
+ },
+ "status.notsyncronized": {
+ "message": "Аккаунт должен быть синхронизирован, по крайней мере один элемент не синхронизирован."
+ },
+ "status.nouserhost": {
+ "message": "Отсутствует имя пользователя и/или сервера. Укажите эти значения."
+ },
+ "status.pending": {
+ "message": "Ожидание пока синхронизируется"
+ },
+ "status.policy.2": {
+ "message": "Для этого клиента нет политики. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
+ },
+ "status.policy.3": {
+ "message": "Неизвестное значение политики для этого клиента. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
+ },
+ "status.policy.4": {
+ "message": "Данные политики на сервере повреждены (возможно, подделаны). Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
+ },
+ "status.policy.5": {
+ "message": "Клиент обнаружил неправильный ключ политики. Обратитесь к администратору вашего сервера или отключите использование этого аккаунта."
+ },
+ "status.provision": {
+ "message": "Резервирование не удалось со статусом <##replace.1##>"
+ },
+ "status.response-contains-no-data": {
+ "message": "Ответ от сервера не содержит данных."
+ },
+ "status.resync-loop": {
+ "message": "Произошла ошибка, из-за которой не удалось пересинхронизировать аккаунт. Отключите аккаунт и повторите попытку. (Ошибка: повторная синхронизация)"
+ },
+ "status.security": {
+ "message": "Не удалось установить безопасное соединение. Вы используете самоподписанный или ненадежный сертификат без импорта его в Thunderbird? (##replace.1##)"
+ },
+ "status.skipped": {
+ "message": "Пока не поддерживается, пропущено"
+ },
+ "status.syncing": {
+ "message": "Синхронизация"
+ },
+ "status.timeout": {
+ "message": "Тайм-аут связи."
+ },
+ "status.wbxml-parse-error": {
+ "message": "Сервер отправляет нечитаемый ответ."
+ },
+ "status.wbxmlerror": {
+ "message": "Ошибка синхронизации. Сервер ответил статусом <##replace.1##>."
+ },
+ "status.wbxmlmissingfield": {
+ "message": "ActiveSync протокол нарушен: Обязательное поле <##replace.1##> отсутствует в ответе сервера."
+ },
+ "syncstate.accountdone": {
+ "message": "Завершенный аккаунт"
+ },
+ "syncstate.done": {
+ "message": "Подготовка следующего элемента для синхронизации"
+ },
+ "syncstate.eval.response.autodiscover": {
+ "message": "Обработка обновленных настроек сервера"
+ },
+ "syncstate.eval.response.deletefolder": {
+ "message": "Папка удалена"
+ },
+ "syncstate.eval.response.estimate": {
+ "message": "Обработка оценки изменений"
+ },
+ "syncstate.eval.response.folders": {
+ "message": "Обработка обновления листа папок"
+ },
+ "syncstate.eval.response.localchanges": {
+ "message": "Обработка подтверждения локальных изменений"
+ },
+ "syncstate.eval.response.localdeletes": {
+ "message": "Обработка подтверждения локальных удалений"
+ },
+ "syncstate.eval.response.options": {
+ "message": "Обработка настроек сервера"
+ },
+ "syncstate.eval.response.provision": {
+ "message": "Обработка резервирования"
+ },
+ "syncstate.eval.response.remotechanges": {
+ "message": "Обработка удаленных изменений"
+ },
+ "syncstate.eval.response.revertlocalchanges": {
+ "message": "Откат локальных изменений"
+ },
+ "syncstate.eval.response.setdeviceinfo": {
+ "message": "Обработка информации об устройстве"
+ },
+ "syncstate.eval.response.synckey": {
+ "message": "Обработка элементов синхронизации"
+ },
+ "syncstate.prepare.request.autodiscover": {
+ "message": "Запрос обновленных настроек сервера"
+ },
+ "syncstate.prepare.request.deletefolder": {
+ "message": "Подготовка к удалению папки"
+ },
+ "syncstate.prepare.request.estimate": {
+ "message": "Запрос оценки изменения"
+ },
+ "syncstate.prepare.request.folders": {
+ "message": "Отправка обновления листа папок"
+ },
+ "syncstate.prepare.request.localchanges": {
+ "message": "Отправка локальных изменений"
+ },
+ "syncstate.prepare.request.localdeletes": {
+ "message": "Отправка локальных удалений"
+ },
+ "syncstate.prepare.request.options": {
+ "message": "Запрос настроек сервера"
+ },
+ "syncstate.prepare.request.provision": {
+ "message": "Запрос для резервирования"
+ },
+ "syncstate.prepare.request.remotechanges": {
+ "message": "Запрос удаленных изменений"
+ },
+ "syncstate.prepare.request.revertlocalchanges": {
+ "message": "Сбор локальных изменений"
+ },
+ "syncstate.prepare.request.setdeviceinfo": {
+ "message": "Обработка информации об устройстве"
+ },
+ "syncstate.prepare.request.synckey": {
+ "message": "Запрос элементов синхронизации"
+ },
+ "syncstate.preparing": {
+ "message": "Подготовка следующего элемента для синхронизации"
+ },
+ "syncstate.send.request.autodiscover": {
+ "message": "Ожидание обновленных настроек сервера"
+ },
+ "syncstate.send.request.deletefolder": {
+ "message": "Ожидание удаления папки"
+ },
+ "syncstate.send.request.estimate": {
+ "message": "Ожидание оценки изменений"
+ },
+ "syncstate.send.request.folders": {
+ "message": "Ожидание обновления листа папок"
+ },
+ "syncstate.send.request.localchanges": {
+ "message": "Ожидание подтверждения локальных изменений"
+ },
+ "syncstate.send.request.localdeletes": {
+ "message": "Ожидание подтверждения локальных удалений"
+ },
+ "syncstate.send.request.options": {
+ "message": "Ожидание настроек сервера"
+ },
+ "syncstate.send.request.provision": {
+ "message": "Ожидание резервирования"
+ },
+ "syncstate.send.request.remotechanges": {
+ "message": "Ожидание удаленных изменений"
+ },
+ "syncstate.send.request.revertlocalchanges": {
+ "message": "Ожидание самых последних версий"
+ },
+ "syncstate.send.request.setdeviceinfo": {
+ "message": "Обработка информации об устройстве"
+ },
+ "syncstate.send.request.synckey": {
+ "message": "Ожидание элементов синхронизации"
+ },
+ "syncstate.syncing": {
+ "message": "Инициализация синхронизации"
+ }
+}
diff -Nru eas4tbsync-4.11/api/EAS4TbSync/implementation.js eas4tbsync-4.17/api/EAS4TbSync/implementation.js
--- eas4tbsync-4.11/api/EAS4TbSync/implementation.js 1970-01-01 00:00:00.000000000 +0000
+++ eas4tbsync-4.17/api/EAS4TbSync/implementation.js 2025-05-15 11:21:20.000000000 +0000
@@ -0,0 +1,74 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+// Using a closure to not leak anything but the API to the outside world.
+(function (exports) {
+
+ const { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+ );
+
+ async function observeTbSyncInitialized(aSubject, aTopic, aData) {
+ try {
+ const tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+ );
+ const { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+ );
+ // Load this provider add-on into TbSync
+ if (TbSync.enabled) {
+ const easExtension = ExtensionParent.GlobalManager.getExtension(
+ "eas4tbsync@jobisoft.de"
+ );
+ console.log(`Registering EAS provider v${easExtension.manifest.version} with TbSync v${tbsyncExtension.manifest.version}`);
+ await TbSync.providers.loadProvider(easExtension, "eas", "chrome://eas4tbsync/content/provider.js");
+ }
+ } catch (e) {
+ // If this fails, TbSync is not loaded yet and we will get the notification later again.
+ }
+
+ }
+
+ var EAS4TbSync = class extends ExtensionCommon.ExtensionAPI {
+
+ getAPI(context) {
+ return {
+ EAS4TbSync: {
+ async load() {
+ Services.obs.addObserver(observeTbSyncInitialized, "tbsync.observer.initialized", false);
+
+ // Did we miss the observer?
+ observeTbSyncInitialized();
+ }
+ },
+ };
+ }
+
+ onShutdown(isAppShutdown) {
+ if (isAppShutdown) {
+ return; // the application gets unloaded anyway
+ }
+
+ Services.obs.removeObserver(observeTbSyncInitialized, "tbsync.observer.initialized");
+ //unload this provider add-on from TbSync
+ try {
+ const tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+ );
+ const { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+ );
+ TbSync.providers.unloadProvider("eas");
+ } catch (e) {
+ //if this fails, TbSync has been unloaded already and has unloaded this addon as well
+ }
+ }
+ };
+ exports.EAS4TbSync = EAS4TbSync;
+})(this);
\ No newline at end of file
diff -Nru eas4tbsync-4.11/api/EAS4TbSync/schema.json eas4tbsync-4.17/api/EAS4TbSync/schema.json
--- eas4tbsync-4.11/api/EAS4TbSync/schema.json 1970-01-01 00:00:00.000000000 +0000
+++ eas4tbsync-4.17/api/EAS4TbSync/schema.json 2025-05-15 11:21:20.000000000 +0000
@@ -0,0 +1,13 @@
+[
+ {
+ "namespace": "EAS4TbSync",
+ "functions": [
+ {
+ "name": "load",
+ "type": "function",
+ "async": true,
+ "parameters": []
+ }
+ ]
+ }
+]
\ No newline at end of file
diff -Nru eas4tbsync-4.11/api/LegacyHelper/README.md eas4tbsync-4.17/api/LegacyHelper/README.md
--- eas4tbsync-4.11/api/LegacyHelper/README.md 1970-01-01 00:00:00.000000000 +0000
+++ eas4tbsync-4.17/api/LegacyHelper/README.md 2025-05-15 11:21:20.000000000 +0000
@@ -0,0 +1,50 @@
+## Objective
+
+This API is a temporary helper while converting legacy extensions to modern WebExtensions. It allows to register `resource://` URLs, which are needed to load custom system modules (*.sys.mjs), and `chrome://` URLs, which are needed to open legacy XUL dialogs.
+
+## Usage
+
+Add the [LegacyHelper API](https://github.com/thunderbird/webext-support/tree/master/experiments/LegacyHelper) to your add-on. Your `manifest.json` needs an entry like this:
+
+```json
+ "experiment_apis": {
+ "LegacyHelper": {
+ "schema": "api/LegacyHelper/schema.json",
+ "parent": {
+ "scopes": ["addon_parent"],
+ "paths": [["LegacyHelper"]],
+ "script": "api/LegacyHelper/implementation.js"
+ }
+ }
+ },
+```
+
+## API Functions
+
+This API provides the following functions:
+
+### async registerGlobalUrls(data)
+
+Register `chrome://*/content/` and `resource://*/` URLs. The function accepts a `data` parameter, which is an array of URL definition items. For example:
+
+```javascript
+await browser.LegacyHelper.registerGlobalUrls([
+ ["content", "myaddon", "chrome/content/"],
+ ["resource", "myaddon", "modules/"],
+]);
+```
+
+This registers the following URLs:
+* `chrome://myaddon/content/` pointing to the `/chrome/content/` folder (the `/content/` part in the URL is fix and does not depend on the name of the folder it is pointing to)
+* `resource://myaddon/` pointing to the `/modules/` folder. To register a `resource://` URL which points to the root folder, use `.` instead".
+
+### async openDialog(name, path)
+
+Open a XUL dialog. The `name` parameter is a unique name identifying the dialog. If the dialog with that name is already open, it will be focused instead of being re-opened. The `path` parameter is a `chrome://*/content/` URL pointing to the XUL dialog file (*.xul or *.xhtml).
+
+```javascript
+browser.LegacyHelper.openDialog(
+ "XulAddonOptions",
+ "chrome://myaddon/content/options.xhtml"
+);
+```
diff -Nru eas4tbsync-4.11/api/LegacyHelper/implementation.js eas4tbsync-4.17/api/LegacyHelper/implementation.js
--- eas4tbsync-4.11/api/LegacyHelper/implementation.js 1970-01-01 00:00:00.000000000 +0000
+++ eas4tbsync-4.17/api/LegacyHelper/implementation.js 2025-05-15 11:21:20.000000000 +0000
@@ -0,0 +1,118 @@
+/*
+ * This file is provided by the webext-support repository at
+ * https://github.com/thunderbird/webext-support
+ *
+ * Version 1.1
+ * - registerGlobalUrls() is now async, to be able to properly await registration
+ *
+ * Version 1.0
+ * - initial release
+ *
+ * Author:
+ * - John Bieling (john@thunderbird.net)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+// Using a closure to not leak anything but the API to the outside world.
+(function (exports) {
+
+ const aomStartup = Cc[
+ "@mozilla.org/addons/addon-manager-startup;1"
+ ].getService(Ci.amIAddonManagerStartup);
+ const resProto = Cc[
+ "@mozilla.org/network/protocol;1?name=resource"
+ ].getService(Ci.nsISubstitutingProtocolHandler);
+
+ const chromeHandlers = [];
+ const resourceUrls = [];
+
+ var LegacyHelper = class extends ExtensionCommon.ExtensionAPI {
+ getAPI(context) {
+ return {
+ LegacyHelper: {
+ registerGlobalUrls(data) {
+ const manifestURI = Services.io.newURI(
+ "manifest.json",
+ null,
+ context.extension.rootURI
+ );
+
+ for (let entry of data) {
+ // [ "resource", "shortname" , "path" ]
+
+ switch (entry[0]) {
+ case "resource":
+ {
+ let uri = Services.io.newURI(
+ entry[2],
+ null,
+ context.extension.rootURI
+ );
+ resProto.setSubstitutionWithFlags(
+ entry[1],
+ uri,
+ resProto.ALLOW_CONTENT_ACCESS
+ );
+ resourceUrls.push(entry[1]);
+ }
+ break;
+
+ case "content":
+ case "locale":
+ {
+ let handle = aomStartup.registerChrome(
+ manifestURI,
+ [entry]
+ );
+ chromeHandlers.push(handle);
+ }
+ break;
+
+ default:
+ console.warn(`LegacyHelper: Unsupported url type: ${entry[0]}`)
+ }
+ }
+ },
+
+ openDialog(name, path) {
+ let window = Services.wm.getMostRecentWindow("mail:3pane");
+ window.openDialog(
+ path,
+ name,
+ "chrome,resizable,centerscreen"
+ );
+ },
+ },
+ };
+ }
+
+ onShutdown(isAppShutdown) {
+ if (isAppShutdown) {
+ return; // the application gets unloaded anyway
+ }
+
+ for (let chromeHandler of chromeHandlers) {
+ if (chromeHandler) {
+ chromeHandler.destruct();
+ chromeHandler = null;
+ }
+ }
+
+ for (let resourceUrl of resourceUrls) {
+ resProto.setSubstitution(
+ resourceUrl,
+ null
+ );
+ }
+
+ // Flush all caches.
+ Services.obs.notifyObservers(null, "startupcache-invalidate");
+ }
+ };
+ exports.LegacyHelper = LegacyHelper;
+})(this);
\ No newline at end of file
diff -Nru eas4tbsync-4.11/api/LegacyHelper/schema.json eas4tbsync-4.17/api/LegacyHelper/schema.json
--- eas4tbsync-4.11/api/LegacyHelper/schema.json 1970-01-01 00:00:00.000000000 +0000
+++ eas4tbsync-4.17/api/LegacyHelper/schema.json 2025-05-15 11:21:20.000000000 +0000
@@ -0,0 +1,42 @@
+[
+ {
+ "namespace": "LegacyHelper",
+ "functions": [
+ {
+ "name": "registerGlobalUrls",
+ "type": "function",
+ "async": true,
+ "description": "Register folders which should be available as legacy chrome:// urls or resource:// urls",
+ "parameters": [
+ {
+ "name": "data",
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "description": "Array of manifest url definitions (content, locale or resource)"
+ }
+ ]
+ },
+ {
+ "name": "openDialog",
+ "type": "function",
+ "parameters": [
+ {
+ "name": "name",
+ "type": "string",
+ "description": "name of the new dialog"
+ },
+ {
+ "name": "path",
+ "type": "string",
+ "description": "path of the dialog to be opened"
+ }
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff -Nru eas4tbsync-4.11/background.js eas4tbsync-4.17/background.js
--- eas4tbsync-4.11/background.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/background.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,6 +1,5 @@
-async function main() {
- await messenger.BootstrapLoader.registerChromeUrl([ ["content", "eas4tbsync", "content/"] ]);
- await messenger.BootstrapLoader.registerBootstrapScript("chrome://eas4tbsync/content/bootstrap.js");
-}
-
-main();
+await browser.LegacyHelper.registerGlobalUrls([
+ ["content", "eas4tbsync", "content/"],
+]);
+
+await browser.EAS4TbSync.load();
diff -Nru eas4tbsync-4.11/beta-release-channel-update.json eas4tbsync-4.17/beta-release-channel-update.json
--- eas4tbsync-4.11/beta-release-channel-update.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/beta-release-channel-update.json 1970-01-01 00:00:00.000000000 +0000
@@ -1,13 +0,0 @@
-{
- "addons": {
- "eas4tbsync@jobisoft.de": {
- "updates": [
- { "version": "%VERSION%",
- "update_info_url": "https://github.com/jobisoft/EAS-4-TbSync/releases",
- "update_link": "%LINK%",
- "applications": {
- "gecko": { "strict_min_version": "78.0" } } }
- ]
- }
- }
-}
\ No newline at end of file
diff -Nru eas4tbsync-4.11/content/api/BootstrapLoader/CHANGELOG.md eas4tbsync-4.17/content/api/BootstrapLoader/CHANGELOG.md
--- eas4tbsync-4.11/content/api/BootstrapLoader/CHANGELOG.md 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/api/BootstrapLoader/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000
@@ -1,75 +0,0 @@
-Version: 1.21
--------------
-- Explicitly set hasAddonManagerEventListeners flag to false on uninstall
-
-Version: 1.20
--------------
-- hard fork BootstrapLoader v1.19 implementation and continue to serve it for
- Thunderbird 111 and older
-- BootstrapLoader v1.20 has removed a lot of unnecessary code used for backward
- compatibility
-
-Version: 1.19
--------------
-- fix race condition which could prevent the AOM tab to be monkey patched correctly
-
-Version: 1.18
--------------
-- be precise on which revision the wrench symbol should be displayed, instead of
- the options button
-
-Version: 1.17
--------------
-- fix "ownerDoc.getElementById() is undefined" bug
-
-Version: 1.16
--------------
-- fix "tab.browser is undefined" bug
-
-Version 1.15
-------------
-- clear cache only if add-on is uninstalled/updated, not on app shutdown
-
-Version 1.14
-------------
-- fix for TB90 ("view-loaded" event) and TB78.10 (wrench icon for options)
-
-Version 1.13
-------------
-- removed notifyTools and move it into its own NotifyTools API
-
-Version 1.12
-------------
-- add support for notifyExperiment and onNotifyBackground
-
-Version 1.11
-------------
-- add openOptionsDialog()
-
-Version 1.10
-------------
-- fix for 68
-
-Version 1.7
------------
-- fix for beta 87
-
-Version 1.6
------------
-- add support for options button/menu in add-on manager and fix 68 double menu entry
-
-Version 1.5
------------
-- fix for e10s
-
-Version 1.4
------------
-- add registerOptionsPage
-
-Version 1.3
------------
-- flush cache
-
-Version 1.2
------------
-- add support for resource urls
diff -Nru eas4tbsync-4.11/content/api/BootstrapLoader/README.md eas4tbsync-4.17/content/api/BootstrapLoader/README.md
--- eas4tbsync-4.11/content/api/BootstrapLoader/README.md 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/api/BootstrapLoader/README.md 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-Usage description can be found in the [wiki](https://github.com/thundernest/addon-developer-support/wiki/Using-the-BootstrapLoader-API-to-convert-a-Legacy-Bootstrap-WebExtension-into-a-MailExtension-for-Thunderbird-78).
diff -Nru eas4tbsync-4.11/content/api/BootstrapLoader/implementation.js eas4tbsync-4.17/content/api/BootstrapLoader/implementation.js
--- eas4tbsync-4.11/content/api/BootstrapLoader/implementation.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/api/BootstrapLoader/implementation.js 1970-01-01 00:00:00.000000000 +0000
@@ -1,187 +0,0 @@
-/*
- * This file is provided by the addon-developer-support repository at
- * https://github.com/thundernest/addon-developer-support
- *
- * Version: 1.21
- *
- * Author: John Bieling (john@thunderbird.net)
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-// Get various parts of the WebExtension framework that we need.
-var { ExtensionCommon } = ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm");
-var { ExtensionSupport } = ChromeUtils.import("resource:///modules/ExtensionSupport.jsm");
-var { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
-
-function getMessenger(context) {
- let apis = ["storage", "runtime", "extension", "i18n"];
-
- function getStorage() {
- let localstorage = null;
- try {
- localstorage = context.apiCan.findAPIPath("storage");
- localstorage.local.get = (...args) =>
- localstorage.local.callMethodInParentProcess("get", args);
- localstorage.local.set = (...args) =>
- localstorage.local.callMethodInParentProcess("set", args);
- localstorage.local.remove = (...args) =>
- localstorage.local.callMethodInParentProcess("remove", args);
- localstorage.local.clear = (...args) =>
- localstorage.local.callMethodInParentProcess("clear", args);
- } catch (e) {
- console.info("Storage permission is missing");
- }
- return localstorage;
- }
-
- let messenger = {};
- for (let api of apis) {
- switch (api) {
- case "storage":
- ChromeUtils.defineLazyGetter(messenger, "storage", () =>
- getStorage()
- );
- break;
-
- default:
- ChromeUtils.defineLazyGetter(messenger, api, () =>
- context.apiCan.findAPIPath(api)
- );
- }
- }
- return messenger;
-}
-
-// Removed all extra code for backward compatibility for better maintainability.
-var BootstrapLoader = class extends ExtensionCommon.ExtensionAPI {
- getAPI(context) {
- this.uniqueRandomID = "AddOnNS" + context.extension.instanceId;
- this.menu_addonPrefs_id = "addonPrefs";
-
-
- this.pathToBootstrapScript = null;
- this.chromeHandle = null;
- this.chromeData = null;
- this.bootstrappedObj = {};
-
- // make the extension object and the messenger object available inside
- // the bootstrapped scope
- this.bootstrappedObj.extension = context.extension;
- this.bootstrappedObj.messenger = getMessenger(this.context);
-
- this.BOOTSTRAP_REASONS = {
- APP_STARTUP: 1,
- APP_SHUTDOWN: 2,
- ADDON_ENABLE: 3,
- ADDON_DISABLE: 4,
- ADDON_INSTALL: 5,
- ADDON_UNINSTALL: 6, // not supported
- ADDON_UPGRADE: 7,
- ADDON_DOWNGRADE: 8,
- };
-
- const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
- const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler);
-
- let self = this;
-
- // TabMonitor to detect opening of tabs, to setup the options button in the add-on manager.
- this.tabMonitor = {
- onTabTitleChanged(tab) { },
- onTabClosing(tab) { },
- onTabPersist(tab) { },
- onTabRestored(tab) { },
- onTabSwitched(aNewTab, aOldTab) { },
- async onTabOpened(tab) {
- if (tab.browser && tab.mode.name == "contentTab") {
- let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane");
- // Instead of registering a load observer, wait until its loaded. Not nice,
- // but gets aroud a lot of edge cases.
- while (!tab.pageLoaded) {
- await new Promise(r => setTimeout(r, 150));
- }
- self.setupAddonManager(self.getAddonManagerFromTab(tab));
- }
- },
- };
-
- return {
- BootstrapLoader: {
- registerChromeUrl(data) {
- let chromeData = [];
- for (let entry of data) {
- chromeData.push(entry)
- }
-
- if (chromeData.length > 0) {
- const manifestURI = Services.io.newURI(
- "manifest.json",
- null,
- context.extension.rootURI
- );
- self.chromeHandle = aomStartup.registerChrome(manifestURI, chromeData);
- }
-
- self.chromeData = chromeData;
- },
-
- registerBootstrapScript: async function (aPath) {
- self.pathToBootstrapScript = aPath.startsWith("chrome://")
- ? aPath
- : context.extension.rootURI.resolve(aPath);
-
- // Get the addon object belonging to this extension.
- let addon = await AddonManager.getAddonByID(context.extension.id);
- console.log(addon.id);
- //make the addon globally available in the bootstrapped scope
- self.bootstrappedObj.addon = addon;
-
- // add BOOTSTRAP_REASONS to scope
- for (let reason of Object.keys(self.BOOTSTRAP_REASONS)) {
- self.bootstrappedObj[reason] = self.BOOTSTRAP_REASONS[reason];
- }
-
- // Load registered bootstrap scripts and execute its startup() function.
- try {
- if (self.pathToBootstrapScript) Services.scriptloader.loadSubScript(self.pathToBootstrapScript, self.bootstrappedObj, "UTF-8");
- if (self.bootstrappedObj.startup) self.bootstrappedObj.startup.call(self.bootstrappedObj, self.extension.addonData, self.BOOTSTRAP_REASONS[self.extension.startupReason]);
- } catch (e) {
- Components.utils.reportError(e)
- }
-
- }
- }
- };
- }
-
- onShutdown(isAppShutdown) {
- if (isAppShutdown) {
- return; // the application gets unloaded anyway
- }
-
-
- // Execute registered shutdown()
- try {
- if (this.bootstrappedObj.shutdown) {
- this.bootstrappedObj.shutdown(
- this.extension.addonData,
- isAppShutdown
- ? this.BOOTSTRAP_REASONS.APP_SHUTDOWN
- : this.BOOTSTRAP_REASONS.ADDON_DISABLE);
- }
- } catch (e) {
- Components.utils.reportError(e)
- }
-
- if (this.chromeHandle) {
- this.chromeHandle.destruct();
- this.chromeHandle = null;
- }
- // Flush all caches
- Services.obs.notifyObservers(null, "startupcache-invalidate");
- console.log("BootstrapLoader for " + this.extension.id + " unloaded!");
- }
-};
\ No newline at end of file
diff -Nru eas4tbsync-4.11/content/api/BootstrapLoader/schema.json eas4tbsync-4.17/content/api/BootstrapLoader/schema.json
--- eas4tbsync-4.11/content/api/BootstrapLoader/schema.json 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/api/BootstrapLoader/schema.json 1970-01-01 00:00:00.000000000 +0000
@@ -1,61 +0,0 @@
-[
- {
- "namespace": "BootstrapLoader",
- "functions": [
- {
- "name": "registerOptionsPage",
- "type": "function",
- "parameters": [
- {
- "name": "aPath",
- "type": "string",
- "description": "Path to the options page, which should be made accessible in the (legacy) Add-On Options menu."
- }
- ]
- },
- {
- "name": "openOptionsDialog",
- "type": "function",
- "parameters": [
- {
- "name": "windowId",
- "type": "integer",
- "description": "Id of the window the dialog should be opened from."
- }
- ]
- },
- {
- "name": "registerChromeUrl",
- "type": "function",
- "description": "Register folders which should be available as chrome:// urls (as defined in the legacy chrome.manifest)",
- "async": true,
- "parameters": [
- {
- "name": "chromeData",
- "type": "array",
- "items": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "description": "Array of ChromeData Arrays."
- }
- ]
- },
- {
- "name": "registerBootstrapScript",
- "type": "function",
- "description": "Register a bootstrap.js style script",
- "async": true,
- "parameters": [
- {
- "name": "aPath",
- "type": "string",
- "description": "Either the chrome:// path to the script or its relative location from the root of the extension,"
- }
- ]
- }
- ]
- }
-]
\ No newline at end of file
diff -Nru eas4tbsync-4.11/content/bootstrap.js eas4tbsync-4.17/content/bootstrap.js
--- eas4tbsync-4.11/content/bootstrap.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/bootstrap.js 1970-01-01 00:00:00.000000000 +0000
@@ -1,53 +0,0 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-// no need to create namespace, we are in a sandbox
-
-let onInitDoneObserver = {
- observe: async function (aSubject, aTopic, aData) {
- let valid = false;
- try {
- var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
- valid = TbSync.enabled;
- } catch (e) {
- // If this fails, TbSync is not loaded yet and we will get the notification later again.
- }
-
- //load this provider add-on into TbSync
- if (valid) {
- await TbSync.providers.loadProvider(extension, "eas", "chrome://eas4tbsync/content/provider.js");
- }
- }
-}
-
-function startup(data, reason) {
- // Possible reasons: APP_STARTUP, ADDON_ENABLE, ADDON_INSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE.
-
- Services.obs.addObserver(onInitDoneObserver, "tbsync.observer.initialized", false);
-
- // Did we miss the observer?
- onInitDoneObserver.observe();
-}
-
-function shutdown(data, reason) {
- // Possible reasons: APP_STARTUP, ADDON_ENABLE, ADDON_INSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE.
-
- // When the application is shutting down we normally don't have to clean up.
- if (reason == APP_SHUTDOWN) {
- return;
- }
-
- Services.obs.removeObserver(onInitDoneObserver, "tbsync.observer.initialized");
- //unload this provider add-on from TbSync
- try {
- var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
- TbSync.providers.unloadProvider("eas");
- } catch (e) {
- //if this fails, TbSync has been unloaded already and has unloaded this addon as well
- }
-}
diff -Nru eas4tbsync-4.11/content/includes/calendarsync.js eas4tbsync-4.17/content/includes/calendarsync.js
--- eas4tbsync-4.11/content/includes/calendarsync.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/calendarsync.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,422 +1,430 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetters(this, {
- CalAlarm: "resource:///modules/CalAlarm.jsm",
- CalAttachment: "resource:///modules/CalAttachment.jsm",
- CalAttendee: "resource:///modules/CalAttendee.jsm",
- CalEvent: "resource:///modules/CalEvent.jsm",
- CalTodo: "resource:///modules/CalTodo.jsm",
-});
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-const cal = TbSync.lightning.cal;
-const ICAL = TbSync.lightning.ICAL;
-
-var Calendar = {
-
- // --------------------------------------------------------------------------- //
- // Read WBXML and set Thunderbird item
- // --------------------------------------------------------------------------- //
- setThunderbirdItemFromWbxml: function (tbItem, data, id, syncdata, mode = "standard") {
-
- let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
-
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- item.id = id;
- eas.sync.setItemSubject(item, syncdata, data);
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " calendar item", item.title + " (" + id + ")");
-
- eas.sync.setItemLocation(item, syncdata, data);
- eas.sync.setItemCategories(item, syncdata, data);
- eas.sync.setItemBody(item, syncdata, data);
-
- //timezone
- let stdOffset = eas.defaultTimezoneInfo.std.offset;
- let dstOffset = eas.defaultTimezoneInfo.dst.offset;
- let easTZ = new eas.tools.TimeZoneDataStructure();
- if (data.TimeZone) {
- if (data.TimeZone == "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") {
- TbSync.dump("Recieve TZ", "No timezone data received, using local default timezone.");
- } else {
- //load timezone struct into EAS TimeZone object
- easTZ.easTimeZone64 = data.TimeZone;
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Recieve TZ", item.title + easTZ.toString());
- stdOffset = easTZ.utcOffset;
- dstOffset = easTZ.daylightBias + easTZ.utcOffset;
- }
- }
- let timezone = eas.tools.guessTimezoneByStdDstOffset(stdOffset, dstOffset, easTZ.standardName);
-
- if (data.StartTime) {
- let utc = cal.createDateTime(data.StartTime); //format "19800101T000000Z" - UTC
- item.startDate = utc.getInTimezone(timezone);
- if (data.AllDayEvent && data.AllDayEvent == "1") {
- item.startDate.timezone = (cal.dtz && cal.dtz.floating) ? cal.dtz.floating : cal.floating();
- item.startDate.isDate = true;
- }
- }
-
- if (data.EndTime) {
- let utc = cal.createDateTime(data.EndTime);
- item.endDate = utc.getInTimezone(timezone);
- if (data.AllDayEvent && data.AllDayEvent == "1") {
- item.endDate.timezone = (cal.dtz && cal.dtz.floating) ? cal.dtz.floating : cal.floating();
- item.endDate.isDate = true;
- }
- }
-
- //stamp time cannot be set and it is not needed, an updated version is only send to the server, if there was a change, so stamp will be updated
-
-
- //EAS Reminder
- item.clearAlarms();
- if (data.Reminder && data.StartTime) {
- let alarm = new CalAlarm();
- alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
- alarm.offset = cal.createDuration();
- alarm.offset.inSeconds = (0-parseInt(data.Reminder)*60);
- alarm.action ="DISPLAY";
- item.addAlarm(alarm);
-
- let alarmData = cal.alarms.calculateAlarmDate(item, alarm);
- let startDate = cal.createDateTime(data.StartTime);
- let nowDate = eas.tools.getNowUTC();
- if (startDate.compare(nowDate) < 0) {
- // Mark alarm as ACK if in the past.
- item.alarmLastAck = nowDate;
- }
- }
-
- eas.sync.mapEasPropertyToThunderbird ("BusyStatus", "TRANSP", data, item);
- eas.sync.mapEasPropertyToThunderbird ("Sensitivity", "CLASS", data, item);
-
- if (data.ResponseType) {
- //store original EAS value
- item.setProperty("X-EAS-ResponseType", eas.xmltools.checkString(data.ResponseType, "0")); //some server send empty ResponseType ???
- }
-
- //Attendees - remove all Attendees and re-add the ones from XML
- item.removeAllAttendees();
- if (data.Attendees && data.Attendees.Attendee) {
- let att = [];
- if (Array.isArray(data.Attendees.Attendee)) att = data.Attendees.Attendee;
- else att.push(data.Attendees.Attendee);
- for (let i = 0; i < att.length; i++) {
- if (att[i].Email && eas.tools.isString(att[i].Email) && att[i].Name) { //req.
-
- let attendee = new CalAttendee();
-
- //is this attendee the local EAS user?
- let isSelf = (att[i].Email == syncdata.accountData.getAccountProperty("user"));
-
- attendee["id"] = cal.email.prependMailTo(att[i].Email);
- attendee["commonName"] = att[i].Name;
- //default is "FALSE", only if THIS attendee isSelf, use ResponseRequested (we cannot respond for other attendee) - ResponseType is not send back to the server, it is just a local information
- attendee["rsvp"] = (isSelf && data.ResponseRequested) ? "TRUE" : "FALSE";
-
- //not supported in 2.5
- switch (att[i].AttendeeType) {
- case "1": //required
- attendee["role"] = "REQ-PARTICIPANT";
- attendee["userType"] = "INDIVIDUAL";
- break;
- case "2": //optional
- attendee["role"] = "OPT-PARTICIPANT";
- attendee["userType"] = "INDIVIDUAL";
- break;
- default : //resource or unknown
- attendee["role"] = "NON-PARTICIPANT";
- attendee["userType"] = "RESOURCE";
- break;
- }
-
- //not supported in 2.5 - if attendeeStatus is missing, check if this isSelf and there is a ResponseType
- if (att[i].AttendeeStatus)
- attendee["participationStatus"] = eas.sync.MAP_EAS2TB.ATTENDEESTATUS[att[i].AttendeeStatus];
- else if (isSelf && data.ResponseType)
- attendee["participationStatus"] = eas.sync.MAP_EAS2TB.ATTENDEESTATUS[data.ResponseType];
- else
- attendee["participationStatus"] = "NEEDS-ACTION";
-
- // status : [NEEDS-ACTION, ACCEPTED, DECLINED, TENTATIVE, DELEGATED, COMPLETED, IN-PROCESS]
- // rolemap : [REQ-PARTICIPANT, OPT-PARTICIPANT, NON-PARTICIPANT, CHAIR]
- // typemap : [INDIVIDUAL, GROUP, RESOURCE, ROOM]
-
- // Add attendee to event
- item.addAttendee(attendee);
- } else {
- TbSync.eventlog.add("info", syncdata, "Attendee without required name and/or email found. Skipped.");
- }
- }
- }
-
- if (data.OrganizerName && data.OrganizerEmail && eas.tools.isString(data.OrganizerEmail)) {
- //Organizer
- let organizer = new CalAttendee();
- organizer.id = cal.email.prependMailTo(data.OrganizerEmail);
- organizer.commonName = data.OrganizerName;
- organizer.rsvp = "FALSE";
- organizer.role = "CHAIR";
- organizer.userType = null;
- organizer.participationStatus = "ACCEPTED";
- organizer.isOrganizer = true;
- item.organizer = organizer;
- }
-
- eas.sync.setItemRecurrence(item, syncdata, data, timezone);
-
- // BusyStatus is always representing the status of the current user in terms of availability.
- // It has nothing to do with the status of a meeting. The user could be just the organizer, but does not need to attend, so he would be free.
- // The correct map is between BusyStatus and TRANSP (show time as avail, busy, unset)
- // A new event always sets TRANSP to busy, so unset is indeed a good way to store Tentiative
- // However:
- // - EAS Meetingstatus only knows ACTIVE or CANCELLED, but not CONFIRMED or TENTATIVE
- // - TB STATUS has UNSET, CONFIRMED, TENTATIVE, CANCELLED
- // -> Special case: User sets BusyStatus to TENTIATIVE -> TRANSP is unset and also set STATUS to TENTATIVE
- // The TB STATUS is the correct map for EAS Meetingstatus and should be unset, if it is not a meeting EXCEPT if set to TENTATIVE
- let tbStatus = (data.BusyStatus && data.BusyStatus == "1" ? "TENTATIVE" : null);
-
- if (data.MeetingStatus) {
- //store original EAS value
- item.setProperty("X-EAS-MeetingStatus", data.MeetingStatus);
- //bitwise representation for Meeting, Received, Cancelled:
- let M = data.MeetingStatus & 0x1;
- let R = data.MeetingStatus & 0x2;
- let C = data.MeetingStatus & 0x4;
-
- // We can map M+C to TB STATUS (TENTATIVE, CONFIRMED, CANCELLED, unset).
- if (M) {
- if (C) tbStatus = "CANCELLED";
- else if (!tbStatus) tbStatus = "CONFIRMED"; // do not override "TENTIATIVE"
- }
-
- //we can also use the R information, to update our fallbackOrganizerName
- if (!R && data.OrganizerName) syncdata.target.calendar.setProperty("fallbackOrganizerName", data.OrganizerName);
- }
-
- if (tbStatus) item.setProperty("STATUS", tbStatus)
- else item.deleteProperty("STATUS");
-
- //TODO: attachements (needs EAS 16.0!)
- },
-
-
-
-
-
-
-
-
-
- // --------------------------------------------------------------------------- //
- //read TB event and return its data as WBXML
- // --------------------------------------------------------------------------- //
- getWbxmlFromThunderbirdItem: async function (tbItem, syncdata, isException = false) {
- let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
-
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
- let nowDate = new Date();
-
- /*
- * We do not use ghosting, that means, if we do not include a value in CHANGE, it is removed from the server.
- * However, this does not seem to work on all fields. Furthermore, we need to include any (empty) container to blank its childs.
- */
-
- //Order of tags taken from https://msdn.microsoft.com/en-us/library/dn338917(v=exchg.80).aspx
-
- //timezone
- if (!isException) {
- let easTZ = new eas.tools.TimeZoneDataStructure();
-
- //if there is no end and no start (or both are floating) use default timezone info
- let tzInfo = null;
- if (item.startDate && item.startDate.timezone.tzid != "floating") tzInfo = eas.tools.getTimezoneInfo(item.startDate.timezone);
- else if (item.endDate && item.endDate.timezone.tzid != "floating") tzInfo = eas.tools.getTimezoneInfo(item.endDate.timezone);
- if (!tzInfo) tzInfo = eas.defaultTimezoneInfo;
-
- easTZ.utcOffset = tzInfo.std.offset;
- easTZ.standardBias = 0;
- easTZ.daylightBias = tzInfo.dst.offset - tzInfo.std.offset;
-
- easTZ.standardName = eas.ianaToWindowsTimezoneMap.hasOwnProperty(tzInfo.std.displayname) ? eas.ianaToWindowsTimezoneMap[tzInfo.std.displayname] : tzInfo.std.displayname;
- easTZ.daylightName = eas.ianaToWindowsTimezoneMap.hasOwnProperty(tzInfo.dst.displayname) ? eas.ianaToWindowsTimezoneMap[tzInfo.dst.displayname] : tzInfo.dst.displayname;
-
- if (tzInfo.std.switchdate && tzInfo.dst.switchdate) {
- easTZ.standardDate.wMonth = tzInfo.std.switchdate.month;
- easTZ.standardDate.wDay = tzInfo.std.switchdate.weekOfMonth;
- easTZ.standardDate.wDayOfWeek = tzInfo.std.switchdate.dayOfWeek;
- easTZ.standardDate.wHour = tzInfo.std.switchdate.hour;
- easTZ.standardDate.wMinute = tzInfo.std.switchdate.minute;
- easTZ.standardDate.wSecond = tzInfo.std.switchdate.second;
-
- easTZ.daylightDate.wMonth = tzInfo.dst.switchdate.month;
- easTZ.daylightDate.wDay = tzInfo.dst.switchdate.weekOfMonth;
- easTZ.daylightDate.wDayOfWeek = tzInfo.dst.switchdate.dayOfWeek;
- easTZ.daylightDate.wHour = tzInfo.dst.switchdate.hour;
- easTZ.daylightDate.wMinute = tzInfo.dst.switchdate.minute;
- easTZ.daylightDate.wSecond = tzInfo.dst.switchdate.second;
- }
-
- wbxml.atag("TimeZone", easTZ.easTimeZone64);
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Send TZ", item.title + easTZ.toString());
- }
-
- //AllDayEvent (for simplicity, we always send a value)
- wbxml.atag("AllDayEvent", (item.startDate && item.startDate.isDate && item.endDate && item.endDate.isDate) ? "1" : "0");
-
- //Body
- wbxml.append(eas.sync.getItemBody(item, syncdata));
-
- //BusyStatus (Free, Tentative, Busy) is taken from TRANSP (busy, free, unset=tentative)
- //However if STATUS is set to TENTATIVE, overide TRANSP and set BusyStatus to TENTATIVE
- if (item.hasProperty("STATUS") && item.getProperty("STATUS") == "TENTATIVE") {
- wbxml.atag("BusyStatus","1");
- } else {
- wbxml.atag("BusyStatus", eas.sync.mapThunderbirdPropertyToEas("TRANSP", "BusyStatus", item));
- }
-
- //Organizer
- if (!isException) {
- if (item.organizer && item.organizer.commonName) wbxml.atag("OrganizerName", item.organizer.commonName);
- if (item.organizer && item.organizer.id) wbxml.atag("OrganizerEmail", cal.email.removeMailTo(item.organizer.id));
- }
-
- //DtStamp in UTC
- wbxml.atag("DtStamp", item.stampTime ? eas.tools.getIsoUtcString(item.stampTime) : eas.tools.dateToBasicISOString(nowDate));
-
- //EndTime in UTC
- wbxml.atag("EndTime", item.endDate ? eas.tools.getIsoUtcString(item.endDate) : eas.tools.dateToBasicISOString(nowDate));
-
- //Location
- wbxml.atag("Location", (item.hasProperty("location")) ? item.getProperty("location") : "");
-
- //EAS Reminder (TB getAlarms) - at least with zpush blanking by omitting works, horde does not work
- let alarms = item.getAlarms({});
- if (alarms.length>0) {
-
- let reminder = -1;
- if (alarms[0].offset !== null) {
- reminder = 0 - alarms[0].offset.inSeconds/60;
- } else if (item.startDate) {
- let timeDiff =item.startDate.getInTimezone(eas.utcTimezone).subtractDate(alarms[0].alarmDate.getInTimezone(eas.utcTimezone));
- reminder = timeDiff.inSeconds/60;
- TbSync.eventlog.add("info", syncdata, "Converting absolute alarm to relative alarm (not supported).", item.icalString);
- }
- if (reminder >= 0) wbxml.atag("Reminder", reminder.toString());
- else TbSync.eventlog.add("info", syncdata, "Droping alarm after start date (not supported).", item.icalString);
-
- }
-
- //Sensitivity (CLASS)
- wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
-
- //Subject (obmitting these, should remove them from the server - that does not work reliably, so we send blanks)
- wbxml.atag("Subject", (item.title) ? item.title : "");
-
- //StartTime in UTC
- wbxml.atag("StartTime", item.startDate ? eas.tools.getIsoUtcString(item.startDate) : eas.tools.dateToBasicISOString(nowDate));
-
- //UID (limit to 300)
- //each TB event has an ID, which is used as EAS serverId - however there is a second UID in the ApplicationData
- //since we do not have two different IDs to use, we use the same ID
- if (!isException) { //docs say it would be allowed in exception in 2.5, but it does not work, if present
- wbxml.atag("UID", item.id);
- }
- //IMPORTANT in EAS v16 it is no longer allowed to send a UID
- //Only allowed in exceptions in v2.5
-
-
- //EAS MeetingStatus
- // 0 (000) The event is an appointment, which has no attendees.
- // 1 (001) The event is a meeting and the user is the meeting organizer.
- // 3 (011) This event is a meeting, and the user is not the meeting organizer; the meeting was received from someone else.
- // 5 (101) The meeting has been canceled and the user was the meeting organizer.
- // 7 (111) The meeting has been canceled. The user was not the meeting organizer; the meeting was received from someone else
-
- //there are 3 fields; Meeting, Owner, Cancelled
- //M can be reconstructed from #of attendees (looking at the old value is not wise, since it could have been changed)
- //C can be reconstucted from TB STATUS
- //O can be reconstructed by looking at the original value, or (if not present) by comparing EAS ownerID with TB ownerID
-
- let attendees = item.getAttendees();
- //if (!(isException && asversion == "2.5")) { //MeetingStatus is not supported in exceptions in EAS 2.5
- if (!isException) { //Exchange 2010 does not seem to support MeetingStatus at all in exceptions
- if (attendees.length == 0) wbxml.atag("MeetingStatus", "0");
- else {
- //get owner information
- let isReceived = false;
- if (item.hasProperty("X-EAS-MEETINGSTATUS")) isReceived = item.getProperty("X-EAS-MEETINGSTATUS") & 0x2;
- else isReceived = (item.organizer && item.organizer.id && cal.email.removeMailTo(item.organizer.id) != syncdata.accountData.getAccountProperty("user"));
-
- //either 1,3,5 or 7
- if (item.hasProperty("STATUS") && item.getProperty("STATUS") == "CANCELLED") {
- //either 5 or 7
- wbxml.atag("MeetingStatus", (isReceived ? "7" : "5"));
- } else {
- //either 1 or 3
- wbxml.atag("MeetingStatus", (isReceived ? "3" : "1"));
- }
- }
- }
-
- //Attendees
- let TB_responseType = null;
- if (!(isException && asversion == "2.5")) { //attendees are not supported in exceptions in EAS 2.5
- if (attendees.length > 0) { //We should use it instead of countAttendees.value
- wbxml.otag("Attendees");
- for (let attendee of attendees) {
- wbxml.otag("Attendee");
- wbxml.atag("Email", cal.email.removeMailTo(attendee.id));
- wbxml.atag("Name", (attendee.commonName ? attendee.commonName : cal.email.removeMailTo(attendee.id).split("@")[0]));
- if (asversion != "2.5") {
- //it's pointless to send AttendeeStatus,
- // - if we are the owner of a meeting, TB does not have an option to actually set the attendee status (on behalf of an attendee) in the UI
- // - if we are an attendee (of an invite) we cannot and should not set status of other attendees and or own status must be send through a MeetingResponse
- // -> all changes of attendee status are send from the server to us, either via ResponseType or via AttendeeStatus
- //wbxml.atag("AttendeeStatus", eas.sync.MAP_TB2EAS.ATTENDEESTATUS[attendee.participationStatus]);
-
- if (attendee.userType == "RESOURCE" || attendee.userType == "ROOM" || attendee.role == "NON-PARTICIPANT") wbxml.atag("AttendeeType","3");
- else if (attendee.role == "REQ-PARTICIPANT" || attendee.role == "CHAIR") wbxml.atag("AttendeeType","1");
- else wbxml.atag("AttendeeType","2"); //leftovers are optional
- }
- wbxml.ctag();
- }
- wbxml.ctag();
- } else {
- wbxml.atag("Attendees");
- }
- }
-
- //Categories (see https://github.com/jobisoft/TbSync/pull/35#issuecomment-359286374)
- if (!isException) {
- wbxml.append(eas.sync.getItemCategories(item, syncdata));
- }
-
- //recurrent events (implemented by Chris Allan)
- if (!isException) {
- wbxml.append(await eas.sync.getItemRecurrence(item, syncdata));
- }
-
-
- //---------------------------
-
- //TP PRIORITY (9=LOW, 5=NORMAL, 1=HIGH) not mapable to EAS Event
- //TODO: attachements (needs EAS 16.0!)
-
- //https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIAlarm.idl
- //TbSync.dump("ALARM ("+i+")", [, alarms[i].related, alarms[i].repeat, alarms[i].repeatOffset, alarms[i].repeatDate, alarms[i].action].join("|"));
-
- return wbxml.getBytes();
- }
-}
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ CalAlarm: "resource:///modules/CalAlarm.sys.mjs",
+ CalAttachment: "resource:///modules/CalAttachment.sys.mjs",
+ CalAttendee: "resource:///modules/CalAttendee.sys.mjs",
+ CalEvent: "resource:///modules/CalEvent.sys.mjs",
+ CalTodo: "resource:///modules/CalTodo.sys.mjs",
+});
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+const cal = TbSync.lightning.cal;
+const ICAL = TbSync.lightning.ICAL;
+
+var Calendar = {
+
+ // --------------------------------------------------------------------------- //
+ // Read WBXML and set Thunderbird item
+ // --------------------------------------------------------------------------- //
+ setThunderbirdItemFromWbxml: function (tbItem, data, id, syncdata, mode = "standard") {
+
+ let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
+
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ item.id = id;
+ eas.sync.setItemSubject(item, syncdata, data);
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " calendar item", item.title + " (" + id + ")");
+
+ eas.sync.setItemLocation(item, syncdata, data);
+ eas.sync.setItemCategories(item, syncdata, data);
+ eas.sync.setItemBody(item, syncdata, data);
+
+ //timezone
+ let stdOffset = eas.defaultTimezoneInfo.std.offset;
+ let dstOffset = eas.defaultTimezoneInfo.dst.offset;
+ let easTZ = new eas.tools.TimeZoneDataStructure();
+ if (data.TimeZone) {
+ if (data.TimeZone == "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") {
+ TbSync.dump("Recieve TZ", "No timezone data received, using local default timezone.");
+ } else {
+ //load timezone struct into EAS TimeZone object
+ easTZ.easTimeZone64 = data.TimeZone;
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Recieve TZ", item.title + easTZ.toString());
+ stdOffset = easTZ.utcOffset;
+ dstOffset = easTZ.daylightBias + easTZ.utcOffset;
+ }
+ }
+ let timezone = eas.tools.guessTimezoneByStdDstOffset(stdOffset, dstOffset, easTZ.standardName);
+
+ if (data.StartTime) {
+ let utc = cal.createDateTime(data.StartTime); //format "19800101T000000Z" - UTC
+ item.startDate = utc.getInTimezone(timezone);
+ if (data.AllDayEvent && data.AllDayEvent == "1") {
+ item.startDate.timezone = (cal.dtz && cal.dtz.floating) ? cal.dtz.floating : cal.floating();
+ item.startDate.isDate = true;
+ }
+ }
+
+ if (data.EndTime) {
+ let utc = cal.createDateTime(data.EndTime);
+ item.endDate = utc.getInTimezone(timezone);
+ if (data.AllDayEvent && data.AllDayEvent == "1") {
+ item.endDate.timezone = (cal.dtz && cal.dtz.floating) ? cal.dtz.floating : cal.floating();
+ item.endDate.isDate = true;
+ }
+ }
+
+ //stamp time cannot be set and it is not needed, an updated version is only send to the server, if there was a change, so stamp will be updated
+
+
+ //EAS Reminder
+ item.clearAlarms();
+ if (data.Reminder && data.StartTime) {
+ let alarm = new CalAlarm();
+ alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
+ alarm.offset = cal.createDuration();
+ alarm.offset.inSeconds = (0 - parseInt(data.Reminder) * 60);
+ alarm.action = "DISPLAY";
+ item.addAlarm(alarm);
+
+ let alarmData = cal.alarms.calculateAlarmDate(item, alarm);
+ let startDate = cal.createDateTime(data.StartTime);
+ let nowDate = eas.tools.getNowUTC();
+ if (startDate.compare(nowDate) < 0) {
+ // Mark alarm as ACK if in the past.
+ item.alarmLastAck = nowDate;
+ }
+ }
+
+ eas.sync.mapEasPropertyToThunderbird("BusyStatus", "TRANSP", data, item);
+ eas.sync.mapEasPropertyToThunderbird("Sensitivity", "CLASS", data, item);
+
+ if (data.ResponseType) {
+ //store original EAS value
+ item.setProperty("X-EAS-ResponseType", eas.xmltools.checkString(data.ResponseType, "0")); //some server send empty ResponseType ???
+ }
+
+ //Attendees - remove all Attendees and re-add the ones from XML
+ item.removeAllAttendees();
+ if (data.Attendees && data.Attendees.Attendee) {
+ let att = [];
+ if (Array.isArray(data.Attendees.Attendee)) att = data.Attendees.Attendee;
+ else att.push(data.Attendees.Attendee);
+ for (let i = 0; i < att.length; i++) {
+ if (att[i].Email && eas.tools.isString(att[i].Email) && att[i].Name) { //req.
+
+ let attendee = new CalAttendee();
+
+ //is this attendee the local EAS user?
+ let isSelf = (att[i].Email == syncdata.accountData.getAccountProperty("user"));
+
+ attendee["id"] = cal.email.prependMailTo(att[i].Email);
+ attendee["commonName"] = att[i].Name;
+ //default is "FALSE", only if THIS attendee isSelf, use ResponseRequested (we cannot respond for other attendee) - ResponseType is not send back to the server, it is just a local information
+ attendee["rsvp"] = (isSelf && data.ResponseRequested) ? "TRUE" : "FALSE";
+
+ //not supported in 2.5
+ switch (att[i].AttendeeType) {
+ case "1": //required
+ attendee["role"] = "REQ-PARTICIPANT";
+ attendee["userType"] = "INDIVIDUAL";
+ break;
+ case "2": //optional
+ attendee["role"] = "OPT-PARTICIPANT";
+ attendee["userType"] = "INDIVIDUAL";
+ break;
+ default: //resource or unknown
+ attendee["role"] = "NON-PARTICIPANT";
+ attendee["userType"] = "RESOURCE";
+ break;
+ }
+
+ //not supported in 2.5 - if attendeeStatus is missing, check if this isSelf and there is a ResponseType
+ if (att[i].AttendeeStatus)
+ attendee["participationStatus"] = eas.sync.MAP_EAS2TB.ATTENDEESTATUS[att[i].AttendeeStatus];
+ else if (isSelf && data.ResponseType)
+ attendee["participationStatus"] = eas.sync.MAP_EAS2TB.ATTENDEESTATUS[data.ResponseType];
+ else
+ attendee["participationStatus"] = "NEEDS-ACTION";
+
+ // status : [NEEDS-ACTION, ACCEPTED, DECLINED, TENTATIVE, DELEGATED, COMPLETED, IN-PROCESS]
+ // rolemap : [REQ-PARTICIPANT, OPT-PARTICIPANT, NON-PARTICIPANT, CHAIR]
+ // typemap : [INDIVIDUAL, GROUP, RESOURCE, ROOM]
+
+ // Add attendee to event
+ item.addAttendee(attendee);
+ } else {
+ TbSync.eventlog.add("info", syncdata, "Attendee without required name and/or email found. Skipped.");
+ }
+ }
+ }
+
+ if (data.OrganizerName && data.OrganizerEmail && eas.tools.isString(data.OrganizerEmail)) {
+ //Organizer
+ let organizer = new CalAttendee();
+ organizer.id = cal.email.prependMailTo(data.OrganizerEmail);
+ organizer.commonName = data.OrganizerName;
+ organizer.rsvp = "FALSE";
+ organizer.role = "CHAIR";
+ organizer.userType = null;
+ organizer.participationStatus = "ACCEPTED";
+ organizer.isOrganizer = true;
+ item.organizer = organizer;
+ }
+
+ eas.sync.setItemRecurrence(item, syncdata, data, timezone);
+
+ // BusyStatus is always representing the status of the current user in terms of availability.
+ // It has nothing to do with the status of a meeting. The user could be just the organizer, but does not need to attend, so he would be free.
+ // The correct map is between BusyStatus and TRANSP (show time as avail, busy, unset)
+ // A new event always sets TRANSP to busy, so unset is indeed a good way to store Tentiative
+ // However:
+ // - EAS Meetingstatus only knows ACTIVE or CANCELLED, but not CONFIRMED or TENTATIVE
+ // - TB STATUS has UNSET, CONFIRMED, TENTATIVE, CANCELLED
+ // -> Special case: User sets BusyStatus to TENTIATIVE -> TRANSP is unset and also set STATUS to TENTATIVE
+ // The TB STATUS is the correct map for EAS Meetingstatus and should be unset, if it is not a meeting EXCEPT if set to TENTATIVE
+ let tbStatus = (data.BusyStatus && data.BusyStatus == "1" ? "TENTATIVE" : null);
+
+ if (data.MeetingStatus) {
+ //store original EAS value
+ item.setProperty("X-EAS-MeetingStatus", data.MeetingStatus);
+ //bitwise representation for Meeting, Received, Cancelled:
+ let M = data.MeetingStatus & 0x1;
+ let R = data.MeetingStatus & 0x2;
+ let C = data.MeetingStatus & 0x4;
+
+ // We can map M+C to TB STATUS (TENTATIVE, CONFIRMED, CANCELLED, unset).
+ if (M) {
+ if (C) tbStatus = "CANCELLED";
+ else if (!tbStatus) tbStatus = "CONFIRMED"; // do not override "TENTIATIVE"
+ }
+
+ //we can also use the R information, to update our fallbackOrganizerName
+ if (!R && data.OrganizerName) syncdata.target.calendar.setProperty("fallbackOrganizerName", data.OrganizerName);
+ }
+
+ if (tbStatus) item.setProperty("STATUS", tbStatus)
+ else item.deleteProperty("STATUS");
+
+ //TODO: attachements (needs EAS 16.0!)
+ },
+
+
+
+
+
+
+
+
+
+ // --------------------------------------------------------------------------- //
+ //read TB event and return its data as WBXML
+ // --------------------------------------------------------------------------- //
+ getWbxmlFromThunderbirdItem: async function (tbItem, syncdata, isException = false) {
+ let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
+
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
+ let nowDate = new Date();
+
+ /*
+ * We do not use ghosting, that means, if we do not include a value in CHANGE, it is removed from the server.
+ * However, this does not seem to work on all fields. Furthermore, we need to include any (empty) container to blank its childs.
+ */
+
+ //Order of tags taken from https://msdn.microsoft.com/en-us/library/dn338917(v=exchg.80).aspx
+
+ //timezone
+ if (!isException) {
+ let easTZ = new eas.tools.TimeZoneDataStructure();
+
+ //if there is no end and no start (or both are floating) use default timezone info
+ let tzInfo = null;
+ if (item.startDate && item.startDate.timezone.tzid != "floating") tzInfo = eas.tools.getTimezoneInfo(item.startDate.timezone);
+ else if (item.endDate && item.endDate.timezone.tzid != "floating") tzInfo = eas.tools.getTimezoneInfo(item.endDate.timezone);
+ if (!tzInfo) tzInfo = eas.defaultTimezoneInfo;
+
+ easTZ.utcOffset = tzInfo.std.offset;
+ easTZ.standardBias = 0;
+ easTZ.daylightBias = tzInfo.dst.offset - tzInfo.std.offset;
+
+ easTZ.standardName = eas.ianaToWindowsTimezoneMap.hasOwnProperty(tzInfo.std.displayname) ? eas.ianaToWindowsTimezoneMap[tzInfo.std.displayname] : tzInfo.std.displayname;
+ easTZ.daylightName = eas.ianaToWindowsTimezoneMap.hasOwnProperty(tzInfo.dst.displayname) ? eas.ianaToWindowsTimezoneMap[tzInfo.dst.displayname] : tzInfo.dst.displayname;
+
+ if (tzInfo.std.switchdate && tzInfo.dst.switchdate) {
+ easTZ.standardDate.wMonth = tzInfo.std.switchdate.month;
+ easTZ.standardDate.wDay = tzInfo.std.switchdate.weekOfMonth;
+ easTZ.standardDate.wDayOfWeek = tzInfo.std.switchdate.dayOfWeek;
+ easTZ.standardDate.wHour = tzInfo.std.switchdate.hour;
+ easTZ.standardDate.wMinute = tzInfo.std.switchdate.minute;
+ easTZ.standardDate.wSecond = tzInfo.std.switchdate.second;
+
+ easTZ.daylightDate.wMonth = tzInfo.dst.switchdate.month;
+ easTZ.daylightDate.wDay = tzInfo.dst.switchdate.weekOfMonth;
+ easTZ.daylightDate.wDayOfWeek = tzInfo.dst.switchdate.dayOfWeek;
+ easTZ.daylightDate.wHour = tzInfo.dst.switchdate.hour;
+ easTZ.daylightDate.wMinute = tzInfo.dst.switchdate.minute;
+ easTZ.daylightDate.wSecond = tzInfo.dst.switchdate.second;
+ }
+
+ wbxml.atag("TimeZone", easTZ.easTimeZone64);
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Send TZ", item.title + easTZ.toString());
+ }
+
+ //AllDayEvent (for simplicity, we always send a value)
+ wbxml.atag("AllDayEvent", (item.startDate && item.startDate.isDate && item.endDate && item.endDate.isDate) ? "1" : "0");
+
+ //Body
+ wbxml.append(eas.sync.getItemBody(item, syncdata));
+
+ //BusyStatus (Free, Tentative, Busy) is taken from TRANSP (busy, free, unset=tentative)
+ //However if STATUS is set to TENTATIVE, overide TRANSP and set BusyStatus to TENTATIVE
+ if (item.hasProperty("STATUS") && item.getProperty("STATUS") == "TENTATIVE") {
+ wbxml.atag("BusyStatus", "1");
+ } else {
+ wbxml.atag("BusyStatus", eas.sync.mapThunderbirdPropertyToEas("TRANSP", "BusyStatus", item));
+ }
+
+ //Organizer
+ if (!isException) {
+ if (item.organizer && item.organizer.commonName) wbxml.atag("OrganizerName", item.organizer.commonName);
+ if (item.organizer && item.organizer.id) wbxml.atag("OrganizerEmail", cal.email.removeMailTo(item.organizer.id));
+ }
+
+ //DtStamp in UTC
+ wbxml.atag("DtStamp", item.stampTime ? eas.tools.getIsoUtcString(item.stampTime) : eas.tools.dateToBasicISOString(nowDate));
+
+ //EndTime in UTC
+ wbxml.atag("EndTime", item.endDate ? eas.tools.getIsoUtcString(item.endDate) : eas.tools.dateToBasicISOString(nowDate));
+
+ //Location
+ wbxml.atag("Location", (item.hasProperty("location")) ? item.getProperty("location") : "");
+
+ //EAS Reminder (TB getAlarms) - at least with zpush blanking by omitting works, horde does not work
+ let alarms = item.getAlarms({});
+ if (alarms.length > 0) {
+
+ let reminder = -1;
+ if (alarms[0].offset !== null) {
+ reminder = 0 - alarms[0].offset.inSeconds / 60;
+ } else if (item.startDate) {
+ let timeDiff = item.startDate.getInTimezone(eas.utcTimezone).subtractDate(alarms[0].alarmDate.getInTimezone(eas.utcTimezone));
+ reminder = timeDiff.inSeconds / 60;
+ TbSync.eventlog.add("info", syncdata, "Converting absolute alarm to relative alarm (not supported).", item.icalString);
+ }
+ if (reminder >= 0) wbxml.atag("Reminder", reminder.toString());
+ else TbSync.eventlog.add("info", syncdata, "Droping alarm after start date (not supported).", item.icalString);
+
+ }
+
+ //Sensitivity (CLASS)
+ wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
+
+ //Subject (obmitting these, should remove them from the server - that does not work reliably, so we send blanks)
+ wbxml.atag("Subject", (item.title) ? item.title : "");
+
+ //StartTime in UTC
+ wbxml.atag("StartTime", item.startDate ? eas.tools.getIsoUtcString(item.startDate) : eas.tools.dateToBasicISOString(nowDate));
+
+ //UID (limit to 300)
+ //each TB event has an ID, which is used as EAS serverId - however there is a second UID in the ApplicationData
+ //since we do not have two different IDs to use, we use the same ID
+ if (!isException) { //docs say it would be allowed in exception in 2.5, but it does not work, if present
+ wbxml.atag("UID", item.id);
+ }
+ //IMPORTANT in EAS v16 it is no longer allowed to send a UID
+ //Only allowed in exceptions in v2.5
+
+
+ //EAS MeetingStatus
+ // 0 (000) The event is an appointment, which has no attendees.
+ // 1 (001) The event is a meeting and the user is the meeting organizer.
+ // 3 (011) This event is a meeting, and the user is not the meeting organizer; the meeting was received from someone else.
+ // 5 (101) The meeting has been canceled and the user was the meeting organizer.
+ // 7 (111) The meeting has been canceled. The user was not the meeting organizer; the meeting was received from someone else
+
+ //there are 3 fields; Meeting, Owner, Cancelled
+ //M can be reconstructed from #of attendees (looking at the old value is not wise, since it could have been changed)
+ //C can be reconstucted from TB STATUS
+ //O can be reconstructed by looking at the original value, or (if not present) by comparing EAS ownerID with TB ownerID
+
+ let attendees = item.getAttendees();
+ //if (!(isException && asversion == "2.5")) { //MeetingStatus is not supported in exceptions in EAS 2.5
+ if (!isException) { //Exchange 2010 does not seem to support MeetingStatus at all in exceptions
+ if (attendees.length == 0) wbxml.atag("MeetingStatus", "0");
+ else {
+ //get owner information
+ let isReceived = false;
+ if (item.hasProperty("X-EAS-MEETINGSTATUS")) isReceived = item.getProperty("X-EAS-MEETINGSTATUS") & 0x2;
+ else isReceived = (item.organizer && item.organizer.id && cal.email.removeMailTo(item.organizer.id) != syncdata.accountData.getAccountProperty("user"));
+
+ //either 1,3,5 or 7
+ if (item.hasProperty("STATUS") && item.getProperty("STATUS") == "CANCELLED") {
+ //either 5 or 7
+ wbxml.atag("MeetingStatus", (isReceived ? "7" : "5"));
+ } else {
+ //either 1 or 3
+ wbxml.atag("MeetingStatus", (isReceived ? "3" : "1"));
+ }
+ }
+ }
+
+ //Attendees
+ let TB_responseType = null;
+ if (!(isException && asversion == "2.5")) { //attendees are not supported in exceptions in EAS 2.5
+ if (attendees.length > 0) { //We should use it instead of countAttendees.value
+ wbxml.otag("Attendees");
+ for (let attendee of attendees) {
+ wbxml.otag("Attendee");
+ wbxml.atag("Email", cal.email.removeMailTo(attendee.id));
+ wbxml.atag("Name", (attendee.commonName ? attendee.commonName : cal.email.removeMailTo(attendee.id).split("@")[0]));
+ if (asversion != "2.5") {
+ //it's pointless to send AttendeeStatus,
+ // - if we are the owner of a meeting, TB does not have an option to actually set the attendee status (on behalf of an attendee) in the UI
+ // - if we are an attendee (of an invite) we cannot and should not set status of other attendees and or own status must be send through a MeetingResponse
+ // -> all changes of attendee status are send from the server to us, either via ResponseType or via AttendeeStatus
+ //wbxml.atag("AttendeeStatus", eas.sync.MAP_TB2EAS.ATTENDEESTATUS[attendee.participationStatus]);
+
+ if (attendee.userType == "RESOURCE" || attendee.userType == "ROOM" || attendee.role == "NON-PARTICIPANT") wbxml.atag("AttendeeType", "3");
+ else if (attendee.role == "REQ-PARTICIPANT" || attendee.role == "CHAIR") wbxml.atag("AttendeeType", "1");
+ else wbxml.atag("AttendeeType", "2"); //leftovers are optional
+ }
+ wbxml.ctag();
+ }
+ wbxml.ctag();
+ } else {
+ wbxml.atag("Attendees");
+ }
+ }
+
+ //Categories (see https://github.com/jobisoft/TbSync/pull/35#issuecomment-359286374)
+ if (!isException) {
+ wbxml.append(eas.sync.getItemCategories(item, syncdata));
+ }
+
+ //recurrent events (implemented by Chris Allan)
+ if (!isException) {
+ wbxml.append(await eas.sync.getItemRecurrence(item, syncdata));
+ }
+
+
+ //---------------------------
+
+ //TP PRIORITY (9=LOW, 5=NORMAL, 1=HIGH) not mapable to EAS Event
+ //TODO: attachements (needs EAS 16.0!)
+
+ //https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIAlarm.idl
+ //TbSync.dump("ALARM ("+i+")", [, alarms[i].related, alarms[i].repeat, alarms[i].repeatOffset, alarms[i].repeatDate, alarms[i].action].join("|"));
+
+ return wbxml.getBytes();
+ }
+}
diff -Nru eas4tbsync-4.11/content/includes/contactsync.js eas4tbsync-4.17/content/includes/contactsync.js
--- eas4tbsync-4.11/content/includes/contactsync.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/contactsync.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,551 +1,558 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
- "use strict";
-
- var { XPCOMUtils } = ChromeUtils.import(
- "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-XPCOMUtils.defineLazyModuleGetters(this, {
- newUID: "resource:///modules/AddrBookUtils.jsm",
- AddrBookCard: "resource:///modules/AddrBookCard.jsm",
- BANISHED_PROPERTIES: "resource:///modules/VCardUtils.jsm",
- VCardProperties: "resource:///modules/VCardUtils.jsm",
- VCardPropertyEntry: "resource:///modules/VCardUtils.jsm",
- VCardUtils: "resource:///modules/VCardUtils.jsm",
-});
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-var { MailServices } = ChromeUtils.import("resource:///modules/MailServices.jsm");
-
-const eas = TbSync.providers.eas;
-
-var Contacts = {
-
- // Remove if migration code is removed.
- arrayFromString: function (stringValue) {
- let arrayValue = [];
- if (stringValue.trim().length>0) arrayValue = stringValue.trim().split("\u001A").filter(String);
- return arrayValue;
- },
-
- /* The following TB properties are not synced to the server:
- - only one WebPage
- - more than 3 emails
- - more than one fax, pager, mobile, work, home
- - position (in org)
- */
-
- vcard_array_fields : {
- n : 5,
- adr : 7,
- org : 2
- },
-
- map_EAS_properties_to_vCard: revision => ({
- FileAs: {item: "fn", type: "text", params: {}}, /* DisplayName */
-
- Birthday: {item: "bday", type: "date", params: {}},
- Anniversary: {item: "anniversary", type: "date", params: {}},
-
- LastName: {item: "n", type: "text", params: {}, index: 0},
- FirstName: {item: "n", type: "text", params: {}, index: 1},
- MiddleName: {item: "n", type: "text", params: {}, index: 2},
- Title: {item: "n", type: "text", params: {}, index: 3},
- Suffix: {item: "n", type: "text", params: {}, index: 4},
-
- Notes: {item: "note", type: "text", params: {}},
-
- // What should we do with Email 4+?
- // EAS does not have the concept of home/work for emails. Define matchAll
- // to not use params for finding the correct entry. They will come back as
- // "other".
- Email1Address: {item: "email", type: "text", entry: 0, matchAll: true, params: {}},
- Email2Address: {item: "email", type: "text", entry: 1, matchAll: true, params: {}},
- Email3Address: {item: "email", type: "text", entry: 2, matchAll: true, params: {}},
-
- // EAS does not have the concept of home/work for WebPage. Define matchAll
- // to not use params for finding the correct entry. It will come back as
- // "other".
- WebPage: {item: "url", type: "text", matchAll: true, params: {}},
-
- CompanyName: {item: "org", type: "text", params: {}, index: revision < 2 ? 1 : 0}, /* Company */
- Department: {item: "org", type: "text", params: {}, index: revision < 2 ? 0 : 1}, /* Department */
- JobTitle: { item: "title", type: "text", params: {} }, /* JobTitle */
-
- MobilePhoneNumber: { item: "tel", type: "text", params: {type: "cell" }},
- PagerNumber: { item: "tel", type: "text", params: {type: "pager" }},
- HomeFaxNumber: { item: "tel", type: "text", params: {type: "fax" }},
- // If home phone is defined, use that, otherwise use unspecified phone
- // Note: This must be exclusive (no other field may use home/unspecified)
- // except if entry is specified.
- HomePhoneNumber: { item: "tel", type: "text", params: {type: "home"}, fallbackParams: [{}]},
- BusinessPhoneNumber: { item: "tel", type: "text", params: {type: "work"}},
- Home2PhoneNumber: { item: "tel", type: "text", params: {type: "home"}, entry: 1 },
- Business2PhoneNumber: { item: "tel", type: "text", params: {type: "work"}, entry: 1 },
-
- HomeAddressStreet: {item: "adr", type: "text", params: {type: "home"}, index: 2}, // needs special handling
- HomeAddressCity: {item: "adr", type: "text", params: {type: "home"}, index: 3},
- HomeAddressState: {item: "adr", type: "text", params: {type: "home"}, index: 4},
- HomeAddressPostalCode: {item: "adr", type: "text", params: {type: "home"}, index: 5},
- HomeAddressCountry: {item: "adr", type: "text", params: {type: "home"}, index: 6},
-
- BusinessAddressStreet: {item: "adr", type: "text", params: {type: "work"}, index: 2}, // needs special handling
- BusinessAddressCity: {item: "adr", type: "text", params: {type: "work"}, index: 3},
- BusinessAddressState: {item: "adr", type: "text", params: {type: "work"}, index: 4},
- BusinessAddressPostalCode: {item: "adr", type: "text", params: {type: "work"}, index: 5},
- BusinessAddressCountry: {item: "adr", type: "text", params: {type: "work"}, index: 6},
-
- OtherAddressStreet: {item: "adr", type: "text", params: {}, index: 2}, // needs special handling
- OtherAddressCity: {item: "adr", type: "text", params: {}, index: 3},
- OtherAddressState: {item: "adr", type: "text", params: {}, index: 4},
- OtherAddressPostalCode: {item: "adr", type: "text", params: {}, index: 5},
- OtherAddressCountry: {item: "adr", type: "text", params: {}, index: 6},
-
- // Misusing this EAS field, so that "Custom1" is saved to the server.
- OfficeLocation: {item: "x-custom1", type: "text", params: {}},
-
- Picture: {item: "photo", params: {}, type: "uri"},
-
- // TB shows them as undefined, but showing them might be better, than not. Use a prefix.
- AssistantPhoneNumber: { item: "tel", type: "text", params: {type: "Assistant"}, prefix: true},
- CarPhoneNumber: { item: "tel", type: "text", params: {type: "Car"}, prefix: true},
- RadioPhoneNumber: { item: "tel", type: "text", params: {type: "Radio"}, prefix: true},
- BusinessFaxNumber: { item: "tel", type: "text", params: {type: "WorkFax"}, prefix: true},
- }),
-
- map_EAS_properties_to_vCard_set2 : {
- NickName: {item: "nickname", type: "text", params: {} },
- // Misusing these EAS fields, so that "Custom2,3,4" is saved to the server.
- CustomerId: {item: "x-custom2", type: "text", params: {}},
- GovernmentId: {item: "x-custom3", type: "text", params: {}},
- AccountName: {item: "x-custom4", type: "text", params: {}},
-
- IMAddress: {item: "impp", type: "text", params: {} },
- IMAddress2: {item: "impp", type: "text", params: {}, entry: 1 },
- IMAddress3: {item: "impp", type: "text", params: {}, entry: 2 },
-
- CompanyMainPhone: { item: "tel", type: "text", params: {type: "Company"}, prefix: true},
- },
-
- // There are currently no TB fields for these values, TbSync will store (and
- // resend) them, but will not allow to view/edit.
- unused_EAS_properties: [
- "Alias", //pseudo field
- "WeightedRank", //pseudo field
- "YomiCompanyName", //japanese phonetic equivalent
- "YomiFirstName", //japanese phonetic equivalent
- "YomiLastName", //japanese phonetic equivalent
- "CompressedRTF",
- "MMS",
- // Former custom EAS fields, no longer added to UI after 102.
- "ManagerName",
- "AssistantName",
- "Spouse",
- ],
-
- // Normalize a parameters entry, to be able to find matching existing
- // entries. If we want to be less restrictive, we need to check if all
- // the requested values exist. But we should be the only one who sets
- // the vCard props, so it should be safe. Except someone moves a contact.
- // Should we prevent that via a vendor id in the vcard?
- normalizeParameters: function (unordered) {
- return JSON.stringify(
- Object.keys(unordered).map(e => `${e}`.toLowerCase()).sort().reduce(
- (obj, key) => {
- obj[key] = `${unordered[key]}`.toLowerCase();
- return obj;
- },
- {}
- )
- );
- },
-
- getValue: function (vCardProperties, vCard_property) {
- let parameters = [vCard_property.params];
- if (vCard_property.fallbackParams) {
- parameters.push(...vCard_property.fallbackParams);
- }
- let entries;
- for (let normalizedParams of parameters.map(this.normalizeParameters)) {
- // If no params set, do not filter, otherwise filter for exact match.
- entries = vCardProperties.getAllEntries(vCard_property.item)
- .filter(e => vCard_property.matchAll || normalizedParams == this.normalizeParameters(e.params));
- if (entries.length > 0) {
- break;
- }
- }
-
- // Which entry should we take?
- let entryNr = vCard_property.entry || 0;
- if (entries[entryNr]) {
- let value;
- if (vCard_property.item == "org" && !Array.isArray(entries[entryNr].value)) {
- // The org field sometimes comes back as a string (then it is Company),
- // even though it should be an array [Department,Company]
- value = vCard_property.index == 1 ? entries[entryNr].value : "";
- } else if (this.vcard_array_fields[vCard_property.item]) {
- if (!Array.isArray(entries[entryNr].value)) {
- // If the returned value is a single string, return it only
- // when index 0 is requested, otherwise return nothing.
- value = vCard_property.index == 0 ? entries[entryNr].value : "";
- } else {
- value = entries[entryNr].value[vCard_property.index];
- }
- } else {
- value = entries[entryNr].value;
- }
-
- if (value) {
- if (vCard_property.prefix && value.startsWith(`${vCard_property.params.type}: `)) {
- return value.substring(`${vCard_property.params.type}: `.length);
- }
- return value;
- }
- }
- return "";
- },
-
- /**
- * Reads a DOM File and returns a Promise for its dataUrl.
- *
- * @param {File} file
- * @returns {string}
- */
- getDataUrl(file) {
- return new Promise((resolve, reject) => {
- var reader = new FileReader();
- reader.readAsDataURL(file);
- reader.onload = function() {
- resolve(reader.result);
- };
- reader.onerror = function(error) {
- resolve("");
- };
- });
- },
-
-
-
- // --------------------------------------------------------------------------- //
- // Read WBXML and set Thunderbird item
- // --------------------------------------------------------------------------- //
- setThunderbirdItemFromWbxml: function (abItem, data, id, syncdata, mode = "standard") {
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- let revision = parseInt(syncdata.target._directory.getStringValue("tbSyncRevision","1"), 10);
- let map_EAS_properties_to_vCard = this.map_EAS_properties_to_vCard(revision);
-
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " contact item", id);
-
- // Make sure we are dealing with a vCard, so we can update the card just
- // by updating its vCardProperties.
- if (!abItem._card.supportsVCard) {
- // This is an older card??
- throw new Error("It looks like you are trying to sync a TB91 sync state. Does not work.");
- }
- let vCardProperties = abItem._card.vCardProperties
- abItem.primaryKey = id;
-
- // Loop over all known EAS properties (two EAS sets Contacts and Contacts2).
- for (let set=0; set < 2; set++) {
- let properties = (set == 0) ? this.EAS_properties : this.EAS_properties2;
-
- for (let EAS_property of properties) {
- let vCard_property = (set == 0) ? map_EAS_properties_to_vCard[EAS_property] : this.map_EAS_properties_to_vCard_set2[EAS_property];
- let value;
- switch (EAS_property) {
- case "Notes":
- if (asversion == "2.5") {
- value = eas.xmltools.checkString(data.Body);
- } else if (data.Body && data.Body.Data) {
- value = eas.xmltools.checkString(data.Body.Data);
- }
- break;
-
- default:
- value = eas.xmltools.checkString(data[EAS_property]);
- }
-
- let normalizedParams = this.normalizeParameters(vCard_property.params)
- let entries = vCardProperties.getAllEntries(vCard_property.item)
- .filter(e => vCard_property.matchAll || normalizedParams == this.normalizeParameters(e.params));
- // Which entry should we update? Add empty entries, if the requested entry number
- // does not yet exist.
- let entryNr = vCard_property.entry || 0;
- while (entries.length <= entryNr) {
- let newEntry = new VCardPropertyEntry(
- vCard_property.item,
- vCard_property.params,
- vCard_property.type,
- this.vcard_array_fields[vCard_property.item]
- ? new Array(this.vcard_array_fields[vCard_property.item]).fill("")
- : ""
- );
- vCardProperties.addEntry(newEntry);
- entries = vCardProperties.getAllEntries(vCard_property.item);
- entryNr = entries.length - 1;
- }
-
- // Is this property part of the send data?
- if (value) {
- // Do we need to manipulate the value?
- switch (EAS_property) {
- case "Picture":
- value = `data:image/jpeg;base64,${eas.xmltools.nodeAsArray(data.Picture)[0]}`; //Kerio sends Picture as container
- break;
-
- case "Birthday":
- case "Anniversary":
- let dateObj = new Date(value);
- value = dateObj.toISOString().substr(0, 10);
- break;
-
- case "Email1Address":
- case "Email2Address":
- case "Email3Address":
- let parsedInput = MailServices.headerParser.makeFromDisplayAddress(value);
- let fixedValue = (parsedInput && parsedInput[0] && parsedInput[0].email) ? parsedInput[0].email : value;
- if (fixedValue != value) {
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Parsing email display string via RFC 2231 and RFC 2047 ("+EAS_property+")", value + " -> " + fixedValue);
- value = fixedValue;
- }
- break;
-
- case "HomeAddressStreet":
- case "BusinessAddressStreet":
- case "OtherAddressStreet":
- // Thunderbird accepts an array in the vCardProperty of the 2nd index of the adr field.
- let seperator = String.fromCharCode(syncdata.accountData.getAccountProperty("seperator")); // options are 44 (,) or 10 (\n)
- value = value.split(seperator);
- break;
- }
-
- // Add a typePrefix for fields unknown to TB (better: TB should use the type itself).
- if (vCard_property.prefix && !value.startsWith(`${vCard_property.params.type}: `)) {
- value = `${vCard_property.params.type}: ${value}`;
- }
-
- // Is this an array value?
- if (this.vcard_array_fields[vCard_property.item]) {
- // Make sure this is an array.
- if (!Array.isArray(entries[entryNr].value)) {
- let arr = new Array(this.vcard_array_fields[vCard_property.item]).fill("");
- arr[0] = entries[entryNr].value;
- entries[entryNr].value = arr;
- }
- entries[entryNr].value[vCard_property.index] = value;
- } else {
- entries[entryNr].value = value;
- }
- } else {
- if (this.vcard_array_fields[vCard_property.item]) {
- // Make sure this is an array.
- if (!Array.isArray(entries[entryNr].value)) {
- let arr = new Array(this.vcard_array_fields[vCard_property.item]).fill("");
- arr[0] = entries[entryNr].value;
- entries[entryNr].value = arr;
- }
- entries[entryNr].value[vCard_property.index] = "";
- } else {
- entries[entryNr].value = "";
- }
- }
- }
- }
-
- // Take care of categories.
- if (data["Categories"] && data["Categories"]["Category"]) {
- let categories = Array.isArray(data["Categories"]["Category"])
- ? data["Categories"]["Category"]
- : [data["Categories"]["Category"]];
- vCardProperties.clearValues("categories");
- vCardProperties.addValue("categories", categories);
- // Migration code, remove once no longer needed.
- abItem.setProperty("Categories", "");
- }
-
- // Take care of children, stored in contacts property bag.
- if (data["Children"] && data["Children"]["Child"]) {
- let children = Array.isArray(data["Children"]["Child"])
- ? data["Children"]["Child"]
- : [data["Children"]["Child"]];
- abItem.setProperty("Children", JSON.stringify(children));
- }
-
- // Take care of un-mappable EAS options, which are stored in the contacts
- // property bag.
- for (let i=0; i < this.unused_EAS_properties.length; i++) {
- if (data[this.unused_EAS_properties[i]]) abItem.setProperty("EAS-" + this.unused_EAS_properties[i], data[this.unused_EAS_properties[i]]);
- }
-
- // Remove all entries, which are marked for deletion.
- vCardProperties.entries = vCardProperties.entries.filter(e => Array.isArray(e.value) ? e.value.some(a => a != "") : e.value != "");
-
- // Further manipulations (a few getters are still usable \o/).
- if (syncdata.accountData.getAccountProperty("displayoverride")) {
- abItem._card.displayName = abItem._card.firstName + " " + abItem._card.lastName;
- if (abItem._card.displayName == " " ) {
- let company = (vCardProperties.getFirstValue("org") || [""])[0];
- abItem._card.displayName = company || abItem._card.primaryEmail
- }
- }
- },
-
-
-
-
- // --------------------------------------------------------------------------- //
- //read TB event and return its data as WBXML
- // --------------------------------------------------------------------------- //
- getWbxmlFromThunderbirdItem: async function (abItem, syncdata, isException = false) {
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- let revision = parseInt(syncdata.target._directory.getStringValue("tbSyncRevision","1"), 10);
- let map_EAS_properties_to_vCard = this.map_EAS_properties_to_vCard(revision);
-
- let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
- let nowDate = new Date();
-
- // Make sure we are dealing with a vCard, so we can access its vCardProperties.
- if (!abItem._card.supportsVCard) {
- throw new Error("It looks like you are trying to sync a TB91 sync state. Does not work.");
- }
- let vCardProperties = abItem._card.vCardProperties
-
- // Loop over all known EAS properties (send empty value if not set).
- for (let EAS_property of this.EAS_properties) {
- // Some props need special handling.
- let vCard_property = map_EAS_properties_to_vCard[EAS_property];
- let value;
- switch (EAS_property) {
- case "Notes":
- // Needs to be done later, because we have to switch the code page.
- continue;
-
- case "Picture": {
- let photoUrl = abItem._card.photoURL;
- if (!photoUrl) {
- continue;
- }
- if (photoUrl.startsWith("file://")) {
- let realPhotoFile = Services.io.newURI(photoUrl).QueryInterface(Ci.nsIFileURL).file;
- let photoFile = await File.createFromNsIFile(realPhotoFile);
- photoUrl = await this.getDataUrl(photoFile);
- }
- if (photoUrl.startsWith("data:image/")) {
- let parts = photoUrl.split(",");
- parts.shift();
- value = parts.join(",");
- }
- }
- break;
-
- case "Birthday":
- case "Anniversary": {
- let raw = this.getValue(vCardProperties, vCard_property);
- if (raw) {
- let dateObj = new Date(raw);
- value = dateObj.toISOString();
- }
- }
- break;
-
- case "HomeAddressStreet":
- case "BusinessAddressStreet":
- case "OtherAddressStreet": {
- let raw = this.getValue(vCardProperties, vCard_property);
- try {
- if (raw) {
- // We either get a single string or an array for the
- // street adr field from Thunderbird.
- if (!Array.isArray(raw)) {
- raw = [raw];
- }
- let seperator = String.fromCharCode(syncdata.accountData.getAccountProperty("seperator")); // options are 44 (,) or 10 (\n)
- value = raw.join(seperator);
- }
- } catch (ex) {
- throw new Error(`Failed to eval value: <${JSON.stringify(raw)}> @ ${JSON.stringify(vCard_property)}`);
- }
- }
- break;
-
- default: {
- value = this.getValue(vCardProperties, vCard_property);
- }
- }
-
- if (value) {
- wbxml.atag(EAS_property, value);
- }
- }
-
- // Take care of un-mappable EAS option.
- for (let i=0; i < this.unused_EAS_properties.length; i++) {
- let value = abItem.getProperty("EAS-" + this.unused_EAS_properties[i], "");
- if (value) wbxml.atag(this.unused_EAS_properties[i], value);
- }
-
- // Take care of categories.
- let categories = vCardProperties.getFirstValue("categories");
- let categoriesProperty = abItem.getProperty("Categories", "");
- if (categoriesProperty) {
- // Migration code, remove once no longer needed.
- abItem.setProperty("Categories", "");
- categories = this.arrayFromString(categoriesProperty);
- }
- if (categories) {
- wbxml.otag("Categories");
- for (let category of categories) wbxml.atag("Category", category);
- wbxml.ctag();
- }
-
- // Take care of children, stored in contacts property bag.
- let childrenProperty = abItem.getProperty("Children", "");
- if (childrenProperty) {
- let children = [];
- try {
- children = JSON.parse(childrenProperty);
- } catch(ex) {
- // Migration code, remove once no longer needed.
- children = this.arrayFromString(childrenProperty);
- }
- wbxml.otag("Children");
- for (let child of children) wbxml.atag("Child", child);
- wbxml.ctag();
- }
-
- // Take care of notes - SWITCHING TO AirSyncBase (if 2.5, we still need Contact group here!)
- let description = this.getValue(vCardProperties, map_EAS_properties_to_vCard["Notes"]);
- if (asversion == "2.5") {
- wbxml.atag("Body", description);
- } else {
- wbxml.switchpage("AirSyncBase");
- wbxml.otag("Body");
- wbxml.atag("Type", "1");
- wbxml.atag("EstimatedDataSize", "" + description.length);
- wbxml.atag("Data", description);
- wbxml.ctag();
- }
-
- // Take care of Contacts2 group - SWITCHING TO CONTACTS2
- wbxml.switchpage("Contacts2");
-
- // Loop over all known TB properties of EAS group Contacts2 (send empty value if not set).
- for (let EAS_property of this.EAS_properties2) {
- let vCard_property = this.map_EAS_properties_to_vCard_set2[EAS_property];
- let value = this.getValue(vCardProperties, vCard_property);
- if (value) wbxml.atag(EAS_property, value);
- }
-
- return wbxml.getBytes();
- }
-}
-
-Contacts.EAS_properties = Object.keys(Contacts.map_EAS_properties_to_vCard());
-Contacts.EAS_properties2 = Object.keys(Contacts.map_EAS_properties_to_vCard_set2);
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ newUID: "resource:///modules/AddrBookUtils.sys.mjs",
+ AddrBookCard: "resource:///modules/AddrBookCard.sys.mjs",
+ BANISHED_PROPERTIES: "resource:///modules/VCardUtils.sys.mjs",
+ VCardProperties: "resource:///modules/VCardUtils.sys.mjs",
+ VCardPropertyEntry: "resource:///modules/VCardUtils.sys.mjs",
+ VCardUtils: "resource:///modules/VCardUtils.sys.mjs",
+});
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+var { MailServices } = ChromeUtils.importESModule(
+ "resource:///modules/MailServices.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+const eas = TbSync.providers.eas;
+
+var Contacts = {
+
+ // Remove if migration code is removed.
+ arrayFromString: function (stringValue) {
+ let arrayValue = [];
+ if (stringValue.trim().length > 0) arrayValue = stringValue.trim().split("\u001A").filter(String);
+ return arrayValue;
+ },
+
+ /* The following TB properties are not synced to the server:
+ - only one WebPage
+ - more than 3 emails
+ - more than one fax, pager, mobile, work, home
+ - position (in org)
+ */
+
+ vcard_array_fields: {
+ n: 5,
+ adr: 7,
+ org: 2
+ },
+
+ map_EAS_properties_to_vCard: revision => ({
+ FileAs: { item: "fn", type: "text", params: {} }, /* DisplayName */
+
+ Birthday: { item: "bday", type: "date", params: {} },
+ Anniversary: { item: "anniversary", type: "date", params: {} },
+
+ LastName: { item: "n", type: "text", params: {}, index: 0 },
+ FirstName: { item: "n", type: "text", params: {}, index: 1 },
+ MiddleName: { item: "n", type: "text", params: {}, index: 2 },
+ Title: { item: "n", type: "text", params: {}, index: 3 },
+ Suffix: { item: "n", type: "text", params: {}, index: 4 },
+
+ Notes: { item: "note", type: "text", params: {} },
+
+ // What should we do with Email 4+?
+ // EAS does not have the concept of home/work for emails. Define matchAll
+ // to not use params for finding the correct entry. They will come back as
+ // "other".
+ Email1Address: { item: "email", type: "text", entry: 0, matchAll: true, params: {} },
+ Email2Address: { item: "email", type: "text", entry: 1, matchAll: true, params: {} },
+ Email3Address: { item: "email", type: "text", entry: 2, matchAll: true, params: {} },
+
+ // EAS does not have the concept of home/work for WebPage. Define matchAll
+ // to not use params for finding the correct entry. It will come back as
+ // "other".
+ WebPage: { item: "url", type: "text", matchAll: true, params: {} },
+
+ CompanyName: { item: "org", type: "text", params: {}, index: revision < 2 ? 1 : 0 }, /* Company */
+ Department: { item: "org", type: "text", params: {}, index: revision < 2 ? 0 : 1 }, /* Department */
+ JobTitle: { item: "title", type: "text", params: {} }, /* JobTitle */
+
+ MobilePhoneNumber: { item: "tel", type: "text", params: { type: "cell" } },
+ PagerNumber: { item: "tel", type: "text", params: { type: "pager" } },
+ HomeFaxNumber: { item: "tel", type: "text", params: { type: "fax" } },
+ // If home phone is defined, use that, otherwise use unspecified phone
+ // Note: This must be exclusive (no other field may use home/unspecified)
+ // except if entry is specified.
+ HomePhoneNumber: { item: "tel", type: "text", params: { type: "home" }, fallbackParams: [{}] },
+ BusinessPhoneNumber: { item: "tel", type: "text", params: { type: "work" } },
+ Home2PhoneNumber: { item: "tel", type: "text", params: { type: "home" }, entry: 1 },
+ Business2PhoneNumber: { item: "tel", type: "text", params: { type: "work" }, entry: 1 },
+
+ HomeAddressStreet: { item: "adr", type: "text", params: { type: "home" }, index: 2 }, // needs special handling
+ HomeAddressCity: { item: "adr", type: "text", params: { type: "home" }, index: 3 },
+ HomeAddressState: { item: "adr", type: "text", params: { type: "home" }, index: 4 },
+ HomeAddressPostalCode: { item: "adr", type: "text", params: { type: "home" }, index: 5 },
+ HomeAddressCountry: { item: "adr", type: "text", params: { type: "home" }, index: 6 },
+
+ BusinessAddressStreet: { item: "adr", type: "text", params: { type: "work" }, index: 2 }, // needs special handling
+ BusinessAddressCity: { item: "adr", type: "text", params: { type: "work" }, index: 3 },
+ BusinessAddressState: { item: "adr", type: "text", params: { type: "work" }, index: 4 },
+ BusinessAddressPostalCode: { item: "adr", type: "text", params: { type: "work" }, index: 5 },
+ BusinessAddressCountry: { item: "adr", type: "text", params: { type: "work" }, index: 6 },
+
+ OtherAddressStreet: { item: "adr", type: "text", params: {}, index: 2 }, // needs special handling
+ OtherAddressCity: { item: "adr", type: "text", params: {}, index: 3 },
+ OtherAddressState: { item: "adr", type: "text", params: {}, index: 4 },
+ OtherAddressPostalCode: { item: "adr", type: "text", params: {}, index: 5 },
+ OtherAddressCountry: { item: "adr", type: "text", params: {}, index: 6 },
+
+ // Misusing this EAS field, so that "Custom1" is saved to the server.
+ OfficeLocation: { item: "x-custom1", type: "text", params: {} },
+
+ Picture: { item: "photo", params: {}, type: "uri" },
+
+ // TB shows them as undefined, but showing them might be better, than not. Use a prefix.
+ AssistantPhoneNumber: { item: "tel", type: "text", params: { type: "Assistant" }, prefix: true },
+ CarPhoneNumber: { item: "tel", type: "text", params: { type: "Car" }, prefix: true },
+ RadioPhoneNumber: { item: "tel", type: "text", params: { type: "Radio" }, prefix: true },
+ BusinessFaxNumber: { item: "tel", type: "text", params: { type: "WorkFax" }, prefix: true },
+ }),
+
+ map_EAS_properties_to_vCard_set2: {
+ NickName: { item: "nickname", type: "text", params: {} },
+ // Misusing these EAS fields, so that "Custom2,3,4" is saved to the server.
+ CustomerId: { item: "x-custom2", type: "text", params: {} },
+ GovernmentId: { item: "x-custom3", type: "text", params: {} },
+ AccountName: { item: "x-custom4", type: "text", params: {} },
+
+ IMAddress: { item: "impp", type: "text", params: {} },
+ IMAddress2: { item: "impp", type: "text", params: {}, entry: 1 },
+ IMAddress3: { item: "impp", type: "text", params: {}, entry: 2 },
+
+ CompanyMainPhone: { item: "tel", type: "text", params: { type: "Company" }, prefix: true },
+ },
+
+ // There are currently no TB fields for these values, TbSync will store (and
+ // resend) them, but will not allow to view/edit.
+ unused_EAS_properties: [
+ "Alias", //pseudo field
+ "WeightedRank", //pseudo field
+ "YomiCompanyName", //japanese phonetic equivalent
+ "YomiFirstName", //japanese phonetic equivalent
+ "YomiLastName", //japanese phonetic equivalent
+ "CompressedRTF",
+ "MMS",
+ // Former custom EAS fields, no longer added to UI after 102.
+ "ManagerName",
+ "AssistantName",
+ "Spouse",
+ ],
+
+ // Normalize a parameters entry, to be able to find matching existing
+ // entries. If we want to be less restrictive, we need to check if all
+ // the requested values exist. But we should be the only one who sets
+ // the vCard props, so it should be safe. Except someone moves a contact.
+ // Should we prevent that via a vendor id in the vcard?
+ normalizeParameters: function (unordered) {
+ return JSON.stringify(
+ Object.keys(unordered).map(e => `${e}`.toLowerCase()).sort().reduce(
+ (obj, key) => {
+ obj[key] = `${unordered[key]}`.toLowerCase();
+ return obj;
+ },
+ {}
+ )
+ );
+ },
+
+ getValue: function (vCardProperties, vCard_property) {
+ let parameters = [vCard_property.params];
+ if (vCard_property.fallbackParams) {
+ parameters.push(...vCard_property.fallbackParams);
+ }
+ let entries;
+ for (let normalizedParams of parameters.map(this.normalizeParameters)) {
+ // If no params set, do not filter, otherwise filter for exact match.
+ entries = vCardProperties.getAllEntries(vCard_property.item)
+ .filter(e => vCard_property.matchAll || normalizedParams == this.normalizeParameters(e.params));
+ if (entries.length > 0) {
+ break;
+ }
+ }
+
+ // Which entry should we take?
+ let entryNr = vCard_property.entry || 0;
+ if (entries[entryNr]) {
+ let value;
+ if (vCard_property.item == "org" && !Array.isArray(entries[entryNr].value)) {
+ // The org field sometimes comes back as a string (then it is Company),
+ // even though it should be an array [Department,Company]
+ value = vCard_property.index == 1 ? entries[entryNr].value : "";
+ } else if (this.vcard_array_fields[vCard_property.item]) {
+ if (!Array.isArray(entries[entryNr].value)) {
+ // If the returned value is a single string, return it only
+ // when index 0 is requested, otherwise return nothing.
+ value = vCard_property.index == 0 ? entries[entryNr].value : "";
+ } else {
+ value = entries[entryNr].value[vCard_property.index];
+ }
+ } else {
+ value = entries[entryNr].value;
+ }
+
+ if (value) {
+ if (vCard_property.prefix && value.startsWith(`${vCard_property.params.type}: `)) {
+ return value.substring(`${vCard_property.params.type}: `.length);
+ }
+ return value;
+ }
+ }
+ return "";
+ },
+
+ /**
+ * Reads a DOM File and returns a Promise for its dataUrl.
+ *
+ * @param {File} file
+ * @returns {string}
+ */
+ getDataUrl(file) {
+ return new Promise((resolve, reject) => {
+ var reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = function () {
+ resolve(reader.result);
+ };
+ reader.onerror = function (error) {
+ resolve("");
+ };
+ });
+ },
+
+
+
+ // --------------------------------------------------------------------------- //
+ // Read WBXML and set Thunderbird item
+ // --------------------------------------------------------------------------- //
+ setThunderbirdItemFromWbxml: function (abItem, data, id, syncdata, mode = "standard") {
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ let revision = parseInt(syncdata.target._directory.getStringValue("tbSyncRevision", "1"), 10);
+ let map_EAS_properties_to_vCard = this.map_EAS_properties_to_vCard(revision);
+
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " contact item", id);
+
+ // Make sure we are dealing with a vCard, so we can update the card just
+ // by updating its vCardProperties.
+ if (!abItem._card.supportsVCard) {
+ // This is an older card??
+ throw new Error("It looks like you are trying to sync a TB91 sync state. Does not work.");
+ }
+ let vCardProperties = abItem._card.vCardProperties
+ abItem.primaryKey = id;
+
+ // Loop over all known EAS properties (two EAS sets Contacts and Contacts2).
+ for (let set = 0; set < 2; set++) {
+ let properties = (set == 0) ? this.EAS_properties : this.EAS_properties2;
+
+ for (let EAS_property of properties) {
+ let vCard_property = (set == 0) ? map_EAS_properties_to_vCard[EAS_property] : this.map_EAS_properties_to_vCard_set2[EAS_property];
+ let value;
+ switch (EAS_property) {
+ case "Notes":
+ if (asversion == "2.5") {
+ value = eas.xmltools.checkString(data.Body);
+ } else if (data.Body && data.Body.Data) {
+ value = eas.xmltools.checkString(data.Body.Data);
+ }
+ break;
+
+ default:
+ value = eas.xmltools.checkString(data[EAS_property]);
+ }
+
+ let normalizedParams = this.normalizeParameters(vCard_property.params)
+ let entries = vCardProperties.getAllEntries(vCard_property.item)
+ .filter(e => vCard_property.matchAll || normalizedParams == this.normalizeParameters(e.params));
+ // Which entry should we update? Add empty entries, if the requested entry number
+ // does not yet exist.
+ let entryNr = vCard_property.entry || 0;
+ while (entries.length <= entryNr) {
+ let newEntry = new VCardPropertyEntry(
+ vCard_property.item,
+ vCard_property.params,
+ vCard_property.type,
+ this.vcard_array_fields[vCard_property.item]
+ ? new Array(this.vcard_array_fields[vCard_property.item]).fill("")
+ : ""
+ );
+ vCardProperties.addEntry(newEntry);
+ entries = vCardProperties.getAllEntries(vCard_property.item);
+ entryNr = entries.length - 1;
+ }
+
+ // Is this property part of the send data?
+ if (value) {
+ // Do we need to manipulate the value?
+ switch (EAS_property) {
+ case "Picture":
+ value = `data:image/jpeg;base64,${eas.xmltools.nodeAsArray(data.Picture)[0]}`; //Kerio sends Picture as container
+ break;
+
+ case "Birthday":
+ case "Anniversary":
+ let dateObj = new Date(value);
+ value = dateObj.toISOString().substr(0, 10);
+ break;
+
+ case "Email1Address":
+ case "Email2Address":
+ case "Email3Address":
+ let parsedInput = MailServices.headerParser.makeFromDisplayAddress(value);
+ let fixedValue = (parsedInput && parsedInput[0] && parsedInput[0].email) ? parsedInput[0].email : value;
+ if (fixedValue != value) {
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Parsing email display string via RFC 2231 and RFC 2047 (" + EAS_property + ")", value + " -> " + fixedValue);
+ value = fixedValue;
+ }
+ break;
+
+ case "HomeAddressStreet":
+ case "BusinessAddressStreet":
+ case "OtherAddressStreet":
+ // Thunderbird accepts an array in the vCardProperty of the 2nd index of the adr field.
+ let seperator = String.fromCharCode(syncdata.accountData.getAccountProperty("seperator")); // options are 44 (,) or 10 (\n)
+ value = value.split(seperator);
+ break;
+ }
+
+ // Add a typePrefix for fields unknown to TB (better: TB should use the type itself).
+ if (vCard_property.prefix && !value.startsWith(`${vCard_property.params.type}: `)) {
+ value = `${vCard_property.params.type}: ${value}`;
+ }
+
+ // Is this an array value?
+ if (this.vcard_array_fields[vCard_property.item]) {
+ // Make sure this is an array.
+ if (!Array.isArray(entries[entryNr].value)) {
+ let arr = new Array(this.vcard_array_fields[vCard_property.item]).fill("");
+ arr[0] = entries[entryNr].value;
+ entries[entryNr].value = arr;
+ }
+ entries[entryNr].value[vCard_property.index] = value;
+ } else {
+ entries[entryNr].value = value;
+ }
+ } else {
+ if (this.vcard_array_fields[vCard_property.item]) {
+ // Make sure this is an array.
+ if (!Array.isArray(entries[entryNr].value)) {
+ let arr = new Array(this.vcard_array_fields[vCard_property.item]).fill("");
+ arr[0] = entries[entryNr].value;
+ entries[entryNr].value = arr;
+ }
+ entries[entryNr].value[vCard_property.index] = "";
+ } else {
+ entries[entryNr].value = "";
+ }
+ }
+ }
+ }
+
+ // Take care of categories.
+ if (data["Categories"] && data["Categories"]["Category"]) {
+ let categories = Array.isArray(data["Categories"]["Category"])
+ ? data["Categories"]["Category"]
+ : [data["Categories"]["Category"]];
+ vCardProperties.clearValues("categories");
+ vCardProperties.addValue("categories", categories);
+ // Migration code, remove once no longer needed.
+ abItem.setProperty("Categories", "");
+ }
+
+ // Take care of children, stored in contacts property bag.
+ if (data["Children"] && data["Children"]["Child"]) {
+ let children = Array.isArray(data["Children"]["Child"])
+ ? data["Children"]["Child"]
+ : [data["Children"]["Child"]];
+ abItem.setProperty("Children", JSON.stringify(children));
+ }
+
+ // Take care of un-mappable EAS options, which are stored in the contacts
+ // property bag.
+ for (let i = 0; i < this.unused_EAS_properties.length; i++) {
+ if (data[this.unused_EAS_properties[i]]) abItem.setProperty("EAS-" + this.unused_EAS_properties[i], data[this.unused_EAS_properties[i]]);
+ }
+
+ // Remove all entries, which are marked for deletion.
+ vCardProperties.entries = vCardProperties.entries.filter(e => Array.isArray(e.value) ? e.value.some(a => a != "") : e.value != "");
+
+ // Further manipulations (a few getters are still usable \o/).
+ if (syncdata.accountData.getAccountProperty("displayoverride")) {
+ abItem._card.displayName = abItem._card.firstName + " " + abItem._card.lastName;
+ if (abItem._card.displayName == " ") {
+ let company = (vCardProperties.getFirstValue("org") || [""])[0];
+ abItem._card.displayName = company || abItem._card.primaryEmail
+ }
+ }
+ },
+
+
+
+
+ // --------------------------------------------------------------------------- //
+ //read TB event and return its data as WBXML
+ // --------------------------------------------------------------------------- //
+ getWbxmlFromThunderbirdItem: async function (abItem, syncdata, isException = false) {
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ let revision = parseInt(syncdata.target._directory.getStringValue("tbSyncRevision", "1"), 10);
+ let map_EAS_properties_to_vCard = this.map_EAS_properties_to_vCard(revision);
+
+ let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
+ let nowDate = new Date();
+
+ // Make sure we are dealing with a vCard, so we can access its vCardProperties.
+ if (!abItem._card.supportsVCard) {
+ throw new Error("It looks like you are trying to sync a TB91 sync state. Does not work.");
+ }
+ let vCardProperties = abItem._card.vCardProperties
+
+ // Loop over all known EAS properties (send empty value if not set).
+ for (let EAS_property of this.EAS_properties) {
+ // Some props need special handling.
+ let vCard_property = map_EAS_properties_to_vCard[EAS_property];
+ let value;
+ switch (EAS_property) {
+ case "Notes":
+ // Needs to be done later, because we have to switch the code page.
+ continue;
+
+ case "Picture": {
+ let photoUrl = abItem._card.photoURL;
+ if (!photoUrl) {
+ continue;
+ }
+ if (photoUrl.startsWith("file://")) {
+ let realPhotoFile = Services.io.newURI(photoUrl).QueryInterface(Ci.nsIFileURL).file;
+ let photoFile = await File.createFromNsIFile(realPhotoFile);
+ photoUrl = await this.getDataUrl(photoFile);
+ }
+ if (photoUrl.startsWith("data:image/")) {
+ let parts = photoUrl.split(",");
+ parts.shift();
+ value = parts.join(",");
+ }
+ }
+ break;
+
+ case "Birthday":
+ case "Anniversary": {
+ let raw = this.getValue(vCardProperties, vCard_property);
+ if (raw) {
+ let dateObj = new Date(raw);
+ value = dateObj.toISOString();
+ }
+ }
+ break;
+
+ case "HomeAddressStreet":
+ case "BusinessAddressStreet":
+ case "OtherAddressStreet": {
+ let raw = this.getValue(vCardProperties, vCard_property);
+ try {
+ if (raw) {
+ // We either get a single string or an array for the
+ // street adr field from Thunderbird.
+ if (!Array.isArray(raw)) {
+ raw = [raw];
+ }
+ let seperator = String.fromCharCode(syncdata.accountData.getAccountProperty("seperator")); // options are 44 (,) or 10 (\n)
+ value = raw.join(seperator);
+ }
+ } catch (ex) {
+ throw new Error(`Failed to eval value: <${JSON.stringify(raw)}> @ ${JSON.stringify(vCard_property)}`);
+ }
+ }
+ break;
+
+ default: {
+ value = this.getValue(vCardProperties, vCard_property);
+ }
+ }
+
+ if (value) {
+ wbxml.atag(EAS_property, value);
+ }
+ }
+
+ // Take care of un-mappable EAS option.
+ for (let i = 0; i < this.unused_EAS_properties.length; i++) {
+ let value = abItem.getProperty("EAS-" + this.unused_EAS_properties[i], "");
+ if (value) wbxml.atag(this.unused_EAS_properties[i], value);
+ }
+
+ // Take care of categories.
+ let categories = vCardProperties.getFirstValue("categories");
+ let categoriesProperty = abItem.getProperty("Categories", "");
+ if (categoriesProperty) {
+ // Migration code, remove once no longer needed.
+ abItem.setProperty("Categories", "");
+ categories = this.arrayFromString(categoriesProperty);
+ }
+ if (categories) {
+ wbxml.otag("Categories");
+ for (let category of categories) wbxml.atag("Category", category);
+ wbxml.ctag();
+ }
+
+ // Take care of children, stored in contacts property bag.
+ let childrenProperty = abItem.getProperty("Children", "");
+ if (childrenProperty) {
+ let children = [];
+ try {
+ children = JSON.parse(childrenProperty);
+ } catch (ex) {
+ // Migration code, remove once no longer needed.
+ children = this.arrayFromString(childrenProperty);
+ }
+ wbxml.otag("Children");
+ for (let child of children) wbxml.atag("Child", child);
+ wbxml.ctag();
+ }
+
+ // Take care of notes - SWITCHING TO AirSyncBase (if 2.5, we still need Contact group here!)
+ let description = this.getValue(vCardProperties, map_EAS_properties_to_vCard["Notes"]);
+ if (asversion == "2.5") {
+ wbxml.atag("Body", description);
+ } else {
+ wbxml.switchpage("AirSyncBase");
+ wbxml.otag("Body");
+ wbxml.atag("Type", "1");
+ wbxml.atag("EstimatedDataSize", "" + description.length);
+ wbxml.atag("Data", description);
+ wbxml.ctag();
+ }
+
+ // Take care of Contacts2 group - SWITCHING TO CONTACTS2
+ wbxml.switchpage("Contacts2");
+
+ // Loop over all known TB properties of EAS group Contacts2 (send empty value if not set).
+ for (let EAS_property of this.EAS_properties2) {
+ let vCard_property = this.map_EAS_properties_to_vCard_set2[EAS_property];
+ let value = this.getValue(vCardProperties, vCard_property);
+ if (value) wbxml.atag(EAS_property, value);
+ }
+
+ return wbxml.getBytes();
+ }
+}
+
+Contacts.EAS_properties = Object.keys(Contacts.map_EAS_properties_to_vCard());
+Contacts.EAS_properties2 = Object.keys(Contacts.map_EAS_properties_to_vCard_set2);
diff -Nru eas4tbsync-4.11/content/includes/network.js eas4tbsync-4.17/content/includes/network.js
--- eas4tbsync-4.11/content/includes/network.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/network.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,1544 +1,1606 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { OAuth2 } = ChromeUtils.import("resource:///modules/OAuth2.jsm");
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-
-var containers = [];
-var sandboxes = {};
-
-function resetContainerWithId(id) {
- Services.clearData.deleteDataFromOriginAttributesPattern({ userContextId: id });
-}
-
-function getContainerIdForContainerName(containerName) {
- // Define the allowed range of container ids to be used
- // TbSync is using 10000 - 19999
- // Lightning is using 20000 - 29999
- // Cardbook is using 30000 - 39999
- let min = 10000;
- let max = 19999;
-
- //reset if adding an entry will exceed allowed range
- if (containers.length > (max - min) && containers.indexOf(containerName) == -1) {
- for (let i = 0; i < containers.length; i++) {
- resetContainerWithId(i + min);
- }
- containers = [];
- }
-
- let idx = containers.indexOf(containerName);
- return (idx == -1) ? containers.push(containerName) - 1 + min : (idx + min);
-}
-
-function getSandBoxedXHR({ user, accountname }, uri, containerReset = false) {
- // The content principal used for the sandbox honours CORS. A server redirect
- // to a different server may cause CORS violations. We implemented code to
- // catch such redirects and re-run the request with the correct sandbox. If
- // that becomes an issue, we need to make sandboxing optional.
- // return new XMLHttpRequest({ mozAnon: false });
-
- let containerName = `${accountname}::${user}@${uri.scheme}://${uri.hostPort}`;
-
- let userContextId = getContainerIdForContainerName(containerName);
- if (containerReset) {
- resetContainerWithId(userContextId);
- }
- if (!sandboxes.hasOwnProperty(containerName)) {
- console.log("Creating sandbox for <" + containerName + ">");
- let principal = Services.scriptSecurityManager.createContentPrincipal(uri, { userContextId });
- sandboxes[containerName] = Components.utils.Sandbox(principal, {
- wantXrays: true,
- wantGlobalProperties: ["XMLHttpRequest"],
- });
- }
- return new sandboxes[containerName].XMLHttpRequest({ mozAnon: false });
-}
-
-var network = {
-
- getEasURL: function (accountData) {
- let protocol = (accountData.getAccountProperty("https")) ? "https://" : "http://";
- let h = protocol + accountData.getAccountProperty("host");
- while (h.endsWith("/")) { h = h.slice(0, -1); }
-
- if (h.endsWith("Microsoft-Server-ActiveSync")) return h;
- return h + "/Microsoft-Server-ActiveSync";
- },
-
- getAuthData: function (accountData) {
- let authData = {
- // This is the host for the password manager, which could be different from
- // the actual host property of the account. For EAS we want to couple the password
- // with the ACCOUNT and not any sort of url, which could change via autodiscover
- // at any time.
- get host() {
- return "TbSync#" + accountData.accountID;
- },
-
- get user() {
- return accountData.getAccountProperty("user");
- },
-
- get password() {
- return TbSync.passwordManager.getLoginInfo(this.host, "TbSync/EAS", this.user);
- },
-
- get accountname() {
- return accountData.getAccountProperty("accountname");
- },
-
- updateLoginData: async function (newUsername, newPassword) {
- let oldUsername = this.user;
- await TbSync.passwordManager.updateLoginInfo(this.host, "TbSync/EAS", oldUsername, newUsername, newPassword);
- // Also update the username of this account. Add dedicated username setter?
- accountData.setAccountProperty("user", newUsername);
- },
-
- removeLoginData: function () {
- TbSync.passwordManager.removeLoginInfos(this.host, "TbSync/EAS");
- }
- };
- return authData;
- },
-
- getContextData: function (configObject = null) {
- let contextData = {}
- contextData.accountData = (configObject && configObject.hasOwnProperty("accountData")) ? configObject.accountData : null;
-
- if (contextData.accountData) {
- contextData.accountname = contextData.accountData.getAccountProperty("accountname");
- contextData.user = contextData.accountData.getAccountProperty("user");
- contextData.host = contextData.accountData.getAccountProperty("host");
- contextData.servertype = contextData.accountData.getAccountProperty("servertype");
- contextData.accountID = contextData.accountData.accountID;
- } else {
- contextData.accountname = (configObject && configObject.hasOwnProperty("accountname")) ? configObject.accountname : "";
- contextData.user = (configObject && configObject.hasOwnProperty("user")) ? configObject.user : "";
- contextData.host = (configObject && configObject.hasOwnProperty("host")) ? configObject.host : "";
- contextData.servertype = (configObject && configObject.hasOwnProperty("servertype")) ? configObject.servertype : "";
- contextData.accountID = "";
- }
-
- return contextData;
- },
-
- // prepare and patch OAuth2 object
- getOAuthObj: function (configObject = null) {
- let {
- accountData,
- accountname,
- user,
- host,
- accountID,
- servertype
- } = this.getContextData(configObject);
-
- if (!["office365"].includes(servertype))
- return null;
-
- let config = {};
- let customID = eas.Base.getCustomeOauthClientID();
- switch (host) {
- case "outlook.office365.com":
- case "eas.outlook.com":
- config = {
- auth_uri: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
- token_uri: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
- redirect_uri: "https://login.microsoftonline.com/common/oauth2/nativeclient",
- client_id: customID != "" ? customID : "2980deeb-7460-4723-864a-f9b0f10cd992",
- }
- break;
-
- default:
- return null;
- }
-
- switch (host) {
- case "outlook.office365.com":
- config.scope = "offline_access https://outlook.office.com/.default";
- break;
- case "eas.outlook.com":
- config.scope = "offline_access https://outlook.office.com/EAS.AccessAsUser.All";
- break;
- }
-
- let oauth = new OAuth2(config.scope, {
- authorizationEndpoint: config.auth_uri,
- tokenEndpoint: config.token_uri,
- clientId: config.client_id,
- clientSecret: config.client_secret
- });
- oauth.requestWindowFeatures = "chrome,private,centerscreen,width=500,height=750";
-
- // The v2 redirection endpoint differs from the default and needs manual override
- oauth.redirectionEndpoint = config.redirect_uri;
-
- oauth.extraAuthParams = [
- // removed in beta 1.14.1, according to
- // https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#default-and-consent
- // prompt = consent will always ask for admin consent, even if it was granted
- //["prompt", "consent"],
- ["login_hint", user],
- ];
-
- if (accountname) {
- oauth.requestWindowTitle = "TbSync account <" + accountname + "> requests authorization.";
- } else {
- oauth.requestWindowTitle = "A TbSync account requests authorization.";
- }
-
-
-
-
- /* Adding custom methods to the oauth object */
-
- oauth.asyncConnect = async function (rv) {
- rv.error = "";
-
- // If multiple resources need to authenticate they will all end here, even though they
- // might share the same token. Due to the async nature, each process will refresh
- // "its own" token again, which is not needed. We force clear the token here and each
- // final connect process will actually check the acccessToken and abort the refresh,
- // if it is already there, generated by some other process.
- if (oauth.getToken("accessToken")) {
- await oauth.setToken("accessToken", "");
- }
-
-
- try {
- // refresh = false will do nothing and resolve immediately, if an accessToken
- // exists already, which must have been generated by another process, as
- // we cleared it beforehand.
- await oauth.connect(/* with UI */ true, /* refresh */ false);
- await oauth.setToken("accessToken", oauth.accessToken);
- await oauth.setToken("refreshToken", oauth.refreshToken);
- await oauth.setToken("tokenExpires", oauth.tokenExpires);
- rv.tokens = oauth.tokens;
- return true;
- } catch (e) {
- await oauth.setToken("accessToken", oauth.accessToken);
- await oauth.setToken("refreshToken", oauth.refreshToken);
- await oauth.setToken("tokenExpires", oauth.tokenExpires);
- rv.error = eas.tools.isString(e) ? e : JSON.stringify(e);
- }
-
- try {
- switch (JSON.parse(rv.error).error) {
- case "invalid_grant":
- await oauth.setToken("accessToken", "");
- await oauth.setToken("refreshToken", "");
- rv.tokens = oauth.tokens;
- return true;
-
- case "cancelled":
- rv.error = "OAuthAbortError";
- break;
-
- default:
- rv.error = "OAuthServerError::" + rv.error;
- break;
- }
- } catch (e) {
- rv.error = "OAuthServerError::" + rv.error;
- Components.utils.reportError(e);
- }
- rv.tokens = oauth.tokens;
- return false;
- };
-
- oauth.isExpired = function () {
- const OAUTH_GRACE_TIME = 30 * 1000;
- return (oauth.getToken("tokenExpires") - OAUTH_GRACE_TIME < new Date().getTime());
- };
-
- const OAUTHVALUES = [
- ["access", "", "accessToken"],
- ["refresh", "", "refreshToken"],
- ["expires", Number.MAX_VALUE, "tokenExpires"],
- ];
-
- // returns a JSON string containing all the oauth values
- Object.defineProperty(oauth, "tokens", {
- get: function () {
- let tokensObj = {};
- for (let oauthValue of OAUTHVALUES) {
- // use the system value or if not defined the default
- tokensObj[oauthValue[0]] = this[oauthValue[2]] || oauthValue[1];
- }
- return JSON.stringify(tokensObj);
- },
- enumerable: true,
- });
-
- if (accountData) {
- // authData allows us to access the password manager values belonging to this account/calendar
- // simply by authdata.username and authdata.password
- oauth.authData = TbSync.providers.eas.network.getAuthData(accountData);
-
- oauth.parseAndSanitizeTokenString = function (tokenString) {
- let _tokensObj = {};
- try {
- _tokensObj = JSON.parse(tokenString);
- } catch (e) { }
-
- let tokensObj = {};
- for (let oauthValue of OAUTHVALUES) {
- // use the provided value or if not defined the default
- tokensObj[oauthValue[0]] = (_tokensObj && _tokensObj.hasOwnProperty(oauthValue[0]))
- ? _tokensObj[oauthValue[0]]
- : oauthValue[1];
- }
- return tokensObj;
- };
-
- oauth.getToken = function (tokenName) {
- let oauthValue = OAUTHVALUES.find(e => e[2] == tokenName);
- return oauth.parseAndSanitizeTokenString(oauth.authData.password)[oauthValue[0]];
- };
-
- oauth.setToken = async function (tokenName, val) {
- oauth[tokenName] = val;
-
- let oauthValue = OAUTHVALUES.find(e => e[2] == tokenName);
- let tokens = oauth.parseAndSanitizeTokenString(oauth.authData.password);
- let valueChanged = (val != tokens[oauthValue[0]])
- if (valueChanged) {
- tokens[oauthValue[0]] = val;
- await oauth.authData.updateLoginData(oauth.authData.user, JSON.stringify(tokens));
- }
- };
- } else {
- oauth.getToken = function (tokenName) {
- return oauth[tokenName];
- };
-
- oauth.setToken = async function (tokenName, val) {
- oauth[tokenName] = val;
- };
- }
-
- return oauth;
- },
-
- getOAuthValue: function (currentTokenString, type = "access") {
- try {
- let tokens = JSON.parse(currentTokenString);
- if (tokens.hasOwnProperty(type))
- return tokens[type];
- } catch (e) {
- //NOOP
- }
- return "";
- },
-
- sendRequest: async function (wbxml, command, syncData, allowSoftFail = false) {
- let ALLOWED_RETRIES = {
- PasswordPrompt: 3,
- NetworkError: 1,
- }
-
- let rv = {};
- let oauthData = eas.network.getOAuthObj({ accountData: syncData.accountData });
- let syncState = syncData.getSyncState().state;
-
- for (; ;) {
-
- if (rv.errorType) {
- let retry = false;
-
- if (ALLOWED_RETRIES[rv.errorType] > 0) {
- ALLOWED_RETRIES[rv.errorType]--;
-
-
- switch (rv.errorType) {
-
- case "PasswordPrompt":
- {
-
- if (oauthData) {
- await oauthData.setToken("accessToken", "");
- retry = true;
- } else {
- let authData = eas.network.getAuthData(syncData.accountData);
- syncData.setSyncState("passwordprompt");
- let promptData = {
- windowID: "auth:" + syncData.accountData.accountID,
- accountname: syncData.accountData.getAccountProperty("accountname"),
- usernameLocked: syncData.accountData.isConnected(),
- username: authData.user
- }
- let credentials = await TbSync.passwordManager.asyncPasswordPrompt(promptData, eas.openWindows);
- if (credentials) {
- retry = true;
- await authData.updateLoginData(credentials.username, credentials.password);
- }
- }
- }
- break;
-
- case "NetworkError":
- {
- // Could not connect to server. Can we rerun autodiscover?
- // Note: Autodiscover is currently not supported by OAuth
- if (syncData.accountData.getAccountProperty("servertype") == "auto" && !oauthData) {
- let errorcode = await eas.network.updateServerConnectionViaAutodiscover(syncData);
- console.log("ERR: " + errorcode);
- if (errorcode == 200) {
- // autodiscover succeeded, retry with new data
- retry = true;
- } else if (errorcode == 401) {
- // manipulate rv to run password prompt
- ALLOWED_RETRIES[rv.errorType]++;
- rv.errorType = "PasswordPrompt";
- rv.errorObj = eas.sync.finish("error", "401");
- continue; // with the next loop, skip connection to the server
- }
- }
- }
- break;
-
- }
- }
-
- if (!retry) throw rv.errorObj;
- }
-
- // check OAuth situation before connecting
- if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
- syncData.setSyncState("oauthprompt");
- let _rv = {}
- if (!(await oauthData.asyncConnect(_rv))) {
- throw eas.sync.finish("error", _rv.error);
- }
- }
-
- // Return to original syncstate
- if (syncState != syncData.getSyncState().state) {
- syncData.setSyncState(syncState);
- }
- rv = await this.sendRequestPromise(wbxml, command, syncData, allowSoftFail);
-
- if (rv.errorType) {
- // make sure, there is a valid ALLOWED_RETRIES setting for the returned error
- if (rv.errorType && !ALLOWED_RETRIES.hasOwnProperty(rv.errorType)) {
- ALLOWED_RETRIES[rv.errorType] = 1;
- }
- } else {
- return rv;
- }
- }
- },
-
- sendRequestPromise: function (wbxml, command, syncData, allowSoftFail = false) {
- let msg = "Sending data <" + syncData.getSyncState().state + "> for " + syncData.accountData.getAccountProperty("accountname");
- if (syncData.currentFolderData) msg += " (" + syncData.currentFolderData.getFolderProperty("foldername") + ")";
- syncData.request = eas.network.logXML(wbxml, msg);
- syncData.response = "";
-
- let connection = eas.network.getAuthData(syncData.accountData);
- let userAgent = syncData.accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
- let deviceType = syncData.accountData.getAccountProperty("devicetype");
- let deviceId = syncData.accountData.getAccountProperty("deviceId");
-
- TbSync.dump("Sending (EAS v" + syncData.accountData.getAccountProperty("asversion") + ")", "POST " + eas.network.getEasURL(syncData.accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(connection.user) + '&DeviceType=' + deviceType + '&DeviceId=' + deviceId, true);
-
- const textEncoder = new TextEncoder();
- let encoded = textEncoder.encode(wbxml);
- // console.log("wbxml: " + wbxml);
- // console.log("byte array: " + encoded);
- // console.log("length :" + wbxml.length + " vs " + encoded.byteLength + " vs " + encoded.length);
-
- let contextData = eas.network.getContextData({ accountData: syncData.accountData });
- let uri = Services.io.newURI(eas.network.getEasURL(syncData.accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(connection.user) + '&DeviceType=' + encodeURIComponent(deviceType) + '&DeviceId=' + deviceId);
- return new Promise(function (resolve, reject) {
- syncData.req = getSandBoxedXHR(contextData, uri);
- syncData.req.mozBackgroundRequest = true;
- syncData.req.open("POST", uri.spec, true);
- syncData.req.overrideMimeType("text/plain");
- syncData.req.setRequestHeader("User-Agent", userAgent);
- syncData.req.setRequestHeader("Content-Type", "application/vnd.ms-sync.wbxml");
- if (connection.password) {
- if (eas.network.getOAuthObj({ accountData: syncData.accountData })) {
- syncData.req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(connection.password, "access"));
- } else {
- syncData.req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(connection.user + ':' + connection.password));
- }
- }
-
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") {
- syncData.req.setRequestHeader("MS-ASProtocolVersion", "2.5");
- } else {
- syncData.req.setRequestHeader("MS-ASProtocolVersion", "14.0");
- }
- syncData.req.setRequestHeader("Content-Length", encoded.length);
- if (syncData.accountData.getAccountProperty("provision")) {
- syncData.req.setRequestHeader("X-MS-PolicyKey", syncData.accountData.getAccountProperty("policykey"));
- TbSync.dump("PolicyKey used", syncData.accountData.getAccountProperty("policykey"));
- }
-
- syncData.req.timeout = eas.Base.getConnectionTimeout();
-
- syncData.req.ontimeout = function () {
- if (allowSoftFail) {
- resolve("");
- } else {
- reject(eas.sync.finish("error", "timeout"));
- }
- };
-
- syncData.req.onerror = function () {
- if (allowSoftFail) {
- resolve("");
- } else {
- let error = TbSync.network.createTCPErrorFromFailedXHR(syncData.req) || "networkerror";
- let rv = {};
- rv.errorObj = eas.sync.finish("error", error);
- rv.errorType = "NetworkError";
- resolve(rv);
- }
- };
-
- syncData.req.onload = function () {
- let response = syncData.req.responseText;
- switch (syncData.req.status) {
-
- case 200: //OK
- let msg = "Receiving data <" + syncData.getSyncState().state + "> for " + syncData.accountData.getAccountProperty("accountname");
- if (syncData.currentFolderData) msg += " (" + syncData.currentFolderData.getFolderProperty("foldername") + ")";
- syncData.response = eas.network.logXML(response, msg);
-
- //What to do on error? IS this an error? Yes!
- if (!allowSoftFail && response.length !== 0 && response.substr(0, 4) !== String.fromCharCode(0x03, 0x01, 0x6A, 0x00)) {
- TbSync.dump("Recieved Data", "Expecting WBXML but got junk (request status = " + syncData.req.status + ", ready state = " + syncData.req.readyState + "\n>>>>>>>>>>\n" + response + "\n<<<<<<<<<<\n");
- reject(eas.sync.finish("warning", "invalid"));
- } else {
- resolve(response);
- }
- break;
-
- case 401: // AuthError
- case 403: // Forbiddden (some servers send forbidden on AuthError, like Freenet)
- let rv = {};
- rv.errorObj = eas.sync.finish("error", "401");
- rv.errorType = "PasswordPrompt";
- resolve(rv);
- break;
-
- case 449: // Request for new provision (enable it if needed)
- //enable provision
- syncData.accountData.setAccountProperty("provision", true);
- syncData.accountData.resetAccountProperty("policykey");
- reject(eas.sync.finish("resyncAccount", syncData.req.status));
- break;
-
- case 451: // Redirect - update host and login manager
- let header = syncData.req.getResponseHeader("X-MS-Location");
- let newHost = header.slice(header.indexOf("://") + 3, header.indexOf("/M"));
-
- TbSync.dump("redirect (451)", "header: " + header + ", oldHost: " + syncData.accountData.getAccountProperty("host") + ", newHost: " + newHost);
-
- syncData.accountData.setAccountProperty("host", newHost);
- reject(eas.sync.finish("resyncAccount", syncData.req.status));
- break;
-
- default:
- if (allowSoftFail) {
- resolve("");
- } else {
- reject(eas.sync.finish("error", "httperror::" + syncData.req.status));
- }
- }
- };
-
- syncData.req.send(encoded);
-
- });
- },
-
-
-
-
-
-
-
-
-
-
- // RESPONSE EVALUATION
-
- logXML: function (wbxml, what) {
- let rawxml = eas.wbxmltools.convert2xml(wbxml);
- let xml = null;
- if (rawxml) {
- xml = rawxml.split('><').join('>\n<');
- }
-
- //include xml in log, if userdatalevel 2 or greater
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 1) {
-
- //log raw wbxml if userdatalevel is 3 or greater
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) {
- let charcodes = [];
- for (let i = 0; i < wbxml.length; i++) charcodes.push(wbxml.charCodeAt(i).toString(16));
- let bytestring = charcodes.join(" ");
- TbSync.dump("WBXML: " + what, "\n" + bytestring);
- }
-
- if (xml) {
- //raw xml is save xml with all special chars in user data encoded by encodeURIComponent - KEEP that in order to be able to analyze logged XML
- //let xml = decodeURIComponent(rawxml.split('><').join('>\n<'));
- TbSync.dump("XML: " + what, "\n" + xml);
- } else {
- TbSync.dump("XML: " + what, "\nFailed to convert WBXML to XML!\n");
- }
- }
-
- return xml;
- },
-
- //returns false on parse error and null on empty response (if allowed)
- getDataFromResponse: function (wbxml, allowEmptyResponse = !eas.flags.allowEmptyResponse) {
- //check for empty wbxml
- if (wbxml.length === 0) {
- if (allowEmptyResponse) return null;
- else throw eas.sync.finish("warning", "empty-response");
- }
-
- //convert to save xml (all special chars in user data encoded by encodeURIComponent) and check for parse errors
- let xml = eas.wbxmltools.convert2xml(wbxml);
- if (xml === false) {
- throw eas.sync.finish("warning", "wbxml-parse-error");
- }
-
- //retrieve data and check for empty data (all returned data fields are already decoded by decodeURIComponent)
- let wbxmlData = eas.xmltools.getDataFromXMLString(xml);
- if (wbxmlData === null) {
- if (allowEmptyResponse) return null;
- else throw eas.sync.finish("warning", "response-contains-no-data");
- }
-
- //debug
- eas.xmltools.printXmlData(wbxmlData, false); //do not include ApplicationData in log
- return wbxmlData;
- },
-
- updateSynckey: function (syncData, wbxmlData) {
- let synckey = eas.xmltools.getWbxmlDataField(wbxmlData, "Sync.Collections.Collection.SyncKey");
-
- if (synckey) {
- // This COULD be a cause of problems...
- syncData.synckey = synckey;
- syncData.currentFolderData.setFolderProperty("synckey", synckey);
- } else {
- throw eas.sync.finish("error", "wbxmlmissingfield::Sync.Collections.Collection.SyncKey");
- }
- },
-
- checkStatus: function (syncData, wbxmlData, path, rootpath = "", allowSoftFail = false) {
- //path is relative to wbxmlData
- //rootpath is the absolute path and must be specified, if wbxml is not the root node and thus path is not the rootpath
- let status = eas.xmltools.getWbxmlDataField(wbxmlData, path);
- let fullpath = (rootpath == "") ? path : rootpath;
- let elements = fullpath.split(".");
- let type = elements[0];
-
- //check if fallback to main class status: the answer could just be a "Sync.Status" instead of a "Sync.Collections.Collections.Status"
- if (status === false) {
- let mainStatus = eas.xmltools.getWbxmlDataField(wbxmlData, type + "." + elements[elements.length - 1]);
- if (mainStatus === false) {
- //both possible status fields are missing, abort
- throw eas.sync.finish("warning", "wbxmlmissingfield::" + fullpath, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
- } else {
- //the alternative status could be extracted
- status = mainStatus;
- fullpath = type + "." + elements[elements.length - 1];
- }
- }
-
- //check if all is fine (not bad)
- if (status == "1") {
- return "";
- }
-
- TbSync.dump("wbxml status check", type + ": " + fullpath + " = " + status);
-
- //handle errrors based on type
- let statusType = type + "." + status;
- switch (statusType) {
- case "Sync.3": /*
- MUST return to SyncKey element value of 0 for the collection. The client SHOULD either delete any items that were added
- since the last successful Sync or the client MUST add those items back to the server after completing the full resynchronization
- */
- TbSync.eventlog.add("warning", syncData.eventLogInfo, "Forced Folder Resync", "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
- syncData.currentFolderData.remove();
- throw eas.sync.finish("resyncFolder", statusType);
-
- case "Sync.4": //Malformed request
- case "Sync.5": //Temporary server issues or invalid item
- case "Sync.6": //Invalid item
- case "Sync.8": //Object not found
- if (allowSoftFail) return statusType;
- throw eas.sync.finish("warning", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
-
- case "Sync.7": //The client has changed an item for which the conflict policy indicates that the server's changes take precedence.
- case "Sync.9": //User account could be out of disk space, also send if no write permission (TODO)
- return "";
-
- case "FolderDelete.3": // special system folder - fatal error
- case "FolderDelete.6": // error on server
- throw eas.sync.finish("warning", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
-
- case "FolderDelete.4": // folder does not exist - resync ( we allow delete only if folder is not subscribed )
- case "FolderDelete.9": // invalid synchronization key - resync
- case "FolderSync.9": // invalid synchronization key - resync
- case "Sync.12": // folder hierarchy changed
- {
- let folders = syncData.accountData.getAllFoldersIncludingCache();
- for (let folder of folders) {
- folder.remove();
- }
- // reset account
- eas.Base.onEnableAccount(syncData.accountData);
- throw eas.sync.finish("resyncAccount", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
- }
- }
-
- //handle global error (https://msdn.microsoft.com/en-us/library/ee218647(v=exchg.80).aspx)
- let descriptions = {};
- switch (status) {
- case "101": //invalid content
- case "102": //invalid wbxml
- case "103": //invalid xml
- throw eas.sync.finish("error", "global." + status, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
-
- case "109": descriptions["109"] = "DeviceTypeMissingOrInvalid";
- case "112": descriptions["112"] = "ActiveDirectoryAccessDenied";
- case "126": descriptions["126"] = "UserDisabledForSync";
- case "127": descriptions["127"] = "UserOnNewMailboxCannotSync";
- case "128": descriptions["128"] = "UserOnLegacyMailboxCannotSync";
- case "129": descriptions["129"] = "DeviceIsBlockedForThisUser";
- case "130": descriptions["120"] = "AccessDenied";
- case "131": descriptions["131"] = "AccountDisabled";
- throw eas.sync.finish("error", "global.clientdenied" + "::" + status + "::" + descriptions[status]);
-
- case "110": //server error - abort and disable autoSync for 30 minutes
- {
- let noAutosyncUntil = 30 * 60000 + Date.now();
- let humanDate = new Date(noAutosyncUntil).toUTCString();
- syncData.accountData.setAccountProperty("noAutosyncUntil", noAutosyncUntil);
- throw eas.sync.finish("error", "global." + status, "AutoSync disabled until: " + humanDate + " \n\nRequest:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
-
- /* // reset account
- * let folders = syncData.accountData.getAllFoldersIncludingCache();
- * for (let folder of folders) {
- * folder.remove();
- * }
- * // reset account
- * eas.Base.onEnableAccount(syncData.accountData);
- * throw eas.sync.finish("resyncAccount", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
- */
- }
-
- case "141": // The device is not provisionable
- case "142": // DeviceNotProvisioned
- case "143": // PolicyRefresh
- case "144": // InvalidPolicyKey
- //enable provision
- syncData.accountData.setAccountProperty("provision", true);
- syncData.accountData.resetAccountProperty("policykey");
- throw eas.sync.finish("resyncAccount", statusType);
-
- default:
- if (allowSoftFail) return statusType;
- throw eas.sync.finish("error", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
-
- }
- },
-
-
-
-
-
-
-
-
-
-
- // WBXML COMM STUFF
-
- setDeviceInformation: async function (syncData) {
- if (syncData.accountData.getAccountProperty("asversion") == "2.5" || !syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("Settings")) {
- return;
- }
-
- syncData.setSyncState("prepare.request.setdeviceinfo");
-
- let wbxml = wbxmltools.createWBXML();
- wbxml.switchpage("Settings");
- wbxml.otag("Settings");
- wbxml.otag("DeviceInformation");
- wbxml.otag("Set");
- wbxml.atag("Model", "Computer");
- wbxml.atag("FriendlyName", "TbSync on Device " + syncData.accountData.getAccountProperty("deviceId").substring(4));
- wbxml.atag("OS", Services.appinfo.OS);
- wbxml.atag("UserAgent", syncData.accountData.getAccountProperty("useragent"));
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- syncData.setSyncState("send.request.setdeviceinfo");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Settings", syncData);
-
- syncData.setSyncState("eval.response.setdeviceinfo");
- let wbxmlData = eas.network.getDataFromResponse(response);
-
- eas.network.checkStatus(syncData, wbxmlData, "Settings.Status");
- },
-
- getPolicykey: async function (syncData) {
- //build WBXML to request provision
- syncData.setSyncState("prepare.request.provision");
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("Provision");
- wbxml.otag("Provision");
- wbxml.otag("Policies");
- wbxml.otag("Policy");
- wbxml.atag("PolicyType", (syncData.accountData.getAccountProperty("asversion") == "2.5") ? "MS-WAP-Provisioning-XML" : "MS-EAS-Provisioning-WBXML");
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- for (let loop = 0; loop < 2; loop++) {
- syncData.setSyncState("send.request.provision");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Provision", syncData);
-
- syncData.setSyncState("eval.response.provision");
- let wbxmlData = eas.network.getDataFromResponse(response);
- let policyStatus = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Policies.Policy.Status");
- let provisionStatus = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Status");
- if (provisionStatus === false) {
- throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Status");
- } else if (provisionStatus != "1") {
- //dump policy status as well
- if (policyStatus) TbSync.dump("PolicyKey", "Received policy status: " + policyStatus);
- throw eas.sync.finish("error", "provision::" + provisionStatus);
- }
-
- //reaching this point: provision status was ok
- let policykey = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Policies.Policy.PolicyKey");
- switch (policyStatus) {
- case false:
- throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Policies.Policy.Status");
-
- case "2":
- //server does not have a policy for this device: disable provisioning
- syncData.accountData.setAccountProperty("provision", false)
- syncData.accountData.resetAccountProperty("policykey");
- throw eas.sync.finish("resyncAccount", "NoPolicyForThisDevice");
-
- case "1":
- if (policykey === false) {
- throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Policies.Policy.PolicyKey");
- }
- TbSync.dump("PolicyKey", "Received policykey (" + loop + "): " + policykey);
- syncData.accountData.setAccountProperty("policykey", policykey);
- break;
-
- default:
- throw eas.sync.finish("error", "policy." + policyStatus);
- }
-
- //build WBXML to acknowledge provision
- syncData.setSyncState("prepare.request.provision");
- wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("Provision");
- wbxml.otag("Provision");
- wbxml.otag("Policies");
- wbxml.otag("Policy");
- wbxml.atag("PolicyType", (syncData.accountData.getAccountProperty("asversion") == "2.5") ? "MS-WAP-Provisioning-XML" : "MS-EAS-Provisioning-WBXML");
- wbxml.atag("PolicyKey", policykey);
- wbxml.atag("Status", "1");
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- //this wbxml will be used by Send at the top of this loop
- }
- },
-
- getSynckey: async function (syncData) {
- syncData.setSyncState("prepare.request.synckey");
- //build WBXML to request a new syncKey
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.otag("Sync");
- wbxml.otag("Collections");
- wbxml.otag("Collection");
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
- wbxml.atag("SyncKey", "0");
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- syncData.setSyncState("send.request.synckey");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
-
- syncData.setSyncState("eval.response.synckey");
- // get data from wbxml response
- let wbxmlData = eas.network.getDataFromResponse(response);
- //check status
- eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
- //update synckey
- eas.network.updateSynckey(syncData, wbxmlData);
- },
-
- getItemEstimate: async function (syncData) {
- syncData.progressData.reset();
-
- if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("GetItemEstimate")) {
- return; //do not throw, this is optional
- }
-
- syncData.setSyncState("prepare.request.estimate");
-
- // BUILD WBXML
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("GetItemEstimate");
- wbxml.otag("GetItemEstimate");
- wbxml.otag("Collections");
- wbxml.otag("Collection");
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") { //got this order for 2.5 directly from Microsoft support
- wbxml.atag("Class", syncData.type); //only 2.5
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.switchpage("AirSync");
- // required !
- // https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-ascmd/ffbefa62-e315-40b9-9cc6-f8d74b5f65d4
- if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
- else wbxml.atag("FilterType", "0"); // we may filter incomplete tasks
-
- wbxml.atag("SyncKey", syncData.synckey);
- wbxml.switchpage("GetItemEstimate");
- } else { //14.0
- wbxml.switchpage("AirSync");
- wbxml.atag("SyncKey", syncData.synckey);
- wbxml.switchpage("GetItemEstimate");
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.switchpage("AirSync");
- wbxml.otag("Options");
- // optional
- if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
- wbxml.atag("Class", syncData.type);
- wbxml.ctag();
- wbxml.switchpage("GetItemEstimate");
- }
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- //SEND REQUEST
- syncData.setSyncState("send.request.estimate");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "GetItemEstimate", syncData, /* allowSoftFail */ true);
-
- //VALIDATE RESPONSE
- syncData.setSyncState("eval.response.estimate");
-
- // get data from wbxml response, some servers send empty response if there are no changes, which is not an error
- let wbxmlData = eas.network.getDataFromResponse(response, eas.flags.allowEmptyResponse);
- if (wbxmlData === null) return;
-
- let status = eas.xmltools.getWbxmlDataField(wbxmlData, "GetItemEstimate.Response.Status");
- let estimate = eas.xmltools.getWbxmlDataField(wbxmlData, "GetItemEstimate.Response.Collection.Estimate");
-
- if (status && status == "1") { //do not throw on error, with EAS v2.5 I get error 2 for tasks and calendars ???
- syncData.progressData.reset(0, estimate);
- }
- },
-
- getUserInfo: async function (syncData) {
- if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("Settings")) {
- return;
- }
-
- syncData.setSyncState("prepare.request.getuserinfo");
-
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("Settings");
- wbxml.otag("Settings");
- wbxml.otag("UserInformation");
- wbxml.atag("Get");
- wbxml.ctag();
- wbxml.ctag();
-
- syncData.setSyncState("send.request.getuserinfo");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Settings", syncData);
-
-
- syncData.setSyncState("eval.response.getuserinfo");
- let wbxmlData = eas.network.getDataFromResponse(response);
-
- eas.network.checkStatus(syncData, wbxmlData, "Settings.Status");
- },
-
-
-
-
-
-
-
-
-
-
- // SEARCH
-
- getSearchResults: async function (accountData, currentQuery) {
-
- let _wbxml = eas.wbxmltools.createWBXML();
- _wbxml.switchpage("Search");
- _wbxml.otag("Search");
- _wbxml.otag("Store");
- _wbxml.atag("Name", "GAL");
- _wbxml.atag("Query", currentQuery);
- _wbxml.otag("Options");
- _wbxml.atag("Range", "0-99"); //Z-Push needs a Range
- //Not valid for GAL: https://msdn.microsoft.com/en-us/library/gg675461(v=exchg.80).aspx
- //_wbxml.atag("DeepTraversal");
- //_wbxml.atag("RebuildResults");
- _wbxml.ctag();
- _wbxml.ctag();
- _wbxml.ctag();
-
- let wbxml = _wbxml.getBytes();
-
- eas.network.logXML(wbxml, "Send (GAL Search)");
- let command = "Search";
-
- let authData = eas.network.getAuthData(accountData);
- let oauthData = eas.network.getOAuthObj({ accountData });
- let userAgent = accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
- let deviceType = accountData.getAccountProperty("devicetype");
- let deviceId = accountData.getAccountProperty("deviceId");
-
- TbSync.dump("Sending (EAS v" + accountData.getAccountProperty("asversion") + ")", "POST " + eas.network.getEasURL(accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(authData.user) + '&DeviceType=' + deviceType + '&DeviceId=' + deviceId, true);
-
- for (let i = 0; i < 2; i++) {
- // check OAuth situation before connecting
- if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
- let _rv = {}
- if (!(await oauthData.asyncConnect(_rv))) {
- throw eas.sync.finish("error", _rv.error);
- }
- }
-
- try {
- let contextData = eas.network.getContextData({ accountData });
- let uri = Services.io.newURI(eas.network.getEasURL(accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(authData.user) + '&DeviceType=' + encodeURIComponent(deviceType) + '&DeviceId=' + deviceId);
- let response = await new Promise(function (resolve, reject) {
- let req = getSandBoxedXHR(contextData, uri);
- req.mozBackgroundRequest = true;
- req.open("POST", uri.spec, true);
- req.overrideMimeType("text/plain");
- req.setRequestHeader("User-Agent", userAgent);
- req.setRequestHeader("Content-Type", "application/vnd.ms-sync.wbxml");
-
- if (authData.password) {
- if (eas.network.getOAuthObj({ accountData })) {
- req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(authData.password, "access"));
- } else {
- req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(authData.user + ':' + authData.password));
- }
- }
-
- if (accountData.getAccountProperty("asversion") == "2.5") {
- req.setRequestHeader("MS-ASProtocolVersion", "2.5");
- } else {
- req.setRequestHeader("MS-ASProtocolVersion", "14.0");
- }
- req.setRequestHeader("Content-Length", wbxml.length);
- if (accountData.getAccountProperty("provision")) {
- req.setRequestHeader("X-MS-PolicyKey", accountData.getAccountProperty("policykey"));
- TbSync.dump("PolicyKey used", accountData.getAccountProperty("policykey"));
- }
-
- req.timeout = eas.Base.getConnectionTimeout();
-
- req.ontimeout = function () {
- reject("GAL Search timeout");
- };
-
- req.onerror = function () {
- reject("GAL Search Error");
- };
-
- req.onload = function () {
- let response = req.responseText;
-
- switch (req.status) {
-
- case 200: //OK
- eas.network.logXML(response, "Received (GAL Search");
-
- //What to do on error? IS this an error? Yes!
- if (response.length !== 0 && response.substr(0, 4) !== String.fromCharCode(0x03, 0x01, 0x6A, 0x00)) {
- TbSync.dump("Recieved Data", "Expecting WBXML but got junk (request status = " + req.status + ", ready state = " + req.readyState + "\n>>>>>>>>>>\n" + response + "\n<<<<<<<<<<\n");
- reject("GAL Search Response Invalid");
- } else {
- resolve(response);
- }
- break;
-
- case 401: // bad auth
- resolve("401");
- break;
-
- default:
- reject("GAL Search Failed: " + req.status);
- }
- };
-
- req.send(wbxml);
-
- });
-
- if (response === "401") {
- // try to recover from bad auth via token refresh
- if (oauthData) {
- await oauthData.setToken("accessToken", "");
- continue;
- }
- }
-
- return response;
- } catch (e) {
- Components.utils.reportError(e);
- return;
- }
- }
- },
-
-
-
-
-
-
-
-
-
-
- // OPTIONS
-
- getServerOptions: async function (syncData) {
- syncData.setSyncState("prepare.request.options");
- let authData = eas.network.getAuthData(syncData.accountData);
-
- let userAgent = syncData.accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
- TbSync.dump("Sending", "OPTIONS " + eas.network.getEasURL(syncData.accountData));
-
- let allowedRetries = 5;
- let retry;
- let oauthData = eas.network.getOAuthObj({ accountData: syncData.accountData });
-
- do {
- retry = false;
-
- // Check OAuth situation before connecting
- if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
- let _rv = {};
- syncData.setSyncState("oauthprompt");
- if (!(await oauthData.asyncConnect(_rv))) {
- throw eas.sync.finish("error", _rv.error);
- }
- }
-
- let contextData = eas.network.getContextData({ accountData: syncData.accountData });
- let uri = Services.io.newURI(eas.network.getEasURL(syncData.accountData));
- let result = await new Promise(function (resolve, reject) {
- syncData.req = getSandBoxedXHR(contextData, uri);
- syncData.req.mozBackgroundRequest = true;
- syncData.req.open("OPTIONS", uri.spec, true);
- syncData.req.overrideMimeType("text/plain");
- syncData.req.setRequestHeader("User-Agent", userAgent);
- if (authData.password) {
- if (eas.network.getOAuthObj({ accountData: syncData.accountData })) {
- syncData.req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(authData.password, "access"));
- } else {
- syncData.req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(authData.user + ':' + authData.password));
- }
- }
- syncData.req.timeout = eas.Base.getConnectionTimeout();
-
- syncData.req.ontimeout = function () {
- resolve();
- };
-
- syncData.req.onerror = function () {
- let responseData = {};
- responseData["MS-ASProtocolVersions"] = syncData.req.getResponseHeader("MS-ASProtocolVersions");
- responseData["MS-ASProtocolCommands"] = syncData.req.getResponseHeader("MS-ASProtocolCommands");
-
- TbSync.dump("EAS OPTIONS with response (status: " + syncData.req.status + ")", "\n" +
- "responseText: " + syncData.req.responseText + "\n" +
- "responseHeader(MS-ASProtocolVersions): " + responseData["MS-ASProtocolVersions"] + "\n" +
- "responseHeader(MS-ASProtocolCommands): " + responseData["MS-ASProtocolCommands"]);
- resolve();
- };
-
- syncData.req.onload = function () {
- syncData.setSyncState("eval.request.options");
- let responseData = {};
-
- switch (syncData.req.status) {
- case 401: // AuthError
- let rv = {};
- rv.errorObj = eas.sync.finish("error", "401");
- rv.errorType = "PasswordPrompt";
- resolve(rv);
- break;
-
- case 200:
- responseData["MS-ASProtocolVersions"] = syncData.req.getResponseHeader("MS-ASProtocolVersions");
- responseData["MS-ASProtocolCommands"] = syncData.req.getResponseHeader("MS-ASProtocolCommands");
-
- TbSync.dump("EAS OPTIONS with response (status: 200)", "\n" +
- "responseText: " + syncData.req.responseText + "\n" +
- "responseHeader(MS-ASProtocolVersions): " + responseData["MS-ASProtocolVersions"] + "\n" +
- "responseHeader(MS-ASProtocolCommands): " + responseData["MS-ASProtocolCommands"]);
-
- if (responseData && responseData["MS-ASProtocolCommands"] && responseData["MS-ASProtocolVersions"]) {
- syncData.accountData.setAccountProperty("allowedEasCommands", responseData["MS-ASProtocolCommands"]);
- syncData.accountData.setAccountProperty("allowedEasVersions", responseData["MS-ASProtocolVersions"]);
- syncData.accountData.setAccountProperty("lastEasOptionsUpdate", Date.now());
- }
- resolve();
- break;
-
- default:
- resolve();
- break;
-
- }
- };
-
- syncData.setSyncState("send.request.options");
- syncData.req.send();
-
- });
-
- if (result && result.hasOwnProperty("errorType") && result.errorType == "PasswordPrompt") {
- if (allowedRetries > 0) {
- if (oauthData) {
- await oauthData.setToken("accessToken", "");
- retry = true;
- } else {
- syncData.setSyncState("passwordprompt");
- let authData = eas.network.getAuthData(syncData.accountData);
- let promptData = {
- windowID: "auth:" + syncData.accountData.accountID,
- accountname: syncData.accountData.getAccountProperty("accountname"),
- usernameLocked: syncData.accountData.isConnected(),
- username: authData.user
- }
- let credentials = await TbSync.passwordManager.asyncPasswordPrompt(promptData, eas.openWindows);
- if (credentials) {
- await authData.updateLoginData(credentials.username, credentials.password);
- retry = true;
- }
- }
- }
-
- if (!retry) {
- throw result.errorObj;
- }
- }
-
- allowedRetries--;
- } while (retry);
- },
-
-
-
-
-
-
-
-
-
-
- // AUTODISCOVER
-
- updateServerConnectionViaAutodiscover: async function (syncData) {
- syncData.setSyncState("prepare.request.autodiscover");
- let authData = eas.network.getAuthData(syncData.accountData);
-
- syncData.setSyncState("send.request.autodiscover");
- let result = await eas.network.getServerConnectionViaAutodiscover(authData.accountname, authData.user, authData.password, 30 * 1000);
-
- syncData.setSyncState("eval.response.autodiscover");
- if (result.errorcode == 200) {
- //update account
- syncData.accountData.setAccountProperty("host", eas.network.stripAutodiscoverUrl(result.server));
- syncData.accountData.setAccountProperty("user", result.user);
- syncData.accountData.setAccountProperty("https", (result.server.substring(0, 5) == "https"));
- }
-
- return result.errorcode;
- },
-
- stripAutodiscoverUrl: function (url) {
- let u = url;
- while (u.endsWith("/")) { u = u.slice(0, -1); }
- if (u.endsWith("/Microsoft-Server-ActiveSync")) u = u.slice(0, -28);
- else TbSync.dump("Received non-standard EAS url via autodiscover:", url);
-
- return u.split("//")[1]; //cut off protocol
- },
-
- getServerConnectionViaAutodiscover: async function (accountname, user, password, maxtimeout) {
- let urls = [];
- let parts = user.split("@");
-
- urls.push({ "url": "https://autodiscover." + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
- urls.push({ "url": "https://" + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
- urls.push({ "url": "https://autodiscover." + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
- urls.push({ "url": "https://" + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
-
- urls.push({ "url": "http://autodiscover." + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
- urls.push({ "url": "http://" + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
- urls.push({ "url": "http://autodiscover." + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
- urls.push({ "url": "http://" + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
-
- let requests = [];
- let responses = []; //array of objects {url, error, server}
-
- for (let i = 0; i < urls.length; i++) {
- await TbSync.tools.sleep(200);
- requests.push(eas.network.getServerConnectionViaAutodiscoverRedirectWrapper(
- accountname,
- urls[i].url,
- urls[i].user,
- password,
- maxtimeout
- ));
- }
-
- try {
- responses = await Promise.all(requests);
- } catch (e) {
- responses.push(e.result); //this is actually a success, see return value of getServerConnectionViaAutodiscoverRedirectWrapper()
- }
-
- let result;
- let log = [];
- for (let r = 0; r < responses.length; r++) {
- log.push("* " + responses[r].url + " @ " + responses[r].user + " : " + (responses[r].server ? responses[r].server : responses[r].error));
-
- if (responses[r].server) {
- result = { "server": responses[r].server, "user": responses[r].user, "error": "", "errorcode": 200 };
- break;
- }
-
- if (responses[r].error == 403 || responses[r].error == 401) {
- //we could still find a valid server, so just store this state
- result = { "server": "", "user": responses[r].user, "errorcode": responses[r].error, "error": TbSync.getString("status." + responses[r].error, "eas") };
- }
- }
-
- //this is only reached on fail, if no result defined yet, use general error
- if (!result) {
- result = { "server": "", "user": user, "error": TbSync.getString("autodiscover.Failed", "eas").replace("##user##", user), "errorcode": 503 };
- }
-
- TbSync.eventlog.add("error", new TbSync.EventLogInfo("eas"), result.error, log.join("\n"));
- return result;
- },
-
- getServerConnectionViaAutodiscoverRedirectWrapper: async function (accountname, url, user, password, maxtimeout) {
- let result = {};
- let method = "POST";
- let connection = { accountname, url, user };
-
- do {
- await TbSync.tools.sleep(200);
- result = await eas.network.getServerConnectionViaAutodiscoverRequest(method, connection, password, maxtimeout);
- method = "";
-
- if (result.error == "redirect found") {
- TbSync.dump("EAS autodiscover URL redirect", "\n" + connection.url + " @ " + connection.user + " => \n" + result.url + " @ " + result.user);
- connection.url = result.url;
- connection.user = result.user;
- method = "POST";
- }
-
- } while (method);
-
- //invert reject and resolve, so we exit the promise group on success right away
- if (result.server) {
- let e = new Error("Not an error (early exit from promise group)");
- e.result = result;
- throw e;
- } else {
- return result;
- }
- },
-
- getServerConnectionViaAutodiscoverRequest: function (method, connection, password, maxtimeout) {
- TbSync.dump("Querry EAS autodiscover URL", connection.url + " @ " + connection.user);
-
- return new Promise(function (resolve, reject) {
-
- let xml = '\r\n';
- xml += '\r\n';
- xml += '\r\n';
- xml += '' + connection.user + '\r\n';
- xml += 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006\r\n';
- xml += '\r\n';
- xml += '\r\n';
-
- let userAgent = eas.prefs.getCharPref("clientID.useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
- let uri = Services.io.newURI(connection.url);
- let req = getSandBoxedXHR(connection, uri);
- req.mozBackgroundRequest = true;
- req.open(method, uri.spec, true);
- req.timeout = maxtimeout;
- req.setRequestHeader("User-Agent", userAgent);
-
- let secure = (connection.url.substring(0, 8).toLowerCase() == "https://");
-
- if (method == "POST") {
- req.setRequestHeader("Content-Length", xml.length);
- req.setRequestHeader("Content-Type", "text/xml");
- if (secure && password) {
- // OAUTH accounts cannot authenticate against the standard discovery services
- // updateServerConnectionViaAutodiscover() is not passing them on
- req.setRequestHeader("Authorization", "Basic " + TbSync.tools.b64encode(connection.user + ":" + password));
- }
- }
-
- req.ontimeout = function () {
- TbSync.dump("EAS autodiscover with timeout", "\n" + connection.url + " => \n" + req.responseURL);
- resolve({ "url": req.responseURL, "error": "timeout", "server": "", "user": connection.user });
- };
-
- req.onerror = function () {
- let error = TbSync.network.createTCPErrorFromFailedXHR(req);
- if (!error) error = req.responseText;
-
- // CORS violations can happen on redirects. They come back as NS_ERROR_DOM_BAD_URI.
- if (error == "network::NS_ERROR_DOM_BAD_URI" && req.channel.URI.spec != uri.spec) {
- resolve({ "url": req.channel.URI.spec, "error": "redirect found", "server": "", "user": connection.user });
- return;
- }
-
- TbSync.dump("EAS autodiscover with error (" + error + ")", "\n" + connection.url + " => \n" + req.responseURL);
- resolve({ "url": req.responseURL, "error": error, "server": "", "user": connection.user });
- };
-
- req.onload = function () {
- //initiate rerun on redirects
- if (req.responseURL != connection.url) {
- resolve({ "url": req.responseURL, "error": "redirect found", "server": "", "user": connection.user });
- return;
- }
-
- //ignore POST without autherization (we just do them to get redirect information)
- if (!secure) {
- resolve({ "url": req.responseURL, "error": "unsecure POST", "server": "", "user": connection.user });
- return;
- }
-
- //evaluate secure POST requests which have not been redirected
- TbSync.dump("EAS autodiscover POST with status (" + req.status + ")", "\n" + connection.url + " => \n" + req.responseURL + "\n[" + req.responseText + "]");
-
- if (req.status === 200) {
- let data = null;
- // getDataFromXMLString may throw an error which cannot be catched outside onload,
- // because we are in an async callback of the surrounding Promise
- // Alternatively we could just return the responseText and do any data analysis outside of the Promise
- try {
- data = eas.xmltools.getDataFromXMLString(req.responseText);
- } catch (e) {
- resolve({ "url": req.responseURL, "error": "bad response", "server": "", "user": connection.user });
- return;
- }
-
- if (!(data === null) && data.Autodiscover && data.Autodiscover.Response && data.Autodiscover.Response.Action) {
- // "Redirect" or "Settings" are possible
- if (data.Autodiscover.Response.Action.Redirect) {
- // redirect, start again with new user
- let newuser = action.Redirect;
- resolve({ "url": req.responseURL, "error": "redirect found", "server": "", "user": newuser });
-
- } else if (data.Autodiscover.Response.Action.Settings) {
- // get server settings
- let server = eas.xmltools.nodeAsArray(data.Autodiscover.Response.Action.Settings.Server);
-
- for (let count = 0; count < server.length; count++) {
- if (server[count].Type == "MobileSync" && server[count].Url) {
- resolve({ "url": req.responseURL, "error": "", "server": server[count].Url, "user": connection.user });
- return;
- }
- }
- }
- } else {
- resolve({ "url": req.responseURL, "error": "invalid", "server": "", "user": connection.user });
- }
- } else {
- resolve({ "url": req.responseURL, "error": req.status, "server": "", "user": connection.user });
- }
- };
-
- req.send(xml);
- });
- },
-
- getServerConnectionViaAutodiscoverV2JsonRequest: function (accountname, user, url, maxtimeout) {
- TbSync.dump("Querry EAS autodiscover V2 URL", url);
-
- return new Promise(function (resolve, reject) {
-
- let userAgent = eas.prefs.getCharPref("clientID.useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
- let uri = Services.io.newURI(url);
- let req = getSandBoxedXHR({ accountname, user }, uri);
- req.mozBackgroundRequest = true;
- req.open("GET", uri.spec, true);
- req.timeout = maxtimeout;
- req.setRequestHeader("User-Agent", userAgent);
-
- req.ontimeout = function () {
- TbSync.dump("EAS autodiscover V2 with timeout", "\n" + url + " => \n" + req.responseURL);
- resolve({ "url": req.responseURL, "error": "timeout", "server": "" });
- };
-
- req.onerror = function () {
- let error = TbSync.network.createTCPErrorFromFailedXHR(req);
- if (!error) error = req.responseText;
- TbSync.dump("EAS autodiscover V2 with error (" + error + ")", "\n" + url + " => \n" + req.responseURL);
- resolve({ "url": req.responseURL, "error": error, "server": "" });
- };
-
- req.onload = function () {
- if (req.status === 200) {
- let data = JSON.parse(req.responseText);
-
- if (data && data.Url) {
- resolve({ "url": req.responseURL, "error": "", "server": eas.network.stripAutodiscoverUrl(data.Url) });
- } else {
- resolve({ "url": req.responseURL, "error": "invalid", "server": "" });
- }
- return;
- }
-
- resolve({ "url": req.responseURL, "error": req.status, "server": "" });
- };
-
- req.send();
- });
- }
-}
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+var { OAuth2 } = ChromeUtils.importESModule(
+ "resource:///modules/OAuth2.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+var containers = [];
+var sandboxes = {};
+
+function resetContainerWithId(id) {
+ Services.clearData.deleteDataFromOriginAttributesPattern({ userContextId: id });
+}
+
+function getContainerIdForContainerName(containerName) {
+ // Define the allowed range of container ids to be used
+ // TbSync is using 10000 - 19999
+ // Lightning is using 20000 - 29999
+ // Cardbook is using 30000 - 39999
+ let min = 10000;
+ let max = 19999;
+
+ //reset if adding an entry will exceed allowed range
+ if (containers.length > (max - min) && containers.indexOf(containerName) == -1) {
+ for (let i = 0; i < containers.length; i++) {
+ resetContainerWithId(i + min);
+ }
+ containers = [];
+ }
+
+ let idx = containers.indexOf(containerName);
+ return (idx == -1) ? containers.push(containerName) - 1 + min : (idx + min);
+}
+
+function getSandBoxedXHR({ user, accountname }, uri, containerReset = false) {
+ // The content principal used for the sandbox honours CORS. A server redirect
+ // to a different server may cause CORS violations. We implemented code to
+ // catch such redirects and re-run the request with the correct sandbox. If
+ // that becomes an issue, we need to make sandboxing optional.
+ // return new XMLHttpRequest({ mozAnon: false });
+
+ let containerName = `${accountname}::${user}@${uri.scheme}://${uri.hostPort}`;
+
+ let userContextId = getContainerIdForContainerName(containerName);
+ if (containerReset) {
+ resetContainerWithId(userContextId);
+ }
+
+ // Pre-set cookie needed by eas.outlook.com. The cookie is returned with each
+ // server response, but is is SameSite=None without the secure flag being set
+ // and ignored.
+ if (uri.host == "eas.outlook.com") {
+ Services.cookies.add(
+ "eas.outlook.com",
+ "/",
+ "DefaultAnchorMailbox",
+ user,
+ /* isSecure */ true,
+ /* isHttponly */ false,
+ /* isSession = */ false,
+ /* expiry */ Number.MAX_SAFE_INTEGER,
+ { userContextId },
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTPS,
+ /* partitioned */ false
+ );
+ }
+ if (!sandboxes.hasOwnProperty(containerName)) {
+ console.log("Creating sandbox for <" + containerName + ">");
+ let principal = Services.scriptSecurityManager.createContentPrincipal(uri, { userContextId });
+ sandboxes[containerName] = Components.utils.Sandbox(principal, {
+ wantXrays: true,
+ wantGlobalProperties: ["XMLHttpRequest"],
+ });
+ }
+ return new sandboxes[containerName].XMLHttpRequest({ mozAnon: false });
+}
+
+var network = {
+
+ getEasURL: function (accountData) {
+ let protocol = (accountData.getAccountProperty("https")) ? "https://" : "http://";
+ let h = protocol + accountData.getAccountProperty("host");
+ while (h.endsWith("/")) { h = h.slice(0, -1); }
+
+ if (h.endsWith("Microsoft-Server-ActiveSync")) return h;
+ return h + "/Microsoft-Server-ActiveSync";
+ },
+
+ getAuthData: function (accountData) {
+ let authData = {
+ // This is the host for the password manager, which could be different from
+ // the actual host property of the account. For EAS we want to couple the password
+ // with the ACCOUNT and not any sort of url, which could change via autodiscover
+ // at any time.
+ get host() {
+ return "TbSync#" + accountData.accountID;
+ },
+
+ get user() {
+ return accountData.getAccountProperty("user");
+ },
+
+ get password() {
+ return TbSync.passwordManager.getLoginInfo(this.host, "TbSync/EAS", this.user);
+ },
+
+ get accountname() {
+ return accountData.getAccountProperty("accountname");
+ },
+
+ updateLoginData: async function (newUsername, newPassword) {
+ let oldUsername = this.user;
+ await TbSync.passwordManager.updateLoginInfo(this.host, "TbSync/EAS", oldUsername, newUsername, newPassword);
+ // Also update the username of this account. Add dedicated username setter?
+ accountData.setAccountProperty("user", newUsername);
+ },
+
+ removeLoginData: function () {
+ TbSync.passwordManager.removeLoginInfos(this.host, "TbSync/EAS");
+ }
+ };
+ return authData;
+ },
+
+ getContextData: function (configObject = null) {
+ let contextData = {}
+ contextData.accountData = (configObject && configObject.hasOwnProperty("accountData")) ? configObject.accountData : null;
+
+ if (contextData.accountData) {
+ contextData.accountname = contextData.accountData.getAccountProperty("accountname");
+ contextData.user = contextData.accountData.getAccountProperty("user");
+ contextData.host = contextData.accountData.getAccountProperty("host");
+ contextData.servertype = contextData.accountData.getAccountProperty("servertype");
+ contextData.accountID = contextData.accountData.accountID;
+ } else {
+ contextData.accountname = (configObject && configObject.hasOwnProperty("accountname")) ? configObject.accountname : "";
+ contextData.user = (configObject && configObject.hasOwnProperty("user")) ? configObject.user : "";
+ contextData.host = (configObject && configObject.hasOwnProperty("host")) ? configObject.host : "";
+ contextData.servertype = (configObject && configObject.hasOwnProperty("servertype")) ? configObject.servertype : "";
+ contextData.accountID = "";
+ }
+
+ return contextData;
+ },
+
+ // prepare and patch OAuth2 object
+ getOAuthObj: function (configObject = null) {
+ let {
+ accountData,
+ accountname,
+ user,
+ host,
+ accountID,
+ servertype
+ } = this.getContextData(configObject);
+
+ if (!["office365"].includes(servertype))
+ return null;
+
+ let config = {};
+ let customID = eas.Base.getCustomeOauthClientID();
+ switch (host) {
+ case "outlook.office365.com":
+ case "eas.outlook.com":
+ config = {
+ auth_uri: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
+ token_uri: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
+ redirect_uri: "https://login.microsoftonline.com/common/oauth2/nativeclient",
+ client_id: customID != "" ? customID : "2980deeb-7460-4723-864a-f9b0f10cd992",
+ }
+ break;
+
+ default:
+ return null;
+ }
+
+ switch (host) {
+ case "outlook.office365.com":
+ config.scope = "offline_access https://outlook.office.com/.default";
+ break;
+ case "eas.outlook.com":
+ config.scope = "offline_access https://outlook.office.com/EAS.AccessAsUser.All";
+ break;
+ }
+
+ let oauth = new OAuth2(config.scope, {
+ authorizationEndpoint: config.auth_uri,
+ tokenEndpoint: config.token_uri,
+ clientId: config.client_id,
+ clientSecret: config.client_secret
+ });
+ oauth.requestWindowFeatures = "chrome,private,centerscreen,width=500,height=750";
+
+ // The v2 redirection endpoint differs from the default and needs manual override
+ oauth.redirectionEndpoint = config.redirect_uri;
+
+ oauth.extraAuthParams = [
+ // removed in beta 1.14.1, according to
+ // https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#default-and-consent
+ // prompt = consent will always ask for admin consent, even if it was granted
+ //["prompt", "consent"],
+ ["login_hint", user],
+ ];
+
+ if (accountname) {
+ oauth.requestWindowTitle = "TbSync account <" + accountname + "> requests authorization.";
+ } else {
+ oauth.requestWindowTitle = "A TbSync account requests authorization.";
+ }
+
+
+
+
+ /* Adding custom methods to the oauth object */
+
+ oauth.asyncConnect = async function (rv) {
+ rv.error = "";
+ // This function gets called if we have no accessToken, or the token
+ // is expired. Load current data from password manager into the
+ // properties used by the OAuth module.
+ oauth.accessToken = oauth.getToken("accessToken");
+ oauth.refreshToken = oauth.getToken("refreshToken");
+ oauth.tokenExpires = oauth.getToken("tokenExpires");
+
+ try {
+ // refresh = false will do nothing and resolve immediately, if
+ // a valid accessToken exists.
+ await oauth.connect(/* with UI */ true, /* refresh */ false);
+ } catch (e) {
+ rv.error = eas.tools.isString(e) ? e : JSON.stringify(e);
+ }
+
+ await oauth.setToken("accessToken", oauth.accessToken);
+ await oauth.setToken("refreshToken", oauth.refreshToken);
+ await oauth.setToken("tokenExpires", oauth.tokenExpires);
+ rv.tokens = oauth.tokens;
+
+ if (!rv.error) {
+ return true;
+ }
+
+ try {
+ switch (JSON.parse(rv.error).error) {
+ case "invalid_grant":
+ await oauth.setToken("accessToken", "");
+ await oauth.setToken("refreshToken", "");
+ await oauth.setToken("tokenExpires", 0);
+ rv.tokens = oauth.tokens;
+ return true;
+
+ case "cancelled":
+ rv.error = "OAuthAbortError";
+ break;
+
+ default:
+ rv.error = "OAuthServerError::" + rv.error;
+ break;
+ }
+ } catch (e) {
+ rv.error = "OAuthServerError::" + rv.error;
+ Components.utils.reportError(e);
+ }
+ rv.tokens = oauth.tokens;
+ return false;
+ };
+
+ oauth.isExpired = function () {
+ const OAUTH_GRACE_TIME = 30 * 1000;
+ return (oauth.getToken("tokenExpires") - OAUTH_GRACE_TIME < new Date().getTime());
+ };
+
+ const OAUTHVALUES = [
+ ["access", "", "accessToken"],
+ ["refresh", "", "refreshToken"],
+ ["expires", Number.MAX_VALUE, "tokenExpires"],
+ ];
+
+ // returns a JSON string containing all the oauth values
+ Object.defineProperty(oauth, "tokens", {
+ get: function () {
+ let tokensObj = {};
+ for (let oauthValue of OAUTHVALUES) {
+ // use the system value or if not defined the default
+ tokensObj[oauthValue[0]] = this[oauthValue[2]] || oauthValue[1];
+ }
+ return JSON.stringify(tokensObj);
+ },
+ enumerable: true,
+ });
+
+ if (accountData) {
+ // authData allows us to access the password manager values belonging to this account/calendar
+ // simply by authdata.username and authdata.password
+ oauth.authData = TbSync.providers.eas.network.getAuthData(accountData);
+
+ oauth.parseAndSanitizeTokenString = function (tokenString) {
+ let _tokensObj = {};
+ try {
+ _tokensObj = JSON.parse(tokenString);
+ } catch (e) { }
+
+ let tokensObj = {};
+ for (let oauthValue of OAUTHVALUES) {
+ // use the provided value or if not defined the default
+ tokensObj[oauthValue[0]] = (_tokensObj && _tokensObj.hasOwnProperty(oauthValue[0]))
+ ? _tokensObj[oauthValue[0]]
+ : oauthValue[1];
+ }
+ return tokensObj;
+ };
+
+ oauth.getToken = function (tokenName) {
+ let oauthValue = OAUTHVALUES.find(e => e[2] == tokenName);
+ return oauth.parseAndSanitizeTokenString(oauth.authData.password)[oauthValue[0]];
+ };
+
+ oauth.setToken = async function (tokenName, val) {
+ oauth[tokenName] = val;
+
+ let oauthValue = OAUTHVALUES.find(e => e[2] == tokenName);
+ let tokens = oauth.parseAndSanitizeTokenString(oauth.authData.password);
+ let valueChanged = (val != tokens[oauthValue[0]])
+ if (valueChanged) {
+ tokens[oauthValue[0]] = val;
+ await oauth.authData.updateLoginData(oauth.authData.user, JSON.stringify(tokens));
+ }
+ };
+ } else {
+ oauth.getToken = function (tokenName) {
+ return oauth[tokenName];
+ };
+
+ oauth.setToken = async function (tokenName, val) {
+ oauth[tokenName] = val;
+ };
+ }
+
+ return oauth;
+ },
+
+ getOAuthValue: function (currentTokenString, type = "access") {
+ try {
+ let tokens = JSON.parse(currentTokenString);
+ if (tokens.hasOwnProperty(type))
+ return tokens[type];
+ } catch (e) {
+ //NOOP
+ }
+ return "";
+ },
+
+ sendRequest: async function (wbxml, command, syncData, allowSoftFail = false) {
+ let ALLOWED_RETRIES = {
+ PasswordPrompt: 3,
+ NetworkError: 1,
+ }
+
+ let rv = {};
+ let oauthData = eas.network.getOAuthObj({ accountData: syncData.accountData });
+ let syncState = syncData.getSyncState().state;
+
+ for (; ;) {
+
+ if (rv.errorType) {
+ let retry = false;
+
+ if (ALLOWED_RETRIES[rv.errorType] > 0) {
+ ALLOWED_RETRIES[rv.errorType]--;
+
+
+ switch (rv.errorType) {
+
+ case "PasswordPrompt":
+ {
+
+ if (oauthData) {
+ await oauthData.setToken("accessToken", "");
+ retry = true;
+ } else {
+ let authData = eas.network.getAuthData(syncData.accountData);
+ syncData.setSyncState("passwordprompt");
+ let promptData = {
+ windowID: "auth:" + syncData.accountData.accountID,
+ accountname: syncData.accountData.getAccountProperty("accountname"),
+ usernameLocked: syncData.accountData.isConnected(),
+ username: authData.user
+ }
+ let credentials = await TbSync.passwordManager.asyncPasswordPrompt(promptData, eas.openWindows);
+ if (credentials) {
+ retry = true;
+ await authData.updateLoginData(credentials.username, credentials.password);
+ }
+ }
+ }
+ break;
+
+ case "NetworkError":
+ {
+ // Could not connect to server. Can we rerun autodiscover?
+ // Note: Autodiscover is currently not supported by OAuth
+ if (syncData.accountData.getAccountProperty("servertype") == "auto" && !oauthData) {
+ let errorcode = await eas.network.updateServerConnectionViaAutodiscover(syncData);
+ console.log("ERR: " + errorcode);
+ if (errorcode == 200) {
+ // autodiscover succeeded, retry with new data
+ retry = true;
+ } else if (errorcode == 401) {
+ // manipulate rv to run password prompt
+ ALLOWED_RETRIES[rv.errorType]++;
+ rv.errorType = "PasswordPrompt";
+ rv.errorObj = eas.sync.finish("error", "401");
+ continue; // with the next loop, skip connection to the server
+ }
+ }
+ }
+ break;
+
+ }
+ }
+
+ if (!retry) throw rv.errorObj;
+ }
+
+ // check OAuth situation before connecting
+ if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
+ syncData.setSyncState("oauthprompt");
+ let _rv = {}
+ if (!(await oauthData.asyncConnect(_rv))) {
+ throw eas.sync.finish("error", _rv.error);
+ }
+ }
+
+ // Return to original syncstate
+ if (syncState != syncData.getSyncState().state) {
+ syncData.setSyncState(syncState);
+ }
+ rv = await this.sendRequestPromise(wbxml, command, syncData, allowSoftFail);
+
+ if (rv.errorType) {
+ // make sure, there is a valid ALLOWED_RETRIES setting for the returned error
+ if (rv.errorType && !ALLOWED_RETRIES.hasOwnProperty(rv.errorType)) {
+ ALLOWED_RETRIES[rv.errorType] = 1;
+ }
+ } else {
+ return rv;
+ }
+ }
+ },
+
+ sendRequestPromise: function (wbxml, command, syncData, allowSoftFail = false) {
+ let msg = "Sending data <" + syncData.getSyncState().state + "> for " + syncData.accountData.getAccountProperty("accountname");
+ if (syncData.currentFolderData) msg += " (" + syncData.currentFolderData.getFolderProperty("foldername") + ")";
+ syncData.request = eas.network.logXML(wbxml, msg);
+ syncData.response = "";
+
+ let connection = eas.network.getAuthData(syncData.accountData);
+ let userAgent = syncData.accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
+ let deviceType = syncData.accountData.getAccountProperty("devicetype");
+ let deviceId = syncData.accountData.getAccountProperty("deviceId");
+
+ TbSync.dump("Sending (EAS v" + syncData.accountData.getAccountProperty("asversion") + ")", "POST " + eas.network.getEasURL(syncData.accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(connection.user) + '&DeviceType=' + deviceType + '&DeviceId=' + deviceId, true);
+
+ const textEncoder = new TextEncoder();
+ let encoded = textEncoder.encode(wbxml);
+ // console.log("wbxml: " + wbxml);
+ // console.log("byte array: " + encoded);
+ // console.log("length :" + wbxml.length + " vs " + encoded.byteLength + " vs " + encoded.length);
+
+ let contextData = eas.network.getContextData({ accountData: syncData.accountData });
+ let uri = Services.io.newURI(eas.network.getEasURL(syncData.accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(connection.user) + '&DeviceType=' + encodeURIComponent(deviceType) + '&DeviceId=' + deviceId);
+ return new Promise(function (resolve, reject) {
+ syncData.req = getSandBoxedXHR(contextData, uri);
+ syncData.req.mozBackgroundRequest = true;
+ syncData.req.open("POST", uri.spec, true);
+ syncData.req.overrideMimeType("text/plain");
+ syncData.req.setRequestHeader("User-Agent", userAgent);
+ syncData.req.setRequestHeader("Content-Type", "application/vnd.ms-sync.wbxml");
+ if (connection.password) {
+ if (eas.network.getOAuthObj({ accountData: syncData.accountData })) {
+ syncData.req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(connection.password, "access"));
+ } else {
+ syncData.req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(connection.user + ':' + connection.password));
+ }
+ }
+
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") {
+ syncData.req.setRequestHeader("MS-ASProtocolVersion", "2.5");
+ } else {
+ syncData.req.setRequestHeader("MS-ASProtocolVersion", "14.0");
+ }
+ syncData.req.setRequestHeader("Content-Length", encoded.length);
+ if (syncData.accountData.getAccountProperty("provision")) {
+ syncData.req.setRequestHeader("X-MS-PolicyKey", syncData.accountData.getAccountProperty("policykey"));
+ TbSync.dump("PolicyKey used", syncData.accountData.getAccountProperty("policykey"));
+ }
+
+ syncData.req.timeout = eas.Base.getConnectionTimeout();
+
+ syncData.req.ontimeout = function () {
+ if (allowSoftFail) {
+ resolve("");
+ } else {
+ reject(eas.sync.finish("error", "timeout"));
+ }
+ };
+
+ syncData.req.onerror = function () {
+ if (allowSoftFail) {
+ resolve("");
+ } else {
+ let error = TbSync.network.createTCPErrorFromFailedXHR(syncData.req) || "networkerror";
+ let rv = {};
+ rv.errorObj = eas.sync.finish("error", error);
+ rv.errorType = "NetworkError";
+ resolve(rv);
+ }
+ };
+
+ syncData.req.onload = function () {
+ let response = syncData.req.responseText;
+
+ // Debug: Log received cookies.
+ const channel = syncData.req.channel.QueryInterface(Ci.nsIHttpChannel);
+ const SET_COOKIE_REGEXP = /set-cookie/i;
+ channel.visitOriginalResponseHeaders({
+ visitHeader(name, value) {
+ if (SET_COOKIE_REGEXP.test(name)) {
+ console.log("Received cookie", value);
+ }
+ },
+ });
+
+ switch (syncData.req.status) {
+
+ case 200: //OK
+ let msg = "Receiving data <" + syncData.getSyncState().state + "> for " + syncData.accountData.getAccountProperty("accountname");
+ if (syncData.currentFolderData) msg += " (" + syncData.currentFolderData.getFolderProperty("foldername") + ")";
+ syncData.response = eas.network.logXML(response, msg);
+
+ //What to do on error? IS this an error? Yes!
+ if (!allowSoftFail && response.length !== 0 && response.substr(0, 4) !== String.fromCharCode(0x03, 0x01, 0x6A, 0x00)) {
+ TbSync.dump("Recieved Data", "Expecting WBXML but got junk (request status = " + syncData.req.status + ", ready state = " + syncData.req.readyState + "\n>>>>>>>>>>\n" + response + "\n<<<<<<<<<<\n");
+ reject(eas.sync.finish("warning", "invalid"));
+ } else {
+ resolve(response);
+ }
+ break;
+
+ case 401: // AuthError
+ case 403: // Forbiddden (some servers send forbidden on AuthError, like Freenet)
+ let rv = {};
+ rv.errorObj = eas.sync.finish("error", "401");
+ rv.errorType = "PasswordPrompt";
+ resolve(rv);
+ break;
+
+ case 449: // Request for new provision (enable it if needed)
+ //enable provision
+ syncData.accountData.setAccountProperty("provision", true);
+ syncData.accountData.resetAccountProperty("policykey");
+ reject(eas.sync.finish("resyncAccount", syncData.req.status));
+ break;
+
+ case 451: // Redirect - update host and login manager
+ let header = syncData.req.getResponseHeader("X-MS-Location");
+ let newHost = header.slice(header.indexOf("://") + 3, header.indexOf("/M"));
+
+ TbSync.dump("redirect (451)", "header: " + header + ", oldHost: " + syncData.accountData.getAccountProperty("host") + ", newHost: " + newHost);
+
+ syncData.accountData.setAccountProperty("host", newHost);
+ reject(eas.sync.finish("resyncAccount", syncData.req.status));
+ break;
+
+ default:
+ if (allowSoftFail) {
+ resolve("");
+ } else {
+ reject(eas.sync.finish("error", "httperror::" + syncData.req.status));
+ }
+ }
+ };
+
+ syncData.req.send(encoded);
+
+ });
+ },
+
+
+
+
+
+
+
+
+
+
+ // RESPONSE EVALUATION
+
+ logXML: function (wbxml, what) {
+ let rawxml = eas.wbxmltools.convert2xml(wbxml);
+ let xml = null;
+ if (rawxml) {
+ xml = rawxml.split('><').join('>\n<');
+ }
+
+ //include xml in log, if userdatalevel 2 or greater
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 1) {
+
+ //log raw wbxml if userdatalevel is 3 or greater
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) {
+ let charcodes = [];
+ for (let i = 0; i < wbxml.length; i++) charcodes.push(wbxml.charCodeAt(i).toString(16));
+ let bytestring = charcodes.join(" ");
+ TbSync.dump("WBXML: " + what, "\n" + bytestring);
+ }
+
+ if (xml) {
+ //raw xml is save xml with all special chars in user data encoded by encodeURIComponent - KEEP that in order to be able to analyze logged XML
+ //let xml = decodeURIComponent(rawxml.split('><').join('>\n<'));
+ TbSync.dump("XML: " + what, "\n" + xml);
+ } else {
+ TbSync.dump("XML: " + what, "\nFailed to convert WBXML to XML!\n");
+ }
+ }
+
+ return xml;
+ },
+
+ //returns false on parse error and null on empty response (if allowed)
+ getDataFromResponse: function (wbxml, allowEmptyResponse = !eas.flags.allowEmptyResponse) {
+ //check for empty wbxml
+ if (wbxml.length === 0) {
+ if (allowEmptyResponse) return null;
+ else throw eas.sync.finish("warning", "empty-response");
+ }
+
+ //convert to save xml (all special chars in user data encoded by encodeURIComponent) and check for parse errors
+ let xml = eas.wbxmltools.convert2xml(wbxml);
+ if (xml === false) {
+ throw eas.sync.finish("warning", "wbxml-parse-error");
+ }
+
+ //retrieve data and check for empty data (all returned data fields are already decoded by decodeURIComponent)
+ let wbxmlData = eas.xmltools.getDataFromXMLString(xml);
+ if (wbxmlData === null) {
+ if (allowEmptyResponse) return null;
+ else throw eas.sync.finish("warning", "response-contains-no-data");
+ }
+
+ //debug
+ eas.xmltools.printXmlData(wbxmlData, false); //do not include ApplicationData in log
+ return wbxmlData;
+ },
+
+ updateSynckey: function (syncData, wbxmlData) {
+ let synckey = eas.xmltools.getWbxmlDataField(wbxmlData, "Sync.Collections.Collection.SyncKey");
+
+ if (synckey) {
+ // This COULD be a cause of problems...
+ syncData.synckey = synckey;
+ syncData.currentFolderData.setFolderProperty("synckey", synckey);
+ } else {
+ throw eas.sync.finish("error", "wbxmlmissingfield::Sync.Collections.Collection.SyncKey");
+ }
+ },
+
+ checkStatus: function (syncData, wbxmlData, path, rootpath = "", allowSoftFail = false) {
+ //path is relative to wbxmlData
+ //rootpath is the absolute path and must be specified, if wbxml is not the root node and thus path is not the rootpath
+ let status = eas.xmltools.getWbxmlDataField(wbxmlData, path);
+ let fullpath = (rootpath == "") ? path : rootpath;
+ let elements = fullpath.split(".");
+ let type = elements[0];
+
+ //check if fallback to main class status: the answer could just be a "Sync.Status" instead of a "Sync.Collections.Collections.Status"
+ if (status === false) {
+ let mainStatus = eas.xmltools.getWbxmlDataField(wbxmlData, type + "." + elements[elements.length - 1]);
+ if (mainStatus === false) {
+ //both possible status fields are missing, abort
+ throw eas.sync.finish("warning", "wbxmlmissingfield::" + fullpath, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+ } else {
+ //the alternative status could be extracted
+ status = mainStatus;
+ fullpath = type + "." + elements[elements.length - 1];
+ }
+ }
+
+ //check if all is fine (not bad)
+ if (status == "1") {
+ return "";
+ }
+
+ TbSync.dump("wbxml status check", type + ": " + fullpath + " = " + status);
+
+ //handle errrors based on type
+ let statusType = type + "." + status;
+ switch (statusType) {
+ case "Sync.3": /*
+ MUST return to SyncKey element value of 0 for the collection. The client SHOULD either delete any items that were added
+ since the last successful Sync or the client MUST add those items back to the server after completing the full resynchronization
+ */
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "Forced Folder Resync", "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+ syncData.currentFolderData.remove();
+ throw eas.sync.finish("resyncFolder", statusType);
+
+ case "Sync.4": //Malformed request
+ case "Sync.5": //Temporary server issues or invalid item
+ case "Sync.6": //Invalid item
+ case "Sync.8": //Object not found
+ if (allowSoftFail) return statusType;
+ throw eas.sync.finish("warning", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+
+ case "Sync.7": //The client has changed an item for which the conflict policy indicates that the server's changes take precedence.
+ case "Sync.9": //User account could be out of disk space, also send if no write permission (TODO)
+ return "";
+
+ case "FolderDelete.3": // special system folder - fatal error
+ case "FolderDelete.6": // error on server
+ throw eas.sync.finish("warning", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+
+ case "FolderDelete.4": // folder does not exist - resync ( we allow delete only if folder is not subscribed )
+ case "FolderDelete.9": // invalid synchronization key - resync
+ case "FolderSync.9": // invalid synchronization key - resync
+ case "Sync.12": // folder hierarchy changed
+ {
+ let folders = syncData.accountData.getAllFoldersIncludingCache();
+ for (let folder of folders) {
+ folder.remove();
+ }
+ // reset account
+ eas.Base.onEnableAccount(syncData.accountData);
+ throw eas.sync.finish("resyncAccount", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+ }
+ }
+
+ //handle global error (https://msdn.microsoft.com/en-us/library/ee218647(v=exchg.80).aspx)
+ let descriptions = {};
+ switch (status) {
+ case "101": //invalid content
+ case "102": //invalid wbxml
+ case "103": //invalid xml
+ throw eas.sync.finish("error", "global." + status, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+
+ case "109": descriptions["109"] = "DeviceTypeMissingOrInvalid";
+ case "112": descriptions["112"] = "ActiveDirectoryAccessDenied";
+ case "126": descriptions["126"] = "UserDisabledForSync";
+ case "127": descriptions["127"] = "UserOnNewMailboxCannotSync";
+ case "128": descriptions["128"] = "UserOnLegacyMailboxCannotSync";
+ case "129": descriptions["129"] = "DeviceIsBlockedForThisUser";
+ case "130": descriptions["120"] = "AccessDenied";
+ case "131": descriptions["131"] = "AccountDisabled";
+ throw eas.sync.finish("error", "global.clientdenied" + "::" + status + "::" + descriptions[status]);
+
+ case "110": //server error - abort and disable autoSync for 30 minutes
+ {
+ let noAutosyncUntil = 30 * 60000 + Date.now();
+ let humanDate = new Date(noAutosyncUntil).toUTCString();
+ syncData.accountData.setAccountProperty("noAutosyncUntil", noAutosyncUntil);
+ throw eas.sync.finish("error", "global." + status, "AutoSync disabled until: " + humanDate + " \n\nRequest:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+
+ /* // reset account
+ * let folders = syncData.accountData.getAllFoldersIncludingCache();
+ * for (let folder of folders) {
+ * folder.remove();
+ * }
+ * // reset account
+ * eas.Base.onEnableAccount(syncData.accountData);
+ * throw eas.sync.finish("resyncAccount", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+ */
+ }
+
+ case "141": // The device is not provisionable
+ case "142": // DeviceNotProvisioned
+ case "143": // PolicyRefresh
+ case "144": // InvalidPolicyKey
+ //enable provision
+ syncData.accountData.setAccountProperty("provision", true);
+ syncData.accountData.resetAccountProperty("policykey");
+ throw eas.sync.finish("resyncAccount", statusType);
+
+ default:
+ if (allowSoftFail) return statusType;
+ throw eas.sync.finish("error", statusType, "Request:\n" + syncData.request + "\n\nResponse:\n" + syncData.response);
+
+ }
+ },
+
+
+
+
+
+
+
+
+
+
+ // WBXML COMM STUFF
+
+ setDeviceInformation: async function (syncData) {
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5" || !syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("Settings")) {
+ return;
+ }
+
+ syncData.setSyncState("prepare.request.setdeviceinfo");
+
+ let wbxml = wbxmltools.createWBXML();
+ wbxml.switchpage("Settings");
+ wbxml.otag("Settings");
+ wbxml.otag("DeviceInformation");
+ wbxml.otag("Set");
+ wbxml.atag("Model", "Computer");
+ wbxml.atag("FriendlyName", "TbSync on Device " + syncData.accountData.getAccountProperty("deviceId").substring(4));
+ wbxml.atag("OS", Services.appinfo.OS);
+ wbxml.atag("UserAgent", syncData.accountData.getAccountProperty("useragent"));
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ syncData.setSyncState("send.request.setdeviceinfo");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Settings", syncData);
+
+ syncData.setSyncState("eval.response.setdeviceinfo");
+ let wbxmlData = eas.network.getDataFromResponse(response);
+
+ eas.network.checkStatus(syncData, wbxmlData, "Settings.Status");
+ },
+
+ getPolicykey: async function (syncData) {
+ //build WBXML to request provision
+ syncData.setSyncState("prepare.request.provision");
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("Provision");
+ wbxml.otag("Provision");
+ wbxml.otag("Policies");
+ wbxml.otag("Policy");
+ wbxml.atag("PolicyType", (syncData.accountData.getAccountProperty("asversion") == "2.5") ? "MS-WAP-Provisioning-XML" : "MS-EAS-Provisioning-WBXML");
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ for (let loop = 0; loop < 2; loop++) {
+ syncData.setSyncState("send.request.provision");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Provision", syncData);
+
+ syncData.setSyncState("eval.response.provision");
+ let wbxmlData = eas.network.getDataFromResponse(response);
+ let policyStatus = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Policies.Policy.Status");
+ let provisionStatus = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Status");
+ if (provisionStatus === false) {
+ throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Status");
+ } else if (provisionStatus != "1") {
+ //dump policy status as well
+ if (policyStatus) TbSync.dump("PolicyKey", "Received policy status: " + policyStatus);
+ throw eas.sync.finish("error", "provision::" + provisionStatus);
+ }
+
+ //reaching this point: provision status was ok
+ let policykey = eas.xmltools.getWbxmlDataField(wbxmlData, "Provision.Policies.Policy.PolicyKey");
+ switch (policyStatus) {
+ case false:
+ throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Policies.Policy.Status");
+
+ case "2":
+ //server does not have a policy for this device: disable provisioning
+ syncData.accountData.setAccountProperty("provision", false)
+ syncData.accountData.resetAccountProperty("policykey");
+ throw eas.sync.finish("resyncAccount", "NoPolicyForThisDevice");
+
+ case "1":
+ if (policykey === false) {
+ throw eas.sync.finish("error", "wbxmlmissingfield::Provision.Policies.Policy.PolicyKey");
+ }
+ TbSync.dump("PolicyKey", "Received policykey (" + loop + "): " + policykey);
+ syncData.accountData.setAccountProperty("policykey", policykey);
+ break;
+
+ default:
+ throw eas.sync.finish("error", "policy." + policyStatus);
+ }
+
+ //build WBXML to acknowledge provision
+ syncData.setSyncState("prepare.request.provision");
+ wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("Provision");
+ wbxml.otag("Provision");
+ wbxml.otag("Policies");
+ wbxml.otag("Policy");
+ wbxml.atag("PolicyType", (syncData.accountData.getAccountProperty("asversion") == "2.5") ? "MS-WAP-Provisioning-XML" : "MS-EAS-Provisioning-WBXML");
+ wbxml.atag("PolicyKey", policykey);
+ wbxml.atag("Status", "1");
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ //this wbxml will be used by Send at the top of this loop
+ }
+ },
+
+ getSynckey: async function (syncData) {
+ syncData.setSyncState("prepare.request.synckey");
+ //build WBXML to request a new syncKey
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.otag("Sync");
+ wbxml.otag("Collections");
+ wbxml.otag("Collection");
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
+ wbxml.atag("SyncKey", "0");
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ syncData.setSyncState("send.request.synckey");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
+
+ syncData.setSyncState("eval.response.synckey");
+ // get data from wbxml response
+ let wbxmlData = eas.network.getDataFromResponse(response);
+ //check status
+ eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
+ //update synckey
+ eas.network.updateSynckey(syncData, wbxmlData);
+ },
+
+ getItemEstimate: async function (syncData) {
+ syncData.progressData.reset();
+
+ if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("GetItemEstimate")) {
+ return; //do not throw, this is optional
+ }
+
+ syncData.setSyncState("prepare.request.estimate");
+
+ // BUILD WBXML
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("GetItemEstimate");
+ wbxml.otag("GetItemEstimate");
+ wbxml.otag("Collections");
+ wbxml.otag("Collection");
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") { //got this order for 2.5 directly from Microsoft support
+ wbxml.atag("Class", syncData.type); //only 2.5
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.switchpage("AirSync");
+ // required !
+ // https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-ascmd/ffbefa62-e315-40b9-9cc6-f8d74b5f65d4
+ if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
+ else wbxml.atag("FilterType", "0"); // we may filter incomplete tasks
+
+ wbxml.atag("SyncKey", syncData.synckey);
+ wbxml.switchpage("GetItemEstimate");
+ } else { //14.0
+ wbxml.switchpage("AirSync");
+ wbxml.atag("SyncKey", syncData.synckey);
+ wbxml.switchpage("GetItemEstimate");
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.switchpage("AirSync");
+ wbxml.otag("Options");
+ // optional
+ if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
+ wbxml.atag("Class", syncData.type);
+ wbxml.ctag();
+ wbxml.switchpage("GetItemEstimate");
+ }
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ //SEND REQUEST
+ syncData.setSyncState("send.request.estimate");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "GetItemEstimate", syncData, /* allowSoftFail */ true);
+
+ //VALIDATE RESPONSE
+ syncData.setSyncState("eval.response.estimate");
+
+ // get data from wbxml response, some servers send empty response if there are no changes, which is not an error
+ let wbxmlData = eas.network.getDataFromResponse(response, eas.flags.allowEmptyResponse);
+ if (wbxmlData === null) return;
+
+ let status = eas.xmltools.getWbxmlDataField(wbxmlData, "GetItemEstimate.Response.Status");
+ let estimate = eas.xmltools.getWbxmlDataField(wbxmlData, "GetItemEstimate.Response.Collection.Estimate");
+
+ if (status && status == "1") { //do not throw on error, with EAS v2.5 I get error 2 for tasks and calendars ???
+ syncData.progressData.reset(0, estimate);
+ }
+ },
+
+ getUserInfo: async function (syncData) {
+ if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("Settings")) {
+ return;
+ }
+
+ syncData.setSyncState("prepare.request.getuserinfo");
+
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("Settings");
+ wbxml.otag("Settings");
+ wbxml.otag("UserInformation");
+ wbxml.atag("Get");
+ wbxml.ctag();
+ wbxml.ctag();
+
+ syncData.setSyncState("send.request.getuserinfo");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Settings", syncData);
+
+
+ syncData.setSyncState("eval.response.getuserinfo");
+ let wbxmlData = eas.network.getDataFromResponse(response);
+
+ eas.network.checkStatus(syncData, wbxmlData, "Settings.Status");
+ },
+
+
+
+
+
+
+
+
+
+
+ // SEARCH
+
+ getSearchResults: async function (accountData, currentQuery) {
+
+ let _wbxml = eas.wbxmltools.createWBXML();
+ _wbxml.switchpage("Search");
+ _wbxml.otag("Search");
+ _wbxml.otag("Store");
+ _wbxml.atag("Name", "GAL");
+ _wbxml.atag("Query", currentQuery);
+ _wbxml.otag("Options");
+ _wbxml.atag("Range", "0-99"); //Z-Push needs a Range
+ //Not valid for GAL: https://msdn.microsoft.com/en-us/library/gg675461(v=exchg.80).aspx
+ //_wbxml.atag("DeepTraversal");
+ //_wbxml.atag("RebuildResults");
+ _wbxml.ctag();
+ _wbxml.ctag();
+ _wbxml.ctag();
+
+ let wbxml = _wbxml.getBytes();
+
+ eas.network.logXML(wbxml, "Send (GAL Search)");
+ let command = "Search";
+
+ let authData = eas.network.getAuthData(accountData);
+ let oauthData = eas.network.getOAuthObj({ accountData });
+ let userAgent = accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
+ let deviceType = accountData.getAccountProperty("devicetype");
+ let deviceId = accountData.getAccountProperty("deviceId");
+
+ TbSync.dump("Sending (EAS v" + accountData.getAccountProperty("asversion") + ")", "POST " + eas.network.getEasURL(accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(authData.user) + '&DeviceType=' + deviceType + '&DeviceId=' + deviceId, true);
+
+ for (let i = 0; i < 2; i++) {
+ // check OAuth situation before connecting
+ if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
+ let _rv = {}
+ if (!(await oauthData.asyncConnect(_rv))) {
+ throw eas.sync.finish("error", _rv.error);
+ }
+ }
+
+ try {
+ let contextData = eas.network.getContextData({ accountData });
+ let uri = Services.io.newURI(eas.network.getEasURL(accountData) + '?Cmd=' + command + '&User=' + encodeURIComponent(authData.user) + '&DeviceType=' + encodeURIComponent(deviceType) + '&DeviceId=' + deviceId);
+ let response = await new Promise(function (resolve, reject) {
+ let req = getSandBoxedXHR(contextData, uri);
+ req.mozBackgroundRequest = true;
+ req.open("POST", uri.spec, true);
+ req.overrideMimeType("text/plain");
+ req.setRequestHeader("User-Agent", userAgent);
+ req.setRequestHeader("Content-Type", "application/vnd.ms-sync.wbxml");
+
+ if (authData.password) {
+ if (eas.network.getOAuthObj({ accountData })) {
+ req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(authData.password, "access"));
+ } else {
+ req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(authData.user + ':' + authData.password));
+ }
+ }
+
+ if (accountData.getAccountProperty("asversion") == "2.5") {
+ req.setRequestHeader("MS-ASProtocolVersion", "2.5");
+ } else {
+ req.setRequestHeader("MS-ASProtocolVersion", "14.0");
+ }
+ req.setRequestHeader("Content-Length", wbxml.length);
+ if (accountData.getAccountProperty("provision")) {
+ req.setRequestHeader("X-MS-PolicyKey", accountData.getAccountProperty("policykey"));
+ TbSync.dump("PolicyKey used", accountData.getAccountProperty("policykey"));
+ }
+
+ req.timeout = eas.Base.getConnectionTimeout();
+
+ req.ontimeout = function () {
+ reject("GAL Search timeout");
+ };
+
+ req.onerror = function () {
+ reject("GAL Search Error");
+ };
+
+ req.onload = function () {
+ let response = req.responseText;
+
+ // Debug: Log received cookies.
+ const channel = req.channel.QueryInterface(Ci.nsIHttpChannel);
+ const SET_COOKIE_REGEXP = /set-cookie/i;
+ channel.visitOriginalResponseHeaders({
+ visitHeader(name, value) {
+ if (SET_COOKIE_REGEXP.test(name)) {
+ console.log("Received cookie", value);
+ }
+ },
+ });
+
+ switch (req.status) {
+
+ case 200: //OK
+ eas.network.logXML(response, "Received (GAL Search");
+
+ //What to do on error? IS this an error? Yes!
+ if (response.length !== 0 && response.substr(0, 4) !== String.fromCharCode(0x03, 0x01, 0x6A, 0x00)) {
+ TbSync.dump("Recieved Data", "Expecting WBXML but got junk (request status = " + req.status + ", ready state = " + req.readyState + "\n>>>>>>>>>>\n" + response + "\n<<<<<<<<<<\n");
+ reject("GAL Search Response Invalid");
+ } else {
+ resolve(response);
+ }
+ break;
+
+ case 401: // bad auth
+ resolve("401");
+ break;
+
+ default:
+ reject("GAL Search Failed: " + req.status);
+ }
+ };
+
+ req.send(wbxml);
+
+ });
+
+ if (response === "401") {
+ // try to recover from bad auth via token refresh
+ if (oauthData) {
+ await oauthData.setToken("accessToken", "");
+ continue;
+ }
+ }
+
+ return response;
+ } catch (e) {
+ Components.utils.reportError(e);
+ return;
+ }
+ }
+ },
+
+
+
+
+
+
+
+
+
+
+ // OPTIONS
+
+ getServerOptions: async function (syncData) {
+ syncData.setSyncState("prepare.request.options");
+ let authData = eas.network.getAuthData(syncData.accountData);
+
+ let userAgent = syncData.accountData.getAccountProperty("useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
+ TbSync.dump("Sending", "OPTIONS " + eas.network.getEasURL(syncData.accountData));
+
+ let allowedRetries = 5;
+ let retry;
+ let oauthData = eas.network.getOAuthObj({ accountData: syncData.accountData });
+
+ do {
+ retry = false;
+
+ // Check OAuth situation before connecting
+ if (oauthData && (!oauthData.getToken("accessToken") || oauthData.isExpired())) {
+ let _rv = {};
+ syncData.setSyncState("oauthprompt");
+ if (!(await oauthData.asyncConnect(_rv))) {
+ throw eas.sync.finish("error", _rv.error);
+ }
+ }
+
+ let contextData = eas.network.getContextData({ accountData: syncData.accountData });
+ let uri = Services.io.newURI(eas.network.getEasURL(syncData.accountData));
+ let result = await new Promise(function (resolve, reject) {
+ syncData.req = getSandBoxedXHR(contextData, uri);
+ syncData.req.mozBackgroundRequest = true;
+ syncData.req.open("OPTIONS", uri.spec, true);
+ syncData.req.overrideMimeType("text/plain");
+ syncData.req.setRequestHeader("User-Agent", userAgent);
+ if (authData.password) {
+ if (eas.network.getOAuthObj({ accountData: syncData.accountData })) {
+ syncData.req.setRequestHeader("Authorization", 'Bearer ' + eas.network.getOAuthValue(authData.password, "access"));
+ } else {
+ syncData.req.setRequestHeader("Authorization", 'Basic ' + TbSync.tools.b64encode(authData.user + ':' + authData.password));
+ }
+ }
+ syncData.req.timeout = eas.Base.getConnectionTimeout();
+
+ syncData.req.ontimeout = function () {
+ resolve();
+ };
+
+ syncData.req.onerror = function () {
+ let responseData = {};
+ responseData["MS-ASProtocolVersions"] = syncData.req.getResponseHeader("MS-ASProtocolVersions");
+ responseData["MS-ASProtocolCommands"] = syncData.req.getResponseHeader("MS-ASProtocolCommands");
+
+ TbSync.dump("EAS OPTIONS with response (status: " + syncData.req.status + ")", "\n" +
+ "responseText: " + syncData.req.responseText + "\n" +
+ "responseHeader(MS-ASProtocolVersions): " + responseData["MS-ASProtocolVersions"] + "\n" +
+ "responseHeader(MS-ASProtocolCommands): " + responseData["MS-ASProtocolCommands"]);
+ resolve();
+ };
+
+ syncData.req.onload = function () {
+ syncData.setSyncState("eval.request.options");
+ let responseData = {};
+
+ // Debug: Log received cookies.
+ const channel = syncData.req.channel.QueryInterface(Ci.nsIHttpChannel);
+ const SET_COOKIE_REGEXP = /set-cookie/i;
+ channel.visitOriginalResponseHeaders({
+ visitHeader(name, value) {
+ if (SET_COOKIE_REGEXP.test(name)) {
+ console.log("Received cookie", value);
+ }
+ },
+ });
+
+ switch (syncData.req.status) {
+ case 401: // AuthError
+ let rv = {};
+ rv.errorObj = eas.sync.finish("error", "401");
+ rv.errorType = "PasswordPrompt";
+ resolve(rv);
+ break;
+
+ case 200:
+ responseData["MS-ASProtocolVersions"] = syncData.req.getResponseHeader("MS-ASProtocolVersions");
+ responseData["MS-ASProtocolCommands"] = syncData.req.getResponseHeader("MS-ASProtocolCommands");
+
+ TbSync.dump("EAS OPTIONS with response (status: 200)", "\n" +
+ "responseText: " + syncData.req.responseText + "\n" +
+ "responseHeader(MS-ASProtocolVersions): " + responseData["MS-ASProtocolVersions"] + "\n" +
+ "responseHeader(MS-ASProtocolCommands): " + responseData["MS-ASProtocolCommands"]);
+
+ if (responseData && responseData["MS-ASProtocolCommands"] && responseData["MS-ASProtocolVersions"]) {
+ syncData.accountData.setAccountProperty("allowedEasCommands", responseData["MS-ASProtocolCommands"]);
+ syncData.accountData.setAccountProperty("allowedEasVersions", responseData["MS-ASProtocolVersions"]);
+ syncData.accountData.setAccountProperty("lastEasOptionsUpdate", Date.now());
+ }
+ resolve();
+ break;
+
+ default:
+ resolve();
+ break;
+
+ }
+ };
+
+ syncData.setSyncState("send.request.options");
+ syncData.req.send();
+
+ });
+
+ if (result && result.hasOwnProperty("errorType") && result.errorType == "PasswordPrompt") {
+ if (allowedRetries > 0) {
+ if (oauthData) {
+ await oauthData.setToken("accessToken", "");
+ retry = true;
+ } else {
+ syncData.setSyncState("passwordprompt");
+ let authData = eas.network.getAuthData(syncData.accountData);
+ let promptData = {
+ windowID: "auth:" + syncData.accountData.accountID,
+ accountname: syncData.accountData.getAccountProperty("accountname"),
+ usernameLocked: syncData.accountData.isConnected(),
+ username: authData.user
+ }
+ let credentials = await TbSync.passwordManager.asyncPasswordPrompt(promptData, eas.openWindows);
+ if (credentials) {
+ await authData.updateLoginData(credentials.username, credentials.password);
+ retry = true;
+ }
+ }
+ }
+
+ if (!retry) {
+ throw result.errorObj;
+ }
+ }
+
+ allowedRetries--;
+ } while (retry);
+ },
+
+
+
+
+
+
+
+
+
+
+ // AUTODISCOVER
+
+ updateServerConnectionViaAutodiscover: async function (syncData) {
+ syncData.setSyncState("prepare.request.autodiscover");
+ let authData = eas.network.getAuthData(syncData.accountData);
+
+ syncData.setSyncState("send.request.autodiscover");
+ let result = await eas.network.getServerConnectionViaAutodiscover(authData.accountname, authData.user, authData.password, 30 * 1000);
+
+ syncData.setSyncState("eval.response.autodiscover");
+ if (result.errorcode == 200) {
+ //update account
+ syncData.accountData.setAccountProperty("host", eas.network.stripAutodiscoverUrl(result.server));
+ syncData.accountData.setAccountProperty("user", result.user);
+ syncData.accountData.setAccountProperty("https", (result.server.substring(0, 5) == "https"));
+ }
+
+ return result.errorcode;
+ },
+
+ stripAutodiscoverUrl: function (url) {
+ let u = url;
+ while (u.endsWith("/")) { u = u.slice(0, -1); }
+ if (u.endsWith("/Microsoft-Server-ActiveSync")) u = u.slice(0, -28);
+ else TbSync.dump("Received non-standard EAS url via autodiscover:", url);
+
+ return u.split("//")[1]; //cut off protocol
+ },
+
+ getServerConnectionViaAutodiscover: async function (accountname, user, password, maxtimeout) {
+ let urls = [];
+ let parts = user.split("@");
+
+ urls.push({ "url": "https://autodiscover." + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
+ urls.push({ "url": "https://" + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
+ urls.push({ "url": "https://autodiscover." + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
+ urls.push({ "url": "https://" + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
+
+ urls.push({ "url": "http://autodiscover." + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
+ urls.push({ "url": "http://" + parts[1] + "/autodiscover/autodiscover.xml", "user": user });
+ urls.push({ "url": "http://autodiscover." + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
+ urls.push({ "url": "http://" + parts[1] + "/Autodiscover/Autodiscover.xml", "user": user });
+
+ let requests = [];
+ let responses = []; //array of objects {url, error, server}
+
+ for (let i = 0; i < urls.length; i++) {
+ await TbSync.tools.sleep(200);
+ requests.push(eas.network.getServerConnectionViaAutodiscoverRedirectWrapper(
+ accountname,
+ urls[i].url,
+ urls[i].user,
+ password,
+ maxtimeout
+ ));
+ }
+
+ try {
+ responses = await Promise.all(requests);
+ } catch (e) {
+ responses.push(e.result); //this is actually a success, see return value of getServerConnectionViaAutodiscoverRedirectWrapper()
+ }
+
+ let result;
+ let log = [];
+ for (let r = 0; r < responses.length; r++) {
+ log.push("* " + responses[r].url + " @ " + responses[r].user + " : " + (responses[r].server ? responses[r].server : responses[r].error));
+
+ if (responses[r].server) {
+ result = { "server": responses[r].server, "user": responses[r].user, "error": "", "errorcode": 200 };
+ break;
+ }
+
+ if (responses[r].error == 403 || responses[r].error == 401) {
+ //we could still find a valid server, so just store this state
+ result = { "server": "", "user": responses[r].user, "errorcode": responses[r].error, "error": TbSync.getString("status." + responses[r].error, "eas") };
+ }
+ }
+
+ //this is only reached on fail, if no result defined yet, use general error
+ if (!result) {
+ result = { "server": "", "user": user, "error": TbSync.getString("autodiscover.Failed", "eas").replace("##user##", user), "errorcode": 503 };
+ }
+
+ TbSync.eventlog.add("error", new TbSync.EventLogInfo("eas"), result.error, log.join("\n"));
+ return result;
+ },
+
+ getServerConnectionViaAutodiscoverRedirectWrapper: async function (accountname, url, user, password, maxtimeout) {
+ let result = {};
+ let method = "POST";
+ let connection = { accountname, url, user };
+
+ do {
+ await TbSync.tools.sleep(200);
+ result = await eas.network.getServerConnectionViaAutodiscoverRequest(method, connection, password, maxtimeout);
+ method = "";
+
+ if (result.error == "redirect found") {
+ TbSync.dump("EAS autodiscover URL redirect", "\n" + connection.url + " @ " + connection.user + " => \n" + result.url + " @ " + result.user);
+ connection.url = result.url;
+ connection.user = result.user;
+ method = "POST";
+ }
+
+ } while (method);
+
+ //invert reject and resolve, so we exit the promise group on success right away
+ if (result.server) {
+ let e = new Error("Not an error (early exit from promise group)");
+ e.result = result;
+ throw e;
+ } else {
+ return result;
+ }
+ },
+
+ getServerConnectionViaAutodiscoverRequest: function (method, connection, password, maxtimeout) {
+ TbSync.dump("Querry EAS autodiscover URL", connection.url + " @ " + connection.user);
+
+ return new Promise(function (resolve, reject) {
+
+ let xml = '\r\n';
+ xml += '\r\n';
+ xml += '\r\n';
+ xml += '' + connection.user + '\r\n';
+ xml += 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006\r\n';
+ xml += '\r\n';
+ xml += '\r\n';
+
+ let userAgent = eas.prefs.getCharPref("clientID.useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
+ let uri = Services.io.newURI(connection.url);
+ let req = getSandBoxedXHR(connection, uri);
+ req.mozBackgroundRequest = true;
+ req.open(method, uri.spec, true);
+ req.timeout = maxtimeout;
+ req.setRequestHeader("User-Agent", userAgent);
+
+ let secure = (connection.url.substring(0, 8).toLowerCase() == "https://");
+
+ if (method == "POST") {
+ req.setRequestHeader("Content-Length", xml.length);
+ req.setRequestHeader("Content-Type", "text/xml");
+ if (secure && password) {
+ // OAUTH accounts cannot authenticate against the standard discovery services
+ // updateServerConnectionViaAutodiscover() is not passing them on
+ req.setRequestHeader("Authorization", "Basic " + TbSync.tools.b64encode(connection.user + ":" + password));
+ }
+ }
+
+ req.ontimeout = function () {
+ TbSync.dump("EAS autodiscover with timeout", "\n" + connection.url + " => \n" + req.responseURL);
+ resolve({ "url": req.responseURL, "error": "timeout", "server": "", "user": connection.user });
+ };
+
+ req.onerror = function () {
+ let error = TbSync.network.createTCPErrorFromFailedXHR(req);
+ if (!error) error = req.responseText;
+
+ // CORS violations can happen on redirects. They come back as NS_ERROR_DOM_BAD_URI.
+ if (error == "network::NS_ERROR_DOM_BAD_URI" && req.channel.URI.spec != uri.spec) {
+ resolve({ "url": req.channel.URI.spec, "error": "redirect found", "server": "", "user": connection.user });
+ return;
+ }
+
+ TbSync.dump("EAS autodiscover with error (" + error + ")", "\n" + connection.url + " => \n" + req.responseURL);
+ resolve({ "url": req.responseURL, "error": error, "server": "", "user": connection.user });
+ };
+
+ req.onload = function () {
+ //initiate rerun on redirects
+ if (req.responseURL != connection.url) {
+ resolve({ "url": req.responseURL, "error": "redirect found", "server": "", "user": connection.user });
+ return;
+ }
+
+ //ignore POST without autherization (we just do them to get redirect information)
+ if (!secure) {
+ resolve({ "url": req.responseURL, "error": "unsecure POST", "server": "", "user": connection.user });
+ return;
+ }
+
+ //evaluate secure POST requests which have not been redirected
+ TbSync.dump("EAS autodiscover POST with status (" + req.status + ")", "\n" + connection.url + " => \n" + req.responseURL + "\n[" + req.responseText + "]");
+
+ if (req.status === 200) {
+ let data = null;
+ // getDataFromXMLString may throw an error which cannot be catched outside onload,
+ // because we are in an async callback of the surrounding Promise
+ // Alternatively we could just return the responseText and do any data analysis outside of the Promise
+ try {
+ data = eas.xmltools.getDataFromXMLString(req.responseText);
+ } catch (e) {
+ resolve({ "url": req.responseURL, "error": "bad response", "server": "", "user": connection.user });
+ return;
+ }
+
+ if (!(data === null) && data.Autodiscover && data.Autodiscover.Response && data.Autodiscover.Response.Action) {
+ // "Redirect" or "Settings" are possible
+ if (data.Autodiscover.Response.Action.Redirect) {
+ // redirect, start again with new user
+ let newuser = action.Redirect;
+ resolve({ "url": req.responseURL, "error": "redirect found", "server": "", "user": newuser });
+
+ } else if (data.Autodiscover.Response.Action.Settings) {
+ // get server settings
+ let server = eas.xmltools.nodeAsArray(data.Autodiscover.Response.Action.Settings.Server);
+
+ for (let count = 0; count < server.length; count++) {
+ if (server[count].Type == "MobileSync" && server[count].Url) {
+ resolve({ "url": req.responseURL, "error": "", "server": server[count].Url, "user": connection.user });
+ return;
+ }
+ }
+ }
+ } else {
+ resolve({ "url": req.responseURL, "error": "invalid", "server": "", "user": connection.user });
+ }
+ } else {
+ resolve({ "url": req.responseURL, "error": req.status, "server": "", "user": connection.user });
+ }
+ };
+
+ req.send(xml);
+ });
+ },
+
+ getServerConnectionViaAutodiscoverV2JsonRequest: function (accountname, user, url, maxtimeout) {
+ TbSync.dump("Querry EAS autodiscover V2 URL", url);
+
+ return new Promise(function (resolve, reject) {
+
+ let userAgent = eas.prefs.getCharPref("clientID.useragent"); //plus calendar.useragent.extra = Lightning/5.4.5.2
+ let uri = Services.io.newURI(url);
+ let req = getSandBoxedXHR({ accountname, user }, uri);
+ req.mozBackgroundRequest = true;
+ req.open("GET", uri.spec, true);
+ req.timeout = maxtimeout;
+ req.setRequestHeader("User-Agent", userAgent);
+
+ req.ontimeout = function () {
+ TbSync.dump("EAS autodiscover V2 with timeout", "\n" + url + " => \n" + req.responseURL);
+ resolve({ "url": req.responseURL, "error": "timeout", "server": "" });
+ };
+
+ req.onerror = function () {
+ let error = TbSync.network.createTCPErrorFromFailedXHR(req);
+ if (!error) error = req.responseText;
+ TbSync.dump("EAS autodiscover V2 with error (" + error + ")", "\n" + url + " => \n" + req.responseURL);
+ resolve({ "url": req.responseURL, "error": error, "server": "" });
+ };
+
+ req.onload = function () {
+ if (req.status === 200) {
+ let data = JSON.parse(req.responseText);
+
+ if (data && data.Url) {
+ resolve({ "url": req.responseURL, "error": "", "server": eas.network.stripAutodiscoverUrl(data.Url) });
+ } else {
+ resolve({ "url": req.responseURL, "error": "invalid", "server": "" });
+ }
+ return;
+ }
+
+ resolve({ "url": req.responseURL, "error": req.status, "server": "" });
+ };
+
+ req.send();
+ });
+ }
+}
diff -Nru eas4tbsync-4.11/content/includes/sync.js eas4tbsync-4.17/content/includes/sync.js
--- eas4tbsync-4.11/content/includes/sync.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/sync.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,1505 +1,1510 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-
-XPCOMUtils.defineLazyModuleGetters(this, {
- CalRecurrenceInfo: "resource:///modules/CalRecurrenceInfo.jsm",
-});
-
-// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIEvent.idl
-// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIItemBase.idl
-// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calICalendar.idl
-// - https://dxr.mozilla.org/comm-central/source/calendar/base/modules/calAsyncUtils.jsm
-
-// https://msdn.microsoft.com/en-us/library/dd299454(v=exchg.80).aspx
-
-var sync = {
-
-
-
- finish: function (aStatus = "", msg = "", details = "") {
- let status = TbSync.StatusData.SUCCESS
- switch (aStatus) {
-
- case "":
- case "ok":
- status = TbSync.StatusData.SUCCESS;
- break;
-
- case "info":
- status = TbSync.StatusData.INFO;
- break;
-
- case "resyncAccount":
- status = TbSync.StatusData.ACCOUNT_RERUN;
- break;
-
- case "resyncFolder":
- status = TbSync.StatusData.FOLDER_RERUN;
- break;
-
- case "warning":
- status = TbSync.StatusData.WARNING;
- break;
-
- case "error":
- status = TbSync.StatusData.ERROR;
- break;
-
- default:
- console.log("TbSync/EAS: Unknown status <"+aStatus+">");
- status = TbSync.StatusData.ERROR;
- break;
- }
-
- let e = new Error();
- e.name = "eas4tbsync";
- e.message = status.toUpperCase() + ": " + msg.toString() + " (" + details.toString() + ")";
- e.statusData = new TbSync.StatusData(status, msg.toString(), details.toString());
- return e;
- },
-
-
- resetFolderSyncInfo: function (folderData) {
- folderData.resetFolderProperty("synckey");
- folderData.resetFolderProperty("lastsynctime");
- },
-
-
- // update folders avail on server and handle added, removed and renamed
- // folders
- folderList: async function(syncData) {
- //should we recheck options/commands? Always check, if we have no info about asversion!
- if (syncData.accountData.getAccountProperty("asversion", "") == "" || (Date.now() - syncData.accountData.getAccountProperty("lastEasOptionsUpdate")) > 86400000 ) {
- await eas.network.getServerOptions(syncData);
- }
-
- //only update the actual used asversion, if we are currently not connected or it has not yet been set
- if (syncData.accountData.getAccountProperty("asversion", "") == "" || !syncData.accountData.isConnected()) {
- //eval the currently in the UI selected EAS version
- let asversionselected = syncData.accountData.getAccountProperty("asversionselected");
- let allowedVersionsString = syncData.accountData.getAccountProperty("allowedEasVersions").trim();
- let allowedVersionsArray = allowedVersionsString.split(",");
-
- if (asversionselected == "auto") {
- if (allowedVersionsArray.includes("14.0")) syncData.accountData.setAccountProperty("asversion", "14.0");
- else if (allowedVersionsArray.includes("2.5")) syncData.accountData.setAccountProperty("asversion", "2.5");
- else if (allowedVersionsString == "") {
- throw eas.sync.finish("error", "InvalidServerOptions");
- } else {
- throw eas.sync.finish("error", "nosupportedeasversion::"+allowedVersionsArray.join(", "));
- }
- } else if (allowedVersionsString != "" && !allowedVersionsArray.includes(asversionselected)) {
- throw eas.sync.finish("error", "notsupportedeasversion::"+asversionselected+"::"+allowedVersionsArray.join(", "));
- } else {
- //just use the value set by the user
- syncData.accountData.setAccountProperty("asversion", asversionselected);
- }
- }
-
- //do we need to get a new policy key?
- if (syncData.accountData.getAccountProperty("provision") && syncData.accountData.getAccountProperty("policykey") == "0") {
- await eas.network.getPolicykey(syncData);
- }
-
- //set device info
- await eas.network.setDeviceInformation(syncData);
-
- syncData.setSyncState("prepare.request.folders");
- let foldersynckey = syncData.accountData.getAccountProperty("foldersynckey");
-
- //build WBXML to request foldersync
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("FolderHierarchy");
- wbxml.otag("FolderSync");
- wbxml.atag("SyncKey", foldersynckey);
- wbxml.ctag();
-
- syncData.setSyncState("send.request.folders");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "FolderSync", syncData);
-
- syncData.setSyncState("eval.response.folders");
- let wbxmlData = eas.network.getDataFromResponse(response);
- eas.network.checkStatus(syncData, wbxmlData,"FolderSync.Status");
-
- let synckey = eas.xmltools.getWbxmlDataField(wbxmlData,"FolderSync.SyncKey");
- if (synckey) {
- syncData.accountData.setAccountProperty("foldersynckey", synckey);
- } else {
- throw eas.sync.finish("error", "wbxmlmissingfield::FolderSync.SyncKey");
- }
-
- // If we reach this point, wbxmlData contains FolderSync node,
- // so the next "if" will not fail with an javascript error, no need
- // to use save getWbxmlDataField function.
-
- // Are there any changes in folder hierarchy?
- if (wbxmlData.FolderSync.Changes) {
- // Looking for additions.
- let add = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Add);
- for (let count = 0; count < add.length; count++) {
- // Only add allowed folder types to DB (include trash(4), so we can find trashed folders.
- if (!["9","14","8","13","7","15", "4"].includes(add[count].Type))
- continue;
-
- let existingFolder = syncData.accountData.getFolder("serverID", add[count].ServerId);
- if (existingFolder) {
- // Server has send us an ADD for a folder we alreay have, treat as update.
- existingFolder.setFolderProperty("foldername", add[count].DisplayName);
- existingFolder.setFolderProperty("type", add[count].Type);
- existingFolder.setFolderProperty("parentID", add[count].ParentId);
- } else {
- // Create folder obj for new folder settings.
- let newFolder = syncData.accountData.createNewFolder();
- switch (add[count].Type) {
- case "9": // contact
- case "14":
- newFolder.setFolderProperty("targetType", "addressbook");
- break;
- case "8": // event
- case "13":
- newFolder.setFolderProperty("targetType", "calendar");
- break;
- case "7": // todo
- case "15":
- newFolder.setFolderProperty("targetType", "calendar");
- break;
- default:
- newFolder.setFolderProperty("targetType", "unknown type ("+add[count].Type+")");
- break;
-
- }
-
- newFolder.setFolderProperty("serverID", add[count].ServerId);
- newFolder.setFolderProperty("foldername", add[count].DisplayName);
- newFolder.setFolderProperty("type", add[count].Type);
- newFolder.setFolderProperty("parentID", add[count].ParentId);
-
- // Do we have a cached folder?
- let cachedFolderData = syncData.accountData.getFolderFromCache("serverID", add[count].ServerId);
- if (cachedFolderData) {
- // Copy fields from cache which we want to re-use.
- newFolder.setFolderProperty("targetColor", cachedFolderData.getFolderProperty("targetColor"));
- newFolder.setFolderProperty("targetName", cachedFolderData.getFolderProperty("targetName"));
- newFolder.setFolderProperty("downloadonly", cachedFolderData.getFolderProperty("downloadonly"));
- }
- }
- }
-
- // Looking for updates.
- let update = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Update);
- for (let count = 0; count < update.length; count++) {
- let existingFolder = syncData.accountData.getFolder("serverID", update[count].ServerId);
- if (existingFolder) {
- // Update folder.
- existingFolder.setFolderProperty("foldername", update[count].DisplayName);
- existingFolder.setFolderProperty("type", update[count].Type);
- existingFolder.setFolderProperty("parentID", update[count].ParentId);
- }
- }
-
- // Looking for deletes. Do not delete the targets,
- // but keep them as stale/unconnected elements.
- let del = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Delete);
- for (let count = 0; count < del.length; count++) {
- let existingFolder = syncData.accountData.getFolder("serverID", del[count].ServerId);
- if (existingFolder) {
- existingFolder.remove("[deleted on server]");
- }
- }
- }
- },
-
-
-
-
-
- deleteFolder: async function (syncData) {
- if (!syncData.currentFolderData) {
- return;
- }
-
- if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("FolderDelete")) {
- throw eas.sync.finish("error", "notsupported::FolderDelete");
- }
-
- syncData.setSyncState("prepare.request.deletefolder");
- let foldersynckey = syncData.accountData.getAccountProperty("foldersynckey");
-
- //request foldersync
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.switchpage("FolderHierarchy");
- wbxml.otag("FolderDelete");
- wbxml.atag("SyncKey", foldersynckey);
- wbxml.atag("ServerId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.ctag();
-
- syncData.setSyncState("send.request.deletefolder");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "FolderDelete", syncData);
-
- syncData.setSyncState("eval.response.deletefolder");
- let wbxmlData = eas.network.getDataFromResponse(response);
-
- eas.network.checkStatus(syncData, wbxmlData,"FolderDelete.Status");
-
- let synckey = eas.xmltools.getWbxmlDataField(wbxmlData,"FolderDelete.SyncKey");
- if (synckey) {
- syncData.accountData.setAccountProperty("foldersynckey", synckey);
- syncData.currentFolderData.remove();
- } else {
- throw eas.sync.finish("error", "wbxmlmissingfield::FolderDelete.SyncKey");
- }
- },
-
-
-
-
-
- singleFolder: async function (syncData) {
- // add target to syncData
- try {
- // accessing the target for the first time will check if it is avail and if not will create it (if possible)
- syncData.target = await syncData.currentFolderData.targetData.getTarget();
- } catch (e) {
- Components.utils.reportError(e);
- throw eas.sync.finish("warning", e.message);
- }
-
- //get syncData type, which is also used in WBXML for the CLASS element
- syncData.type = null;
- switch (syncData.currentFolderData.getFolderProperty("type")) {
- case "9": //contact
- case "14":
- syncData.type = "Contacts";
- break;
- case "8": //event
- case "13":
- syncData.type = "Calendar";
- break;
- case "7": //todo
- case "15":
- syncData.type = "Tasks";
- break;
- default:
- throw eas.sync.finish("info", "skipped");
- break;
- }
-
- syncData.setSyncState("preparing");
-
- //get synckey if needed
- syncData.synckey = syncData.currentFolderData.getFolderProperty("synckey");
- if (syncData.synckey == "") {
- await eas.network.getSynckey(syncData);
- }
-
- //sync folder
- syncData.timeOfLastSync = syncData.currentFolderData.getFolderProperty( "lastsynctime") / 1000;
- syncData.timeOfThisSync = (Date.now() / 1000) - 1;
-
- let lightningBatch = false;
- let lightningReadOnly = "";
- let error = null;
-
- // We ned to intercept any throw error, because lightning needs a few operations after sync finished
- try {
- switch (syncData.type) {
- case "Contacts":
- await eas.sync.easFolder(syncData);
- break;
-
- case "Calendar":
- case "Tasks":
- //save current value of readOnly (or take it from the setting)
- lightningReadOnly = syncData.target.calendar.getProperty("readOnly") || syncData.currentFolderData.getFolderProperty( "downloadonly");
- syncData.target.calendar.setProperty("readOnly", false);
-
- lightningBatch = true;
- syncData.target.calendar.startBatch();
-
- await eas.sync.easFolder(syncData);
- break;
- }
- } catch (report) {
- error = report;
- }
-
- if (lightningBatch) {
- syncData.target.calendar.endBatch();
- syncData.target.calendar.setProperty("readOnly", lightningReadOnly);
- }
-
- if (error) throw error;
- },
-
-
-
-
-
-
-
-
-
-
- // ---------------------------------------------------------------------------
- // MAIN FUNCTIONS TO SYNC AN EAS FOLDER
- // ---------------------------------------------------------------------------
-
- easFolder: async function (syncData) {
- syncData.progressData.reset();
-
- if (syncData.currentFolderData.getFolderProperty("downloadonly")) {
- await eas.sync.revertLocalChanges(syncData);
- }
-
- await eas.network.getItemEstimate(syncData);
- await eas.sync.requestRemoteChanges(syncData);
-
- if (!syncData.currentFolderData.getFolderProperty("downloadonly")) {
- let sendChanges = await eas.sync.sendLocalChanges(syncData);
- if (sendChanges) {
- // This is ugly as hell, but Microsoft sometimes sets the state of the
- // remote account to "changed" after we have send a local change (even
- // though it has acked the change) and this will cause the server to
- // send a change request with our next sync. Because we follow the
- // "server wins" policy, this will overwrite any additional local change
- // we have done in the meantime. This is stupid, but we wait 2s and
- // hope it is enough to catch this second ack of the local change.
- let timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
- await new Promise(function(resolve, reject) {
- let event = {
- notify: function(timer) {
- resolve();
- }
- }
- timer.initWithCallback(event, 2000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- });
- await eas.sync.requestRemoteChanges(syncData);
- }
- }
- },
-
-
- requestRemoteChanges: async function (syncData) {
- do {
- syncData.setSyncState("prepare.request.remotechanges");
- syncData.request = "";
- syncData.response = "";
-
- // BUILD WBXML
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.otag("Sync");
- wbxml.otag("Collections");
- wbxml.otag("Collection");
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
- wbxml.atag("SyncKey", syncData.synckey);
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.atag("DeletesAsMoves");
- wbxml.atag("GetChanges");
- wbxml.atag("WindowSize", eas.prefs.getIntPref("maxitems").toString());
-
- if (syncData.accountData.getAccountProperty("asversion") != "2.5") {
- wbxml.otag("Options");
- if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
- wbxml.atag("Class", syncData.type);
- wbxml.switchpage("AirSyncBase");
- wbxml.otag("BodyPreference");
- wbxml.atag("Type", "1");
- wbxml.ctag();
- wbxml.switchpage("AirSync");
- wbxml.ctag();
- } else if (syncData.type == "Calendar") { //in 2.5 we only send it to filter Calendar
- wbxml.otag("Options");
- wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
- wbxml.ctag();
- }
-
- wbxml.ctag();
- wbxml.ctag();
- wbxml.ctag();
-
- //SEND REQUEST
- syncData.setSyncState("send.request.remotechanges");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
-
- //VALIDATE RESPONSE
- // get data from wbxml response, some servers send empty response if there are no changes, which is not an error
- let wbxmlData = eas.network.getDataFromResponse(response, eas.flags.allowEmptyResponse);
- if (wbxmlData === null) return;
-
- //check status, throw on error
- eas.network.checkStatus(syncData, wbxmlData,"Sync.Collections.Collection.Status");
-
- //PROCESS COMMANDS
- await eas.sync.processCommands(wbxmlData, syncData);
-
- //Update count in UI
- syncData.setSyncState("eval.response.remotechanges");
-
- //update synckey
- eas.network.updateSynckey(syncData, wbxmlData);
-
- if (!eas.xmltools.hasWbxmlDataField(wbxmlData,"Sync.Collections.Collection.MoreAvailable")) {
- //Feedback from users: They want to see the final count
- await TbSync.tools.sleep(100);
- return;
- }
- } while (true);
-
- },
-
-
- sendLocalChanges: async function (syncData) {
- let maxnumbertosend = eas.prefs.getIntPref("maxitems");
- syncData.progressData.reset(0, syncData.target.getItemsFromChangeLog().length);
-
- //keep track of failed items
- syncData.failedItems = [];
-
- let done = false;
- let numberOfItemsToSend = maxnumbertosend;
- let sendChanges = false;
- do {
- syncData.setSyncState("prepare.request.localchanges");
- syncData.request = "";
- syncData.response = "";
-
- //get changed items from ChangeLog
- let changes = syncData.target.getItemsFromChangeLog(numberOfItemsToSend);
- //console.log("chnages", changes);
- let c=0;
- let e=0;
-
- //keep track of send items during this request
- let changedItems = [];
- let addedItems = {};
- let sendItems = [];
-
- // BUILD WBXML
- let wbxml = eas.wbxmltools.createWBXML();
- wbxml.otag("Sync");
- wbxml.otag("Collections");
- wbxml.otag("Collection");
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
- wbxml.atag("SyncKey", syncData.synckey);
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.otag("Commands");
-
- for (let i=0; i 0) { //if there was at least one actual local change, send request
- sendChanges = true;
- //SEND REQUEST & VALIDATE RESPONSE
- syncData.setSyncState("send.request.localchanges");
- let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
-
- syncData.setSyncState("eval.response.localchanges");
-
- //get data from wbxml response
- let wbxmlData = eas.network.getDataFromResponse(response);
-
- //check status and manually handle error states which support softfails
- let errorcause = eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status", "", true);
- switch (errorcause) {
- case "":
- break;
-
- case "Sync.4": //Malformed request
- case "Sync.6": //Invalid item
- //some servers send a global error - to catch this, we reduce the number of items we send to the server
- if (sendItems.length == 1) {
- //the request contained only one item, so we know which one failed
- if (sendItems[0].type == "deleted_by_user") {
- //we failed to delete an item, discard and place message in log
- syncData.target.removeItemFromChangeLog(sendItems[0].id);
- TbSync.eventlog.add("warning", syncData.eventLogInfo, "ErrorOnDelete::"+sendItems[0].id);
- } else {
- let foundItem = await syncData.target.getItem(sendItems[0].id);
- if (foundItem) {
- eas.sync.updateFailedItems(syncData, errorcause, foundItem.primaryKey, foundItem.toString());
- } else {
- //should not happen
- syncData.target.removeItemFromChangeLog(sendItems[0].id);
- }
- }
- syncData.progressData.inc();
- //restore numberOfItemsToSend
- numberOfItemsToSend = maxnumbertosend;
- } else if (sendItems.length > 1) {
- //reduce further
- numberOfItemsToSend = Math.min(1, Math.round(sendItems.length / 5));
- } else {
- //sendItems.length == 0 ??? recheck but this time let it handle all cases
- eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
- }
- break;
-
- default:
- //recheck but this time let it handle all cases
- eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
- }
-
- await TbSync.tools.sleep(10, true);
-
- if (errorcause == "") {
- //PROCESS RESPONSE
- await eas.sync.processResponses(wbxmlData, syncData, addedItems, changedItems);
-
- //PROCESS COMMANDS
- await eas.sync.processCommands(wbxmlData, syncData);
-
- //remove all items from changelog that did not fail
- for (let a=0; a < changedItems.length; a++) {
- syncData.target.removeItemFromChangeLog(changedItems[a]);
- syncData.progressData.inc();
- }
-
- //update synckey
- eas.network.updateSynckey(syncData, wbxmlData);
- }
-
- } else if (e==0) { //if there was no local change and also no error (which will not happen twice) finish
-
- done = true;
-
- }
-
- } while (!done);
-
- //was there an error?
- if (syncData.failedItems.length > 0) {
- throw eas.sync.finish("warning", "ServerRejectedSomeItems::" + syncData.failedItems.length);
- }
- return sendChanges;
- },
-
-
-
-
- revertLocalChanges: async function (syncData) {
- let maxnumbertosend = eas.prefs.getIntPref("maxitems");
- syncData.progressData.reset(0, syncData.target.getItemsFromChangeLog().length);
- if (syncData.progressData.todo == 0) {
- return;
- }
-
- let viaItemOperations = (syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("ItemOperations"));
-
- //get changed items from ChangeLog
- do {
- syncData.setSyncState("prepare.request.revertlocalchanges");
- let changes = syncData.target.getItemsFromChangeLog(maxnumbertosend);
- let c=0;
- syncData.request = "";
- syncData.response = "";
-
- // BUILD WBXML
- let wbxml = eas.wbxmltools.createWBXML();
- if (viaItemOperations) {
- wbxml.switchpage("ItemOperations");
- wbxml.otag("ItemOperations");
- } else {
- wbxml.otag("Sync");
- wbxml.otag("Collections");
- wbxml.otag("Collection");
- if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
- wbxml.atag("SyncKey", syncData.synckey);
- wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
- wbxml.otag("Commands");
- }
-
- for (let i=0; i 0) { //if there was at least one actual local change, send request
- let error = false;
- let wbxmlData = "";
-
- //SEND REQUEST & VALIDATE RESPONSE
- try {
- syncData.setSyncState("send.request.revertlocalchanges");
- let response = await eas.network.sendRequest(wbxml.getBytes(), (viaItemOperations) ? "ItemOperations" : "Sync", syncData);
-
- syncData.setSyncState("eval.response.revertlocalchanges");
-
- //get data from wbxml response
- wbxmlData = eas.network.getDataFromResponse(response);
- } catch (e) {
- //we do not handle errors, IF there was an error, wbxmlData is empty and will trigger the fallback
- }
-
- let fetchPath = (viaItemOperations) ? "ItemOperations.Response.Fetch" : "Sync.Collections.Collection.Responses.Fetch";
- if (eas.xmltools.hasWbxmlDataField(wbxmlData, fetchPath)) {
-
- //looking for additions
- let add = eas.xmltools.nodeAsArray(eas.xmltools.getWbxmlDataField(wbxmlData, fetchPath));
- for (let count = 0; count < add.length; count++) {
- await TbSync.tools.sleep(10, true);
-
- let ServerId = add[count].ServerId;
- let data = (viaItemOperations) ? add[count].Properties : add[count].ApplicationData;
-
- if (data && ServerId) {
- let foundItem = await syncData.target.getItem(ServerId);
- if (!foundItem) { //do NOT add, if an item with that ServerId was found
- let newItem = eas.sync.createItem(syncData);
- try {
- eas.sync[syncData.type].setThunderbirdItemFromWbxml(newItem, data, ServerId, syncData);
- await syncData.target.addItem(newItem);
- } catch (e) {
- eas.xmltools.printXmlData(add[count], true); //include application data in log
- TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", newItem.toString());
- throw e; // unable to add item to Thunderbird - fatal error
- }
- } else {
- //should not happen, since we deleted that item beforehand
- syncData.target.removeItemFromChangeLog(ServerId);
- }
- syncData.progressData.inc();
- } else {
- error = true;
- break;
- }
- }
- } else {
- error = true;
- }
-
- if (error) {
- //if ItemOperations.Fetch fails, fall back to Sync.Fetch, if that fails, fall back to resync
- if (viaItemOperations) {
- viaItemOperations = false;
- TbSync.eventlog.add("info", syncData.eventLogInfo, "Server returned error during ItemOperations.Fetch, falling back to Sync.Fetch.");
- } else {
- await eas.sync.revertLocalChangesViaResync(syncData);
- return;
- }
- }
-
- } else { //if there was no more local change we need to revert, return
-
- return;
-
- }
-
- } while (true);
-
- },
-
- revertLocalChangesViaResync: async function (syncData) {
- TbSync.eventlog.add("info", syncData.eventLogInfo, "Server does not support ItemOperations.Fetch and/or Sync.Fetch, must revert via resync.");
- let changes = syncData.target.getItemsFromChangeLog();
-
- syncData.progressData.reset(0, changes.length);
- syncData.setSyncState("prepare.request.revertlocalchanges");
-
- //remove all changes, so we can get them fresh from the server
- for (let i=0; i-1) changedItems.splice(p,1);
- }
-
- }
- }
-
- //looking for deletions
- let del = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Responses.Delete);
- for (let count = 0; count < del.length; count++) {
- //What can we do about failed deletes? SyncLog
- eas.network.checkStatus(syncData, del[count],"Status","Sync.Collections.Collection.Responses.Delete["+count+"].Status", true);
- }
-
- }
- },
-
-
-
-
-
-
-
-
-
-
- // ---------------------------------------------------------------------------
- // HELPER FUNCTIONS AND DEFINITIONS
- // ---------------------------------------------------------------------------
-
- MAP_EAS2TB : {
- //EAS Importance: 0 = LOW | 1 = NORMAL | 2 = HIGH
- Importance : { "0":"9", "1":"5", "2":"1"}, //to PRIORITY
- //EAS Sensitivity : 0 = Normal | 1 = Personal | 2 = Private | 3 = Confidential
- Sensitivity : { "0":"PUBLIC", "1":"PRIVATE", "2":"PRIVATE", "3":"CONFIDENTIAL"}, //to CLASS
- //EAS BusyStatus: 0 = Free | 1 = Tentative | 2 = Busy | 3 = Work | 4 = Elsewhere
- BusyStatus : {"0":"TRANSPARENT", "1":"unset", "2":"OPAQUE", "3":"OPAQUE", "4":"OPAQUE"}, //to TRANSP
- //EAS AttendeeStatus: 0 =Response unknown (but needed) | 2 = Tentative | 3 = Accept | 4 = Decline | 5 = Not responded (and not needed) || 1 = Organizer in ResponseType
- ATTENDEESTATUS : {"0": "NEEDS-ACTION", "1":"Orga", "2":"TENTATIVE", "3":"ACCEPTED", "4":"DECLINED", "5":"ACCEPTED"},
- },
-
- MAP_TB2EAS : {
- //TB PRIORITY: 9 = LOW | 5 = NORMAL | 1 = HIGH
- PRIORITY : { "9":"0", "5":"1", "1":"2","unset":"1"}, //to Importance
- //TB CLASS: PUBLIC, PRIVATE, CONFIDENTIAL)
- CLASS : { "PUBLIC":"0", "PRIVATE":"2", "CONFIDENTIAL":"3", "unset":"0"}, //to Sensitivity
- //TB TRANSP : free = TRANSPARENT, busy = OPAQUE)
- TRANSP : {"TRANSPARENT":"0", "unset":"1", "OPAQUE":"2"}, // to BusyStatus
- //TB STATUS: NEEDS-ACTION, ACCEPTED, DECLINED, TENTATIVE, (DELEGATED, COMPLETED, IN-PROCESS - for todo)
- ATTENDEESTATUS : {"NEEDS-ACTION":"0", "ACCEPTED":"3", "DECLINED":"4", "TENTATIVE":"2", "DELEGATED":"5","COMPLETED":"5", "IN-PROCESS":"5"},
- },
-
- mapEasPropertyToThunderbird : function (easProp, tbProp, data, item) {
- if (data[easProp]) {
- //store original EAS value
- let easPropValue = eas.xmltools.checkString(data[easProp]);
- item.setProperty("X-EAS-" + easProp, easPropValue);
- //map EAS value to TB value (use setCalItemProperty if there is one option which can unset/delete the property)
- eas.tools.setCalItemProperty(item, tbProp, eas.sync.MAP_EAS2TB[easProp][easPropValue]);
- }
- },
-
- mapThunderbirdPropertyToEas: function (tbProp, easProp, item) {
- if (item.hasProperty("X-EAS-" + easProp) && eas.tools.getCalItemProperty(item, tbProp) == eas.sync.MAP_EAS2TB[easProp][item.getProperty("X-EAS-" + easProp)]) {
- //we can use our stored EAS value, because it still maps to the current TB value
- return item.getProperty("X-EAS-" + easProp);
- } else {
- return eas.sync.MAP_TB2EAS[tbProp][eas.tools.getCalItemProperty(item, tbProp)];
- }
- },
-
- getEasItemType(aItem) {
- if (aItem instanceof TbSync.addressbook.AbItem) {
- return "Contacts";
- } else if (aItem instanceof TbSync.lightning.TbItem) {
- return aItem.isTodo ? "Tasks" : "Calendar";
- } else {
- throw "Unknown aItem.";
- }
- },
-
- createItem(syncData) {
- switch (syncData.type) {
- case "Contacts":
- return syncData.target.createNewCard();
- break;
-
- case "Tasks":
- return syncData.target.createNewTodo();
- break;
-
- case "Calendar":
- return syncData.target.createNewEvent();
- break;
-
- default:
- throw "Unknown item type <" + syncData.type + ">";
- }
- },
-
- async getWbxmlFromThunderbirdItem(item, syncData, isException = false) {
- try {
- let wbxml = await eas.sync[syncData.type].getWbxmlFromThunderbirdItem(item, syncData, isException);
- return wbxml;
- } catch (e) {
- TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", item.toString());
- throw e; // unable to read item from Thunderbird - fatal error
- }
- },
-
-
-
-
-
-
-
- // ---------------------------------------------------------------------------
- // LIGHTNING HELPER FUNCTIONS AND DEFINITIONS
- // These functions are needed only by tasks and events, so they
- // are placed here, even though they are not type independent,
- // but I did not want to add another "lightning" sub layer.
- //
- // The item in these functions is a native lightning item.
- // ---------------------------------------------------------------------------
-
- setItemSubject: function (item, syncData, data) {
- if (data.Subject) item.title = eas.xmltools.checkString(data.Subject);
- },
-
- setItemLocation: function (item, syncData, data) {
- if (data.Location) item.setProperty("location", eas.xmltools.checkString(data.Location));
- },
-
-
- setItemCategories: function (item, syncData, data) {
- if (data.Categories && data.Categories.Category) {
- let cats = [];
- if (Array.isArray(data.Categories.Category)) cats = data.Categories.Category;
- else cats.push(data.Categories.Category);
- item.setCategories(cats);
- }
- },
-
- getItemCategories: function (item, syncData) {
- let asversion = syncData.accountData.getAccountProperty("asversion");
- let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks, Contacts etc)
-
- //to properly "blank" categories, we need to always include the container
- let categories = item.getCategories({});
- if (categories.length > 0) {
- wbxml.otag("Categories");
- for (let i=0; i 0 && */ data.Body.Data) item.setProperty("description", eas.xmltools.checkString(data.Body.Data)); //EstimatedDataSize is optional
- }
- },
-
- getItemBody: function (item, syncData) {
- let asversion = syncData.accountData.getAccountProperty("asversion");
- let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks, Contacts etc)
-
- let description = (item.hasProperty("description")) ? item.getProperty("description") : "";
- if (asversion == "2.5") {
- wbxml.atag("Body", description);
- } else {
- wbxml.switchpage("AirSyncBase");
- wbxml.otag("Body");
- wbxml.atag("Type", "1");
- wbxml.atag("EstimatedDataSize", "" + description.length);
- wbxml.atag("Data", description);
- wbxml.ctag();
- //does not work with horde at the moment, does not work with task, does not work with exceptions
- //if (syncData.accountData.getAccountProperty("horde") == "0") wbxml.atag("NativeBodyType", "1");
-
- //return to code page of this type
- wbxml.switchpage(syncData.type);
- }
- return wbxml.getBytes();
- },
-
- //item is a native lightning item
- setItemRecurrence: function (item, syncData, data, timezone) {
- if (data.Recurrence) {
- item.recurrenceInfo = new CalRecurrenceInfo();
- item.recurrenceInfo.item = item;
- let recRule = TbSync.lightning.cal.createRecurrenceRule();
- switch (data.Recurrence.Type) {
- case "0":
- recRule.type = "DAILY";
- break;
- case "1":
- recRule.type = "WEEKLY";
- break;
- case "2":
- case "3":
- recRule.type = "MONTHLY";
- break;
- case "5":
- case "6":
- recRule.type = "YEARLY";
- break;
- }
-
- if (data.Recurrence.CalendarType) {
- // TODO
- }
- if (data.Recurrence.DayOfMonth) {
- recRule.setComponent("BYMONTHDAY", [data.Recurrence.DayOfMonth]);
- }
- if (data.Recurrence.DayOfWeek) {
- let DOW = data.Recurrence.DayOfWeek;
- if (DOW == 127 && (recRule.type == "MONTHLY" || recRule.type == "YEARLY")) {
- recRule.setComponent("BYMONTHDAY", [-1]);
- }
- else {
- let days = [];
- for (let i = 0; i < 7; ++i) {
- if (DOW & 1 << i) days.push(i + 1);
- }
- if (data.Recurrence.WeekOfMonth) {
- for (let i = 0; i < days.length; ++i) {
- if (data.Recurrence.WeekOfMonth == 5) {
- days[i] = -1 * (days[i] + 8);
- }
- else {
- days[i] += 8 * (data.Recurrence.WeekOfMonth - 0);
- }
- }
- }
- recRule.setComponent("BYDAY", days);
- }
- }
- if (data.Recurrence.FirstDayOfWeek) {
- //recRule.setComponent("WKST", [data.Recurrence.FirstDayOfWeek]); // WKST is not a valid component
- //recRule.weekStart = data.Recurrence.FirstDayOfWeek; // - (NS_ERROR_NOT_IMPLEMENTED) [calIRecurrenceRule.weekStart]
- TbSync.eventlog.add("info", syncData.eventLogInfo, "FirstDayOfWeek tag ignored (not supported).", item.icalString);
- }
-
- if (data.Recurrence.Interval) {
- recRule.interval = data.Recurrence.Interval;
- }
- if (data.Recurrence.IsLeapMonth) {
- // TODO
- }
- if (data.Recurrence.MonthOfYear) {
- recRule.setComponent("BYMONTH", [data.Recurrence.MonthOfYear]);
- }
- if (data.Recurrence.Occurrences) {
- recRule.count = data.Recurrence.Occurrences;
- }
- if (data.Recurrence.Until) {
- //time string could be in compact/basic or extended form of ISO 8601,
- //cal.createDateTime only supports compact/basic, our own method takes both styles
- recRule.untilDate = eas.tools.createDateTime(data.Recurrence.Until);
- }
- if (data.Recurrence.Start) {
- TbSync.eventlog.add("info", syncData.eventLogInfo, "Start tag in recurring task is ignored, recurrence will start with first entry.", item.icalString);
- }
-
- item.recurrenceInfo.insertRecurrenceItemAt(recRule, 0);
-
- if (data.Exceptions && syncData.type == "Calendar") { // only events, tasks cannot have exceptions
- // Exception could be an object or an array of objects
- let exceptions = [].concat(data.Exceptions.Exception);
- for (let exception of exceptions) {
- //exception.ExceptionStartTime is in UTC, but the Recurrence Object is in local timezone
- let dateTime = TbSync.lightning.cal.createDateTime(exception.ExceptionStartTime).getInTimezone(timezone);
- if (data.AllDayEvent == "1") {
- dateTime.isDate = true;
- // Pass to replacement event unless overriden
- if (!exception.AllDayEvent) {
- exception.AllDayEvent = "1";
- }
- }
- if (exception.Deleted == "1") {
- item.recurrenceInfo.removeOccurrenceAt(dateTime);
- }
- else {
- let replacement = item.recurrenceInfo.getOccurrenceFor(dateTime);
- // replacement is a native lightning item, so we can access its id via .id
- eas.sync[syncData.type].setThunderbirdItemFromWbxml(replacement, exception, replacement.id, syncData, "recurrence");
- // Reminders should carry over from parent, but setThunderbirdItemFromWbxml clears all alarms
- if (!exception.Reminder && item.getAlarms({}).length) {
- replacement.addAlarm(item.getAlarms({})[0]);
- }
- // Removing a reminder requires EAS 16.0
- item.recurrenceInfo.modifyException(replacement, true);
- }
- }
- }
- }
- },
-
- getItemRecurrence: async function (item, syncData, localStartDate = null) {
- let asversion = syncData.accountData.getAccountProperty("asversion");
- let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks etc)
-
- if (item.recurrenceInfo && (syncData.type == "Calendar" || syncData.type == "Tasks")) {
- let deleted = [];
- let hasRecurrence = false;
- let startDate = (syncData.type == "Calendar") ? item.startDate : item.entryDate;
-
- for (let recRule of item.recurrenceInfo.getRecurrenceItems({})) {
- if (recRule.date) {
- if (recRule.isNegative) {
- // EXDATE
- deleted.push(recRule);
- }
- else {
- // RDATE
- TbSync.eventlog.add("info", syncData.eventLogInfo, "Ignoring RDATE rule (not supported)", recRule.icalString);
- }
- continue;
- }
- if (recRule.isNegative) {
- // EXRULE
- TbSync.eventlog.add("info", syncData.eventLogInfo, "Ignoring EXRULE rule (not supported)", recRule.icalString);
- continue;
- }
-
- // RRULE
- wbxml.otag("Recurrence");
- hasRecurrence = true;
-
- let type = 0;
- let monthDays = recRule.getComponent("BYMONTHDAY", {});
- let weekDays = recRule.getComponent("BYDAY", {});
- let months = recRule.getComponent("BYMONTH", {});
- let weeks = [];
-
- // Unpack 1MO style days
- for (let i = 0; i < weekDays.length; ++i) {
- if (weekDays[i] > 8) {
- weeks[i] = Math.floor(weekDays[i] / 8);
- weekDays[i] = weekDays[i] % 8;
- }
- else if (weekDays[i] < -8) {
- // EAS only supports last week as a special value, treat
- // all as last week or assume every month has 5 weeks?
- // Change to last week
- //weeks[i] = 5;
- // Assumes 5 weeks per month for week <= -2
- weeks[i] = 6 - Math.floor(-weekDays[i] / 8);
- weekDays[i] = -weekDays[i] % 8;
- }
- }
- if (monthDays[0] && monthDays[0] == -1) {
- weeks = [5];
- weekDays = [1, 2, 3, 4, 5, 6, 7]; // 127
- monthDays[0] = null;
- }
- // Type
- if (recRule.type == "WEEKLY") {
- type = 1;
- if (!weekDays.length) {
- weekDays = [startDate.weekday + 1];
- }
- }
- else if (recRule.type == "MONTHLY" && weeks.length) {
- type = 3;
- }
- else if (recRule.type == "MONTHLY") {
- type = 2;
- if (!monthDays.length) {
- monthDays = [startDate.day];
- }
- }
- else if (recRule.type == "YEARLY" && weeks.length) {
- type = 6;
- }
- else if (recRule.type == "YEARLY") {
- type = 5;
- if (!monthDays.length) {
- monthDays = [startDate.day];
- }
- if (!months.length) {
- months = [startDate.month + 1];
- }
- }
- wbxml.atag("Type", type.toString());
-
- //Tasks need a Start tag, but we cannot allow a start date different from the start of the main item (thunderbird does not support that)
- if (localStartDate) wbxml.atag("Start", localStartDate);
-
- // TODO: CalendarType: 14.0 and up
- // DayOfMonth
- if (monthDays[0]) {
- // TODO: Multiple days of month - multiple Recurrence tags?
- wbxml.atag("DayOfMonth", monthDays[0].toString());
- }
- // DayOfWeek
- if (weekDays.length) {
- let bitfield = 0;
- for (let day of weekDays) {
- bitfield |= 1 << (day - 1);
- }
- wbxml.atag("DayOfWeek", bitfield.toString());
- }
- // FirstDayOfWeek: 14.1 and up
- //wbxml.atag("FirstDayOfWeek", recRule.weekStart); - (NS_ERROR_NOT_IMPLEMENTED) [calIRecurrenceRule.weekStart]
- // Interval
- wbxml.atag("Interval", recRule.interval.toString());
- // TODO: IsLeapMonth: 14.0 and up
- // MonthOfYear
- if (months.length) {
- wbxml.atag("MonthOfYear", months[0].toString());
- }
- // Occurrences
- if (recRule.isByCount) {
- wbxml.atag("Occurrences", recRule.count.toString());
- }
- // Until
- else if (recRule.untilDate != null) {
- //Events need the Until data in compact form, Tasks in the basic form
- wbxml.atag("Until", eas.tools.getIsoUtcString(recRule.untilDate, (syncData.type == "Tasks")));
- }
- // WeekOfMonth
- if (weeks.length) {
- wbxml.atag("WeekOfMonth", weeks[0].toString());
- }
- wbxml.ctag();
- }
-
- if (syncData.type == "Calendar" && hasRecurrence) { //Exceptions only allowed in Calendar and only if a valid Recurrence was added
- let modifiedIds = item.recurrenceInfo.getExceptionIds({});
- if (deleted.length || modifiedIds.length) {
- wbxml.otag("Exceptions");
- for (let exception of deleted) {
- wbxml.otag("Exception");
- wbxml.atag("ExceptionStartTime", eas.tools.getIsoUtcString(exception.date));
- wbxml.atag("Deleted", "1");
- //Docs say it is allowed, but if present, it does not work
- //if (asversion == "2.5") {
- // wbxml.atag("UID", item.id); //item.id is not valid, use UID or primaryKey
- //}
- wbxml.ctag();
- }
- for (let exceptionId of modifiedIds) {
- let replacement = item.recurrenceInfo.getExceptionFor(exceptionId);
- wbxml.otag("Exception");
- wbxml.atag("ExceptionStartTime", eas.tools.getIsoUtcString(exceptionId));
- wbxml.append(await eas.sync.getWbxmlFromThunderbirdItem(replacement, syncData, true));
- wbxml.ctag();
- }
- wbxml.ctag();
- }
- }
- }
-
- return wbxml.getBytes();
- }
-
-}
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ CalRecurrenceInfo: "resource:///modules/CalRecurrenceInfo.sys.mjs",
+});
+
+// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIEvent.idl
+// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calIItemBase.idl
+// - https://dxr.mozilla.org/comm-central/source/calendar/base/public/calICalendar.idl
+// - https://dxr.mozilla.org/comm-central/source/calendar/base/modules/calAsyncUtils.sys.mjs
+
+// https://msdn.microsoft.com/en-us/library/dd299454(v=exchg.80).aspx
+
+var sync = {
+ finish: function (aStatus = "", msg = "", details = "") {
+ let status = TbSync.StatusData.SUCCESS
+ switch (aStatus) {
+
+ case "":
+ case "ok":
+ status = TbSync.StatusData.SUCCESS;
+ break;
+
+ case "info":
+ status = TbSync.StatusData.INFO;
+ break;
+
+ case "resyncAccount":
+ status = TbSync.StatusData.ACCOUNT_RERUN;
+ break;
+
+ case "resyncFolder":
+ status = TbSync.StatusData.FOLDER_RERUN;
+ break;
+
+ case "warning":
+ status = TbSync.StatusData.WARNING;
+ break;
+
+ case "error":
+ status = TbSync.StatusData.ERROR;
+ break;
+
+ default:
+ console.log("TbSync/EAS: Unknown status <" + aStatus + ">");
+ status = TbSync.StatusData.ERROR;
+ break;
+ }
+
+ let e = new Error();
+ e.name = "eas4tbsync";
+ e.message = status.toUpperCase() + ": " + msg.toString() + " (" + details.toString() + ")";
+ e.statusData = new TbSync.StatusData(status, msg.toString(), details.toString());
+ return e;
+ },
+
+
+ resetFolderSyncInfo: function (folderData) {
+ folderData.resetFolderProperty("synckey");
+ folderData.resetFolderProperty("lastsynctime");
+ },
+
+
+ // update folders avail on server and handle added, removed and renamed
+ // folders
+ folderList: async function (syncData) {
+ //should we recheck options/commands? Always check, if we have no info about asversion!
+ if (syncData.accountData.getAccountProperty("asversion", "") == "" || (Date.now() - syncData.accountData.getAccountProperty("lastEasOptionsUpdate")) > 86400000) {
+ await eas.network.getServerOptions(syncData);
+ }
+
+ //only update the actual used asversion, if we are currently not connected or it has not yet been set
+ if (syncData.accountData.getAccountProperty("asversion", "") == "" || !syncData.accountData.isConnected()) {
+ //eval the currently in the UI selected EAS version
+ let asversionselected = syncData.accountData.getAccountProperty("asversionselected");
+ let allowedVersionsString = syncData.accountData.getAccountProperty("allowedEasVersions").trim();
+ let allowedVersionsArray = allowedVersionsString.split(",");
+
+ if (asversionselected == "auto") {
+ if (allowedVersionsArray.includes("14.0")) syncData.accountData.setAccountProperty("asversion", "14.0");
+ else if (allowedVersionsArray.includes("2.5")) syncData.accountData.setAccountProperty("asversion", "2.5");
+ else if (allowedVersionsString == "") {
+ throw eas.sync.finish("error", "InvalidServerOptions");
+ } else {
+ throw eas.sync.finish("error", "nosupportedeasversion::" + allowedVersionsArray.join(", "));
+ }
+ } else if (allowedVersionsString != "" && !allowedVersionsArray.includes(asversionselected)) {
+ throw eas.sync.finish("error", "notsupportedeasversion::" + asversionselected + "::" + allowedVersionsArray.join(", "));
+ } else {
+ //just use the value set by the user
+ syncData.accountData.setAccountProperty("asversion", asversionselected);
+ }
+ }
+
+ //do we need to get a new policy key?
+ if (syncData.accountData.getAccountProperty("provision") && syncData.accountData.getAccountProperty("policykey") == "0") {
+ await eas.network.getPolicykey(syncData);
+ }
+
+ //set device info
+ await eas.network.setDeviceInformation(syncData);
+
+ syncData.setSyncState("prepare.request.folders");
+ let foldersynckey = syncData.accountData.getAccountProperty("foldersynckey");
+
+ //build WBXML to request foldersync
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("FolderHierarchy");
+ wbxml.otag("FolderSync");
+ wbxml.atag("SyncKey", foldersynckey);
+ wbxml.ctag();
+
+ syncData.setSyncState("send.request.folders");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "FolderSync", syncData);
+
+ syncData.setSyncState("eval.response.folders");
+ let wbxmlData = eas.network.getDataFromResponse(response);
+ eas.network.checkStatus(syncData, wbxmlData, "FolderSync.Status");
+
+ let synckey = eas.xmltools.getWbxmlDataField(wbxmlData, "FolderSync.SyncKey");
+ if (synckey) {
+ syncData.accountData.setAccountProperty("foldersynckey", synckey);
+ } else {
+ throw eas.sync.finish("error", "wbxmlmissingfield::FolderSync.SyncKey");
+ }
+
+ // If we reach this point, wbxmlData contains FolderSync node,
+ // so the next "if" will not fail with an javascript error, no need
+ // to use save getWbxmlDataField function.
+
+ // Are there any changes in folder hierarchy?
+ if (wbxmlData.FolderSync.Changes) {
+ // Looking for additions.
+ let add = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Add);
+ for (let count = 0; count < add.length; count++) {
+ // Only add allowed folder types to DB (include trash(4), so we can find trashed folders.
+ if (!["9", "14", "8", "13", "7", "15", "4"].includes(add[count].Type))
+ continue;
+
+ let existingFolder = syncData.accountData.getFolder("serverID", add[count].ServerId);
+ if (existingFolder) {
+ // Server has send us an ADD for a folder we alreay have, treat as update.
+ existingFolder.setFolderProperty("foldername", add[count].DisplayName);
+ existingFolder.setFolderProperty("type", add[count].Type);
+ existingFolder.setFolderProperty("parentID", add[count].ParentId);
+ } else {
+ // Create folder obj for new folder settings.
+ let newFolder = syncData.accountData.createNewFolder();
+ switch (add[count].Type) {
+ case "9": // contact
+ case "14":
+ newFolder.setFolderProperty("targetType", "addressbook");
+ break;
+ case "8": // event
+ case "13":
+ newFolder.setFolderProperty("targetType", "calendar");
+ break;
+ case "7": // todo
+ case "15":
+ newFolder.setFolderProperty("targetType", "calendar");
+ break;
+ default:
+ newFolder.setFolderProperty("targetType", "unknown type (" + add[count].Type + ")");
+ break;
+
+ }
+
+ newFolder.setFolderProperty("serverID", add[count].ServerId);
+ newFolder.setFolderProperty("foldername", add[count].DisplayName);
+ newFolder.setFolderProperty("type", add[count].Type);
+ newFolder.setFolderProperty("parentID", add[count].ParentId);
+
+ // Do we have a cached folder?
+ let cachedFolderData = syncData.accountData.getFolderFromCache("serverID", add[count].ServerId);
+ if (cachedFolderData) {
+ // Copy fields from cache which we want to re-use.
+ newFolder.setFolderProperty("targetColor", cachedFolderData.getFolderProperty("targetColor"));
+ newFolder.setFolderProperty("targetName", cachedFolderData.getFolderProperty("targetName"));
+ newFolder.setFolderProperty("downloadonly", cachedFolderData.getFolderProperty("downloadonly"));
+ }
+ }
+ }
+
+ // Looking for updates.
+ let update = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Update);
+ for (let count = 0; count < update.length; count++) {
+ let existingFolder = syncData.accountData.getFolder("serverID", update[count].ServerId);
+ if (existingFolder) {
+ // Update folder.
+ existingFolder.setFolderProperty("foldername", update[count].DisplayName);
+ existingFolder.setFolderProperty("type", update[count].Type);
+ existingFolder.setFolderProperty("parentID", update[count].ParentId);
+ }
+ }
+
+ // Looking for deletes. Do not delete the targets,
+ // but keep them as stale/unconnected elements.
+ let del = eas.xmltools.nodeAsArray(wbxmlData.FolderSync.Changes.Delete);
+ for (let count = 0; count < del.length; count++) {
+ let existingFolder = syncData.accountData.getFolder("serverID", del[count].ServerId);
+ if (existingFolder) {
+ existingFolder.remove("[deleted on server]");
+ }
+ }
+ }
+ },
+
+
+
+
+
+ deleteFolder: async function (syncData) {
+ if (!syncData.currentFolderData) {
+ return;
+ }
+
+ if (!syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("FolderDelete")) {
+ throw eas.sync.finish("error", "notsupported::FolderDelete");
+ }
+
+ syncData.setSyncState("prepare.request.deletefolder");
+ let foldersynckey = syncData.accountData.getAccountProperty("foldersynckey");
+
+ //request foldersync
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.switchpage("FolderHierarchy");
+ wbxml.otag("FolderDelete");
+ wbxml.atag("SyncKey", foldersynckey);
+ wbxml.atag("ServerId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.ctag();
+
+ syncData.setSyncState("send.request.deletefolder");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "FolderDelete", syncData);
+
+ syncData.setSyncState("eval.response.deletefolder");
+ let wbxmlData = eas.network.getDataFromResponse(response);
+
+ eas.network.checkStatus(syncData, wbxmlData, "FolderDelete.Status");
+
+ let synckey = eas.xmltools.getWbxmlDataField(wbxmlData, "FolderDelete.SyncKey");
+ if (synckey) {
+ syncData.accountData.setAccountProperty("foldersynckey", synckey);
+ syncData.currentFolderData.remove();
+ } else {
+ throw eas.sync.finish("error", "wbxmlmissingfield::FolderDelete.SyncKey");
+ }
+ },
+
+
+
+
+
+ singleFolder: async function (syncData) {
+ // add target to syncData
+ try {
+ // accessing the target for the first time will check if it is avail and if not will create it (if possible)
+ syncData.target = await syncData.currentFolderData.targetData.getTarget();
+ } catch (e) {
+ Components.utils.reportError(e);
+ throw eas.sync.finish("warning", e.message);
+ }
+
+ //get syncData type, which is also used in WBXML for the CLASS element
+ syncData.type = null;
+ switch (syncData.currentFolderData.getFolderProperty("type")) {
+ case "9": //contact
+ case "14":
+ syncData.type = "Contacts";
+ break;
+ case "8": //event
+ case "13":
+ syncData.type = "Calendar";
+ break;
+ case "7": //todo
+ case "15":
+ syncData.type = "Tasks";
+ break;
+ default:
+ throw eas.sync.finish("info", "skipped");
+ break;
+ }
+
+ syncData.setSyncState("preparing");
+
+ //get synckey if needed
+ syncData.synckey = syncData.currentFolderData.getFolderProperty("synckey");
+ if (syncData.synckey == "") {
+ await eas.network.getSynckey(syncData);
+ }
+
+ //sync folder
+ syncData.timeOfLastSync = syncData.currentFolderData.getFolderProperty("lastsynctime") / 1000;
+ syncData.timeOfThisSync = (Date.now() / 1000) - 1;
+
+ let lightningBatch = false;
+ let lightningReadOnly = "";
+ let error = null;
+
+ // We ned to intercept any throw error, because lightning needs a few operations after sync finished
+ try {
+ switch (syncData.type) {
+ case "Contacts":
+ await eas.sync.easFolder(syncData);
+ break;
+
+ case "Calendar":
+ case "Tasks":
+ //save current value of readOnly (or take it from the setting)
+ lightningReadOnly = syncData.target.calendar.getProperty("readOnly") || syncData.currentFolderData.getFolderProperty("downloadonly");
+ syncData.target.calendar.setProperty("readOnly", false);
+
+ lightningBatch = true;
+ syncData.target.calendar.startBatch();
+
+ await eas.sync.easFolder(syncData);
+ break;
+ }
+ } catch (report) {
+ error = report;
+ }
+
+ if (lightningBatch) {
+ syncData.target.calendar.endBatch();
+ syncData.target.calendar.setProperty("readOnly", lightningReadOnly);
+ }
+
+ if (error) throw error;
+ },
+
+
+
+
+
+
+
+
+
+
+ // ---------------------------------------------------------------------------
+ // MAIN FUNCTIONS TO SYNC AN EAS FOLDER
+ // ---------------------------------------------------------------------------
+
+ easFolder: async function (syncData) {
+ syncData.progressData.reset();
+
+ if (syncData.currentFolderData.getFolderProperty("downloadonly")) {
+ await eas.sync.revertLocalChanges(syncData);
+ }
+
+ await eas.network.getItemEstimate(syncData);
+ await eas.sync.requestRemoteChanges(syncData);
+
+ if (!syncData.currentFolderData.getFolderProperty("downloadonly")) {
+ let sendChanges = await eas.sync.sendLocalChanges(syncData);
+ if (sendChanges) {
+ // This is ugly as hell, but Microsoft sometimes sets the state of the
+ // remote account to "changed" after we have send a local change (even
+ // though it has acked the change) and this will cause the server to
+ // send a change request with our next sync. Because we follow the
+ // "server wins" policy, this will overwrite any additional local change
+ // we have done in the meantime. This is stupid, but we wait 2s and
+ // hope it is enough to catch this second ack of the local change.
+ let timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
+ await new Promise(function (resolve, reject) {
+ let event = {
+ notify: function (timer) {
+ resolve();
+ }
+ }
+ timer.initWithCallback(event, 2000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ });
+ await eas.sync.requestRemoteChanges(syncData);
+ }
+ }
+ },
+
+
+ requestRemoteChanges: async function (syncData) {
+ do {
+ syncData.setSyncState("prepare.request.remotechanges");
+ syncData.request = "";
+ syncData.response = "";
+
+ // BUILD WBXML
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.otag("Sync");
+ wbxml.otag("Collections");
+ wbxml.otag("Collection");
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
+ wbxml.atag("SyncKey", syncData.synckey);
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.atag("DeletesAsMoves");
+ wbxml.atag("GetChanges");
+ wbxml.atag("WindowSize", eas.prefs.getIntPref("maxitems").toString());
+
+ if (syncData.accountData.getAccountProperty("asversion") != "2.5") {
+ wbxml.otag("Options");
+ if (syncData.type == "Calendar") wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
+ wbxml.atag("Class", syncData.type);
+ wbxml.switchpage("AirSyncBase");
+ wbxml.otag("BodyPreference");
+ wbxml.atag("Type", "1");
+ wbxml.ctag();
+ wbxml.switchpage("AirSync");
+ wbxml.ctag();
+ } else if (syncData.type == "Calendar") { //in 2.5 we only send it to filter Calendar
+ wbxml.otag("Options");
+ wbxml.atag("FilterType", syncData.currentFolderData.accountData.getAccountProperty("synclimit"));
+ wbxml.ctag();
+ }
+
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.ctag();
+
+ //SEND REQUEST
+ syncData.setSyncState("send.request.remotechanges");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
+
+ //VALIDATE RESPONSE
+ // get data from wbxml response, some servers send empty response if there are no changes, which is not an error
+ let wbxmlData = eas.network.getDataFromResponse(response, eas.flags.allowEmptyResponse);
+ if (wbxmlData === null) return;
+
+ //check status, throw on error
+ eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
+
+ //PROCESS COMMANDS
+ await eas.sync.processCommands(wbxmlData, syncData);
+
+ //Update count in UI
+ syncData.setSyncState("eval.response.remotechanges");
+
+ //update synckey
+ eas.network.updateSynckey(syncData, wbxmlData);
+
+ if (!eas.xmltools.hasWbxmlDataField(wbxmlData, "Sync.Collections.Collection.MoreAvailable")) {
+ //Feedback from users: They want to see the final count
+ await TbSync.tools.sleep(100);
+ return;
+ }
+ } while (true);
+
+ },
+
+
+ sendLocalChanges: async function (syncData) {
+ let maxnumbertosend = eas.prefs.getIntPref("maxitems");
+ syncData.progressData.reset(0, syncData.target.getItemsFromChangeLog().length);
+
+ //keep track of failed items
+ syncData.failedItems = [];
+
+ let done = false;
+ let numberOfItemsToSend = maxnumbertosend;
+ let sendChanges = false;
+ do {
+ syncData.setSyncState("prepare.request.localchanges");
+ syncData.request = "";
+ syncData.response = "";
+
+ //get changed items from ChangeLog
+ let changes = syncData.target.getItemsFromChangeLog(numberOfItemsToSend);
+ //console.log("chnages", changes);
+ let c = 0;
+ let e = 0;
+
+ //keep track of send items during this request
+ let changedItems = [];
+ let addedItems = {};
+ let sendItems = [];
+
+ // BUILD WBXML
+ let wbxml = eas.wbxmltools.createWBXML();
+ wbxml.otag("Sync");
+ wbxml.otag("Collections");
+ wbxml.otag("Collection");
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
+ wbxml.atag("SyncKey", syncData.synckey);
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.otag("Commands");
+
+ for (let i = 0; i < changes.length; i++) if (!syncData.failedItems.includes(changes[i].itemId)) {
+ //TbSync.dump("CHANGES",(i+1) + "/" + changes.length + " ("+changes[i].status+"," + changes[i].itemId + ")");
+ let item = null;
+ switch (changes[i].status) {
+
+ case "added_by_user":
+ item = await syncData.target.getItem(changes[i].itemId);
+ if (item) {
+ //filter out bad object types for this folder
+ if (syncData.type == "Contacts" && item.isMailList) {
+ // Mailing lists are not supported, this is not an error
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "MailingListNotSupportedItemSkipped");
+ syncData.target.removeItemFromChangeLog(changes[i].itemId);
+ } else if (syncData.type == eas.sync.getEasItemType(item)) {
+ //create a temp clientId, to cope with too long or invalid clientIds (for EAS)
+ let clientId = Date.now() + "-" + c;
+ addedItems[clientId] = changes[i].itemId;
+ sendItems.push({ type: changes[i].status, id: changes[i].itemId });
+
+ wbxml.otag("Add");
+ wbxml.atag("ClientId", clientId); //Our temp clientId will get replaced by an id generated by the server
+ wbxml.otag("ApplicationData");
+ wbxml.switchpage(syncData.type);
+
+ /*wbxml.atag("TimeZone", "xP///0UAdQByAG8AcABlAC8AQgBlAHIAbABpAG4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAIAAAAAAAAAAAAAAEUAdQByAG8AcABlAC8AQgBlAHIAbABpAG4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAEAAAAAAAAAxP///w==");
+ wbxml.atag("AllDayEvent", "0");
+ wbxml.switchpage("AirSyncBase");
+ wbxml.otag("Body");
+ wbxml.atag("Type", "1");
+ wbxml.atag("EstimatedDataSize", "0");
+ wbxml.atag("Data");
+ wbxml.ctag();
+
+ wbxml.switchpage(syncData.type);
+ wbxml.atag("BusyStatus", "2");
+ wbxml.atag("OrganizerName", "REDACTED.REDACTED");
+ wbxml.atag("OrganizerEmail", "REDACTED.REDACTED@REDACTED");
+ wbxml.atag("DtStamp", "20190131T091024Z");
+ wbxml.atag("EndTime", "20180906T083000Z");
+ wbxml.atag("Location");
+ wbxml.atag("Reminder", "5");
+ wbxml.atag("Sensitivity", "0");
+ wbxml.atag("Subject", "SE-CN weekly sync");
+ wbxml.atag("StartTime", "20180906T080000Z");
+ wbxml.atag("UID", "1D51E503-9DFE-4A46-A6C2-9129E5E00C1D");
+ wbxml.atag("MeetingStatus", "3");
+ wbxml.otag("Attendees");
+ wbxml.otag("Attendee");
+ wbxml.atag("Email", "REDACTED.REDACTED@REDACTED");
+ wbxml.atag("Name", "REDACTED.REDACTED");
+ wbxml.atag("AttendeeType", "1");
+ wbxml.ctag();
+ wbxml.ctag();
+ wbxml.atag("Categories");
+ wbxml.otag("Recurrence");
+ wbxml.atag("Type", "1");
+ wbxml.atag("DayOfWeek", "16");
+ wbxml.atag("Interval", "1");
+ wbxml.ctag();
+ wbxml.otag("Exceptions");
+ wbxml.otag("Exception");
+ wbxml.atag("ExceptionStartTime", "20181227T090000Z");
+ wbxml.atag("Deleted", "1");
+ wbxml.ctag();
+ wbxml.ctag();*/
+
+ wbxml.append(await eas.sync.getWbxmlFromThunderbirdItem(item, syncData));
+ wbxml.switchpage("AirSync");
+ wbxml.ctag();
+ wbxml.ctag();
+ c++;
+ } else {
+ eas.sync.updateFailedItems(syncData, "forbidden" + eas.sync.getEasItemType(item) + "ItemIn" + syncData.type + "Folder", item.primaryKey, item.toString());
+ e++;
+ }
+ } else {
+ syncData.target.removeItemFromChangeLog(changes[i].itemId);
+ }
+ break;
+
+ case "modified_by_user":
+ item = await syncData.target.getItem(changes[i].itemId);
+ if (item) {
+ //filter out bad object types for this folder
+ if (syncData.type == eas.sync.getEasItemType(item)) {
+ wbxml.otag("Change");
+ wbxml.atag("ServerId", changes[i].itemId);
+ wbxml.otag("ApplicationData");
+ wbxml.switchpage(syncData.type);
+ wbxml.append(await eas.sync.getWbxmlFromThunderbirdItem(item, syncData));
+ wbxml.switchpage("AirSync");
+ wbxml.ctag();
+ wbxml.ctag();
+ changedItems.push(changes[i].itemId);
+ sendItems.push({ type: changes[i].status, id: changes[i].itemId });
+ c++;
+ } else {
+ eas.sync.updateFailedItems(syncData, "forbidden" + eas.sync.getEasItemType(item) + "ItemIn" + syncData.type + "Folder", item.primaryKey, item.toString());
+ e++;
+ }
+ } else {
+ syncData.target.removeItemFromChangeLog(changes[i].itemId);
+ }
+ break;
+
+ case "deleted_by_user":
+ wbxml.otag("Delete");
+ wbxml.atag("ServerId", changes[i].itemId);
+ wbxml.ctag();
+ changedItems.push(changes[i].itemId);
+ sendItems.push({ type: changes[i].status, id: changes[i].itemId });
+ c++;
+ break;
+ }
+ }
+
+ wbxml.ctag(); //Commands
+ wbxml.ctag(); //Collection
+ wbxml.ctag(); //Collections
+ wbxml.ctag(); //Sync
+
+
+ if (c > 0) { //if there was at least one actual local change, send request
+ sendChanges = true;
+ //SEND REQUEST & VALIDATE RESPONSE
+ syncData.setSyncState("send.request.localchanges");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), "Sync", syncData);
+
+ syncData.setSyncState("eval.response.localchanges");
+
+ //get data from wbxml response
+ let wbxmlData = eas.network.getDataFromResponse(response);
+
+ //check status and manually handle error states which support softfails
+ let errorcause = eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status", "", true);
+ switch (errorcause) {
+ case "":
+ break;
+
+ case "Sync.4": //Malformed request
+ case "Sync.6": //Invalid item
+ //some servers send a global error - to catch this, we reduce the number of items we send to the server
+ if (sendItems.length == 1) {
+ //the request contained only one item, so we know which one failed
+ if (sendItems[0].type == "deleted_by_user") {
+ //we failed to delete an item, discard and place message in log
+ syncData.target.removeItemFromChangeLog(sendItems[0].id);
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "ErrorOnDelete::" + sendItems[0].id);
+ } else {
+ let foundItem = await syncData.target.getItem(sendItems[0].id);
+ if (foundItem) {
+ eas.sync.updateFailedItems(syncData, errorcause, foundItem.primaryKey, foundItem.toString());
+ } else {
+ //should not happen
+ syncData.target.removeItemFromChangeLog(sendItems[0].id);
+ }
+ }
+ syncData.progressData.inc();
+ //restore numberOfItemsToSend
+ numberOfItemsToSend = maxnumbertosend;
+ } else if (sendItems.length > 1) {
+ //reduce further
+ numberOfItemsToSend = Math.min(1, Math.round(sendItems.length / 5));
+ } else {
+ //sendItems.length == 0 ??? recheck but this time let it handle all cases
+ eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
+ }
+ break;
+
+ default:
+ //recheck but this time let it handle all cases
+ eas.network.checkStatus(syncData, wbxmlData, "Sync.Collections.Collection.Status");
+ }
+
+ await TbSync.tools.sleep(10, true);
+
+ if (errorcause == "") {
+ //PROCESS RESPONSE
+ await eas.sync.processResponses(wbxmlData, syncData, addedItems, changedItems);
+
+ //PROCESS COMMANDS
+ await eas.sync.processCommands(wbxmlData, syncData);
+
+ //remove all items from changelog that did not fail
+ for (let a = 0; a < changedItems.length; a++) {
+ syncData.target.removeItemFromChangeLog(changedItems[a]);
+ syncData.progressData.inc();
+ }
+
+ //update synckey
+ eas.network.updateSynckey(syncData, wbxmlData);
+ }
+
+ } else if (e == 0) { //if there was no local change and also no error (which will not happen twice) finish
+
+ done = true;
+
+ }
+
+ } while (!done);
+
+ //was there an error?
+ if (syncData.failedItems.length > 0) {
+ throw eas.sync.finish("warning", "ServerRejectedSomeItems::" + syncData.failedItems.length);
+ }
+ return sendChanges;
+ },
+
+
+
+
+ revertLocalChanges: async function (syncData) {
+ let maxnumbertosend = eas.prefs.getIntPref("maxitems");
+ syncData.progressData.reset(0, syncData.target.getItemsFromChangeLog().length);
+ if (syncData.progressData.todo == 0) {
+ return;
+ }
+
+ let viaItemOperations = (syncData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("ItemOperations"));
+
+ //get changed items from ChangeLog
+ do {
+ syncData.setSyncState("prepare.request.revertlocalchanges");
+ let changes = syncData.target.getItemsFromChangeLog(maxnumbertosend);
+ let c = 0;
+ syncData.request = "";
+ syncData.response = "";
+
+ // BUILD WBXML
+ let wbxml = eas.wbxmltools.createWBXML();
+ if (viaItemOperations) {
+ wbxml.switchpage("ItemOperations");
+ wbxml.otag("ItemOperations");
+ } else {
+ wbxml.otag("Sync");
+ wbxml.otag("Collections");
+ wbxml.otag("Collection");
+ if (syncData.accountData.getAccountProperty("asversion") == "2.5") wbxml.atag("Class", syncData.type);
+ wbxml.atag("SyncKey", syncData.synckey);
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.otag("Commands");
+ }
+
+ for (let i = 0; i < changes.length; i++) {
+ let item = null;
+ let ServerId = changes[i].itemId;
+ let foundItem = await syncData.target.getItem(ServerId);
+
+ switch (changes[i].status) {
+ case "added_by_user": //remove
+ if (foundItem) {
+ await syncData.target.deleteItem(foundItem);
+ }
+ break;
+
+ case "modified_by_user":
+ if (foundItem) { //delete item so it can be replaced with a fresh copy, the changelog entry will be changed from modified to deleted
+ await syncData.target.deleteItem(foundItem);
+ }
+ case "deleted_by_user":
+ if (viaItemOperations) {
+ wbxml.otag("Fetch");
+ wbxml.atag("Store", "Mailbox");
+ wbxml.switchpage("AirSync");
+ wbxml.atag("CollectionId", syncData.currentFolderData.getFolderProperty("serverID"));
+ wbxml.atag("ServerId", ServerId);
+ wbxml.switchpage("ItemOperations");
+ wbxml.otag("Options");
+ wbxml.switchpage("AirSyncBase");
+ wbxml.otag("BodyPreference");
+ wbxml.atag("Type", "1");
+ wbxml.ctag();
+ wbxml.switchpage("ItemOperations");
+ wbxml.ctag();
+ wbxml.ctag();
+ } else {
+ wbxml.otag("Fetch");
+ wbxml.atag("ServerId", ServerId);
+ wbxml.ctag();
+ }
+ c++;
+ break;
+ }
+ }
+
+ if (viaItemOperations) {
+ wbxml.ctag(); //ItemOperations
+ } else {
+ wbxml.ctag(); //Commands
+ wbxml.ctag(); //Collection
+ wbxml.ctag(); //Collections
+ wbxml.ctag(); //Sync
+ }
+
+ if (c > 0) { //if there was at least one actual local change, send request
+ let error = false;
+ let wbxmlData = "";
+
+ //SEND REQUEST & VALIDATE RESPONSE
+ try {
+ syncData.setSyncState("send.request.revertlocalchanges");
+ let response = await eas.network.sendRequest(wbxml.getBytes(), (viaItemOperations) ? "ItemOperations" : "Sync", syncData);
+
+ syncData.setSyncState("eval.response.revertlocalchanges");
+
+ //get data from wbxml response
+ wbxmlData = eas.network.getDataFromResponse(response);
+ } catch (e) {
+ //we do not handle errors, IF there was an error, wbxmlData is empty and will trigger the fallback
+ }
+
+ let fetchPath = (viaItemOperations) ? "ItemOperations.Response.Fetch" : "Sync.Collections.Collection.Responses.Fetch";
+ if (eas.xmltools.hasWbxmlDataField(wbxmlData, fetchPath)) {
+
+ //looking for additions
+ let add = eas.xmltools.nodeAsArray(eas.xmltools.getWbxmlDataField(wbxmlData, fetchPath));
+ for (let count = 0; count < add.length; count++) {
+ await TbSync.tools.sleep(10, true);
+
+ let ServerId = add[count].ServerId;
+ let data = (viaItemOperations) ? add[count].Properties : add[count].ApplicationData;
+
+ if (data && ServerId) {
+ let foundItem = await syncData.target.getItem(ServerId);
+ if (!foundItem) { //do NOT add, if an item with that ServerId was found
+ let newItem = eas.sync.createItem(syncData);
+ try {
+ eas.sync[syncData.type].setThunderbirdItemFromWbxml(newItem, data, ServerId, syncData);
+ await syncData.target.addItem(newItem);
+ } catch (e) {
+ eas.xmltools.printXmlData(add[count], true); //include application data in log
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", newItem.toString());
+ throw e; // unable to add item to Thunderbird - fatal error
+ }
+ } else {
+ //should not happen, since we deleted that item beforehand
+ syncData.target.removeItemFromChangeLog(ServerId);
+ }
+ syncData.progressData.inc();
+ } else {
+ error = true;
+ break;
+ }
+ }
+ } else {
+ error = true;
+ }
+
+ if (error) {
+ //if ItemOperations.Fetch fails, fall back to Sync.Fetch, if that fails, fall back to resync
+ if (viaItemOperations) {
+ viaItemOperations = false;
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Server returned error during ItemOperations.Fetch, falling back to Sync.Fetch.");
+ } else {
+ await eas.sync.revertLocalChangesViaResync(syncData);
+ return;
+ }
+ }
+
+ } else { //if there was no more local change we need to revert, return
+
+ return;
+
+ }
+
+ } while (true);
+
+ },
+
+ revertLocalChangesViaResync: async function (syncData) {
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Server does not support ItemOperations.Fetch and/or Sync.Fetch, must revert via resync.");
+ let changes = syncData.target.getItemsFromChangeLog();
+
+ syncData.progressData.reset(0, changes.length);
+ syncData.setSyncState("prepare.request.revertlocalchanges");
+
+ //remove all changes, so we can get them fresh from the server
+ for (let i = 0; i < changes.length; i++) {
+ let item = null;
+ let ServerId = changes[i].itemId;
+ syncData.target.removeItemFromChangeLog(ServerId);
+ let foundItem = await syncData.target.getItem(ServerId);
+ if (foundItem) { //delete item with that ServerId
+ await syncData.target.deleteItem(foundItem);
+ }
+ syncData.progressData.inc();
+ }
+
+ //This will resync all missing items fresh from the server
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "RevertViaFolderResync");
+ eas.sync.resetFolderSyncInfo(syncData.currentFolderData);
+ throw eas.sync.finish("resyncFolder", "RevertViaFolderResync");
+ },
+
+
+
+
+ // ---------------------------------------------------------------------------
+ // SUB FUNCTIONS CALLED BY MAIN FUNCTION
+ // ---------------------------------------------------------------------------
+
+ processCommands: async function (wbxmlData, syncData) {
+ //any commands for us to work on? If we reach this point, Sync.Collections.Collection is valid,
+ //no need to use the save getWbxmlDataField function
+ if (wbxmlData.Sync.Collections.Collection.Commands) {
+
+ //looking for additions
+ let add = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Commands.Add);
+ for (let count = 0; count < add.length; count++) {
+ await TbSync.tools.sleep(10, true);
+
+ let ServerId = add[count].ServerId;
+ let data = add[count].ApplicationData;
+
+ let foundItem = await syncData.target.getItem(ServerId);
+ if (!foundItem) {
+ //do NOT add, if an item with that ServerId was found
+ let newItem = eas.sync.createItem(syncData);
+ try {
+ eas.sync[syncData.type].setThunderbirdItemFromWbxml(newItem, data, ServerId, syncData);
+ await syncData.target.addItem(newItem);
+ } catch (e) {
+ eas.xmltools.printXmlData(add[count], true); //include application data in log
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", newItem.toString());
+ throw e; // unable to add item to Thunderbird - fatal error
+ }
+ } else {
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Add request, but element exists already, skipped.", ServerId);
+ }
+ syncData.progressData.inc();
+ }
+
+ //looking for changes
+ let upd = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Commands.Change);
+ //inject custom change object for debug
+ //upd = JSON.parse('[{"ServerId":"2tjoanTeS0CJ3QTsq5vdNQAAAAABDdrY6Gp03ktAid0E7Kub3TUAAAoZy4A1","ApplicationData":{"DtStamp":"20171109T142149Z"}}]');
+ for (let count = 0; count < upd.length; count++) {
+ await TbSync.tools.sleep(10, true);
+
+ let ServerId = upd[count].ServerId;
+ let data = upd[count].ApplicationData;
+
+ syncData.progressData.inc();
+ let foundItem = await syncData.target.getItem(ServerId);
+ if (foundItem) { //only update, if an item with that ServerId was found
+
+ let keys = Object.keys(data);
+ //replace by smart merge
+ if (keys.length == 1 && keys[0] == "DtStamp") TbSync.dump("DtStampOnly", keys); //ignore DtStamp updates (fix with smart merge)
+ else {
+
+ if (foundItem.changelogStatus !== null) {
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Change request from server, but also local modifications, server wins!", ServerId);
+ foundItem.changelogStatus = null;
+ }
+
+ let newItem = foundItem.clone();
+ try {
+ eas.sync[syncData.type].setThunderbirdItemFromWbxml(newItem, data, ServerId, syncData);
+ await syncData.target.modifyItem(newItem, foundItem);
+ } catch (e) {
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", newItem.toString());
+ eas.xmltools.printXmlData(upd[count], true); //include application data in log
+ throw e; // unable to mod item to Thunderbird - fatal error
+ }
+ }
+
+ }
+ }
+
+ //looking for deletes
+ let del = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Commands.Delete).concat(eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Commands.SoftDelete));
+ for (let count = 0; count < del.length; count++) {
+ await TbSync.tools.sleep(10, true);
+
+ let ServerId = del[count].ServerId;
+
+ let foundItem = await syncData.target.getItem(ServerId);
+ if (foundItem) { //delete item with that ServerId
+ await syncData.target.deleteItem(foundItem);
+ }
+ syncData.progressData.inc();
+ }
+
+ }
+ },
+
+
+ updateFailedItems: function (syncData, cause, id, data) {
+ //something is wrong with this item, move it to the end of changelog and go on
+ if (!syncData.failedItems.includes(id)) {
+ //the extra parameter true will re-add the item to the end of the changelog
+ syncData.target.removeItemFromChangeLog(id, true);
+ syncData.failedItems.push(id);
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "BadItemSkipped::" + TbSync.getString("status." + cause, "eas"), "\n\nRequest:\n" + syncData.request + "\n\nResponse:\n" + syncData.response + "\n\nElement:\n" + data);
+ }
+ },
+
+
+ processResponses: async function (wbxmlData, syncData, addedItems, changedItems) {
+ //any responses for us to work on? If we reach this point, Sync.Collections.Collection is valid,
+ //no need to use the save getWbxmlDataField function
+ if (wbxmlData.Sync.Collections.Collection.Responses) {
+
+ //looking for additions (Add node contains, status, old ClientId and new ServerId)
+ let add = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Responses.Add);
+ for (let count = 0; count < add.length; count++) {
+ await TbSync.tools.sleep(10, true);
+
+ //get the true Thunderbird UID of this added item (we created a temp clientId during add)
+ add[count].ClientId = addedItems[add[count].ClientId];
+
+ //look for an item identfied by ClientId and update its id to the new id received from the server
+ let foundItem = await syncData.target.getItem(add[count].ClientId);
+ if (foundItem) {
+
+ //Check status, stop sync if bad, allow soft fail
+ let errorcause = eas.network.checkStatus(syncData, add[count], "Status", "Sync.Collections.Collection.Responses.Add[" + count + "].Status", true);
+ if (errorcause !== "") {
+ //something is wrong with this item, move it to the end of changelog and go on
+ eas.sync.updateFailedItems(syncData, errorcause, foundItem.primaryKey, foundItem.toString());
+ } else {
+ let newItem = foundItem.clone();
+ newItem.primaryKey = add[count].ServerId;
+ syncData.target.removeItemFromChangeLog(add[count].ClientId);
+ await syncData.target.modifyItem(newItem, foundItem);
+ syncData.progressData.inc();
+ }
+
+ }
+ }
+
+ //looking for modifications
+ let upd = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Responses.Change);
+ for (let count = 0; count < upd.length; count++) {
+ let foundItem = await syncData.target.getItem(upd[count].ServerId);
+ if (foundItem) {
+
+ //Check status, stop sync if bad, allow soft fail
+ let errorcause = eas.network.checkStatus(syncData, upd[count], "Status", "Sync.Collections.Collection.Responses.Change[" + count + "].Status", true);
+ if (errorcause !== "") {
+ //something is wrong with this item, move it to the end of changelog and go on
+ eas.sync.updateFailedItems(syncData, errorcause, foundItem.primaryKey, foundItem.toString());
+ //also remove from changedItems
+ let p = changedItems.indexOf(upd[count].ServerId);
+ if (p > -1) changedItems.splice(p, 1);
+ }
+
+ }
+ }
+
+ //looking for deletions
+ let del = eas.xmltools.nodeAsArray(wbxmlData.Sync.Collections.Collection.Responses.Delete);
+ for (let count = 0; count < del.length; count++) {
+ //What can we do about failed deletes? SyncLog
+ eas.network.checkStatus(syncData, del[count], "Status", "Sync.Collections.Collection.Responses.Delete[" + count + "].Status", true);
+ }
+
+ }
+ },
+
+
+
+
+
+
+
+
+
+
+ // ---------------------------------------------------------------------------
+ // HELPER FUNCTIONS AND DEFINITIONS
+ // ---------------------------------------------------------------------------
+
+ MAP_EAS2TB: {
+ //EAS Importance: 0 = LOW | 1 = NORMAL | 2 = HIGH
+ Importance: { "0": "9", "1": "5", "2": "1" }, //to PRIORITY
+ //EAS Sensitivity : 0 = Normal | 1 = Personal | 2 = Private | 3 = Confidential
+ Sensitivity: { "0": "PUBLIC", "1": "PRIVATE", "2": "PRIVATE", "3": "CONFIDENTIAL" }, //to CLASS
+ //EAS BusyStatus: 0 = Free | 1 = Tentative | 2 = Busy | 3 = Work | 4 = Elsewhere
+ BusyStatus: { "0": "TRANSPARENT", "1": "unset", "2": "OPAQUE", "3": "OPAQUE", "4": "OPAQUE" }, //to TRANSP
+ //EAS AttendeeStatus: 0 =Response unknown (but needed) | 2 = Tentative | 3 = Accept | 4 = Decline | 5 = Not responded (and not needed) || 1 = Organizer in ResponseType
+ ATTENDEESTATUS: { "0": "NEEDS-ACTION", "1": "Orga", "2": "TENTATIVE", "3": "ACCEPTED", "4": "DECLINED", "5": "ACCEPTED" },
+ },
+
+ MAP_TB2EAS: {
+ //TB PRIORITY: 9 = LOW | 5 = NORMAL | 1 = HIGH
+ PRIORITY: { "9": "0", "5": "1", "1": "2", "unset": "1" }, //to Importance
+ //TB CLASS: PUBLIC, PRIVATE, CONFIDENTIAL)
+ CLASS: { "PUBLIC": "0", "PRIVATE": "2", "CONFIDENTIAL": "3", "unset": "0" }, //to Sensitivity
+ //TB TRANSP : free = TRANSPARENT, busy = OPAQUE)
+ TRANSP: { "TRANSPARENT": "0", "unset": "1", "OPAQUE": "2" }, // to BusyStatus
+ //TB STATUS: NEEDS-ACTION, ACCEPTED, DECLINED, TENTATIVE, (DELEGATED, COMPLETED, IN-PROCESS - for todo)
+ ATTENDEESTATUS: { "NEEDS-ACTION": "0", "ACCEPTED": "3", "DECLINED": "4", "TENTATIVE": "2", "DELEGATED": "5", "COMPLETED": "5", "IN-PROCESS": "5" },
+ },
+
+ mapEasPropertyToThunderbird: function (easProp, tbProp, data, item) {
+ if (data[easProp]) {
+ //store original EAS value
+ let easPropValue = eas.xmltools.checkString(data[easProp]);
+ item.setProperty("X-EAS-" + easProp, easPropValue);
+ //map EAS value to TB value (use setCalItemProperty if there is one option which can unset/delete the property)
+ eas.tools.setCalItemProperty(item, tbProp, eas.sync.MAP_EAS2TB[easProp][easPropValue]);
+ }
+ },
+
+ mapThunderbirdPropertyToEas: function (tbProp, easProp, item) {
+ if (item.hasProperty("X-EAS-" + easProp) && eas.tools.getCalItemProperty(item, tbProp) == eas.sync.MAP_EAS2TB[easProp][item.getProperty("X-EAS-" + easProp)]) {
+ //we can use our stored EAS value, because it still maps to the current TB value
+ return item.getProperty("X-EAS-" + easProp);
+ } else {
+ return eas.sync.MAP_TB2EAS[tbProp][eas.tools.getCalItemProperty(item, tbProp)];
+ }
+ },
+
+ getEasItemType(aItem) {
+ if (aItem instanceof TbSync.addressbook.AbItem) {
+ return "Contacts";
+ } else if (aItem instanceof TbSync.lightning.TbItem) {
+ return aItem.isTodo ? "Tasks" : "Calendar";
+ } else {
+ throw "Unknown aItem.";
+ }
+ },
+
+ createItem(syncData) {
+ switch (syncData.type) {
+ case "Contacts":
+ return syncData.target.createNewCard();
+ break;
+
+ case "Tasks":
+ return syncData.target.createNewTodo();
+ break;
+
+ case "Calendar":
+ return syncData.target.createNewEvent();
+ break;
+
+ default:
+ throw "Unknown item type <" + syncData.type + ">";
+ }
+ },
+
+ async getWbxmlFromThunderbirdItem(item, syncData, isException = false) {
+ try {
+ let wbxml = await eas.sync[syncData.type].getWbxmlFromThunderbirdItem(item, syncData, isException);
+ return wbxml;
+ } catch (e) {
+ TbSync.eventlog.add("warning", syncData.eventLogInfo, "BadItemSkipped::JavaScriptError", item.toString());
+ throw e; // unable to read item from Thunderbird - fatal error
+ }
+ },
+
+
+
+
+
+
+
+ // ---------------------------------------------------------------------------
+ // LIGHTNING HELPER FUNCTIONS AND DEFINITIONS
+ // These functions are needed only by tasks and events, so they
+ // are placed here, even though they are not type independent,
+ // but I did not want to add another "lightning" sub layer.
+ //
+ // The item in these functions is a native lightning item.
+ // ---------------------------------------------------------------------------
+
+ setItemSubject: function (item, syncData, data) {
+ if (data.Subject) item.title = eas.xmltools.checkString(data.Subject);
+ },
+
+ setItemLocation: function (item, syncData, data) {
+ if (data.Location) item.setProperty("location", eas.xmltools.checkString(data.Location));
+ },
+
+
+ setItemCategories: function (item, syncData, data) {
+ if (data.Categories && data.Categories.Category) {
+ let cats = [];
+ if (Array.isArray(data.Categories.Category)) cats = data.Categories.Category;
+ else cats.push(data.Categories.Category);
+ item.setCategories(cats);
+ }
+ },
+
+ getItemCategories: function (item, syncData) {
+ let asversion = syncData.accountData.getAccountProperty("asversion");
+ let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks, Contacts etc)
+
+ //to properly "blank" categories, we need to always include the container
+ let categories = item.getCategories({});
+ if (categories.length > 0) {
+ wbxml.otag("Categories");
+ for (let i = 0; i < categories.length; i++) wbxml.atag("Category", categories[i]);
+ wbxml.ctag();
+ } else {
+ wbxml.atag("Categories");
+ }
+ return wbxml.getBytes();
+ },
+
+
+ setItemBody: function (item, syncData, data) {
+ let asversion = syncData.accountData.getAccountProperty("asversion");
+ if (asversion == "2.5") {
+ if (data.Body) item.setProperty("description", eas.xmltools.checkString(data.Body));
+ } else {
+ if (data.Body && /* data.Body.EstimatedDataSize > 0 && */ data.Body.Data) item.setProperty("description", eas.xmltools.checkString(data.Body.Data)); //EstimatedDataSize is optional
+ }
+ },
+
+ getItemBody: function (item, syncData) {
+ let asversion = syncData.accountData.getAccountProperty("asversion");
+ let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks, Contacts etc)
+
+ let description = (item.hasProperty("description")) ? item.getProperty("description") : "";
+ if (asversion == "2.5") {
+ wbxml.atag("Body", description);
+ } else {
+ wbxml.switchpage("AirSyncBase");
+ wbxml.otag("Body");
+ wbxml.atag("Type", "1");
+ wbxml.atag("EstimatedDataSize", "" + description.length);
+ wbxml.atag("Data", description);
+ wbxml.ctag();
+ //does not work with horde at the moment, does not work with task, does not work with exceptions
+ //if (syncData.accountData.getAccountProperty("horde") == "0") wbxml.atag("NativeBodyType", "1");
+
+ //return to code page of this type
+ wbxml.switchpage(syncData.type);
+ }
+ return wbxml.getBytes();
+ },
+
+ //item is a native lightning item
+ setItemRecurrence: function (item, syncData, data, timezone) {
+ if (data.Recurrence) {
+ item.recurrenceInfo = new CalRecurrenceInfo();
+ item.recurrenceInfo.item = item;
+ let recRule = TbSync.lightning.cal.createRecurrenceRule();
+ switch (data.Recurrence.Type) {
+ case "0":
+ recRule.type = "DAILY";
+ break;
+ case "1":
+ recRule.type = "WEEKLY";
+ break;
+ case "2":
+ case "3":
+ recRule.type = "MONTHLY";
+ break;
+ case "5":
+ case "6":
+ recRule.type = "YEARLY";
+ break;
+ }
+
+ if (data.Recurrence.CalendarType) {
+ // TODO
+ }
+ if (data.Recurrence.DayOfMonth) {
+ recRule.setComponent("BYMONTHDAY", [data.Recurrence.DayOfMonth]);
+ }
+ if (data.Recurrence.DayOfWeek) {
+ let DOW = data.Recurrence.DayOfWeek;
+ if (DOW == 127 && (recRule.type == "MONTHLY" || recRule.type == "YEARLY")) {
+ recRule.setComponent("BYMONTHDAY", [-1]);
+ }
+ else {
+ let days = [];
+ for (let i = 0; i < 7; ++i) {
+ if (DOW & 1 << i) days.push(i + 1);
+ }
+ if (data.Recurrence.WeekOfMonth) {
+ for (let i = 0; i < days.length; ++i) {
+ if (data.Recurrence.WeekOfMonth == 5) {
+ days[i] = -1 * (days[i] + 8);
+ }
+ else {
+ days[i] += 8 * (data.Recurrence.WeekOfMonth - 0);
+ }
+ }
+ }
+ recRule.setComponent("BYDAY", days);
+ }
+ }
+ if (data.Recurrence.FirstDayOfWeek) {
+ //recRule.setComponent("WKST", [data.Recurrence.FirstDayOfWeek]); // WKST is not a valid component
+ //recRule.weekStart = data.Recurrence.FirstDayOfWeek; // - (NS_ERROR_NOT_IMPLEMENTED) [calIRecurrenceRule.weekStart]
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "FirstDayOfWeek tag ignored (not supported).", item.icalString);
+ }
+
+ if (data.Recurrence.Interval) {
+ recRule.interval = data.Recurrence.Interval;
+ }
+ if (data.Recurrence.IsLeapMonth) {
+ // TODO
+ }
+ if (data.Recurrence.MonthOfYear) {
+ recRule.setComponent("BYMONTH", [data.Recurrence.MonthOfYear]);
+ }
+ if (data.Recurrence.Occurrences) {
+ recRule.count = data.Recurrence.Occurrences;
+ }
+ if (data.Recurrence.Until) {
+ //time string could be in compact/basic or extended form of ISO 8601,
+ //cal.createDateTime only supports compact/basic, our own method takes both styles
+ recRule.untilDate = eas.tools.createDateTime(data.Recurrence.Until);
+ }
+ if (data.Recurrence.Start) {
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Start tag in recurring task is ignored, recurrence will start with first entry.", item.icalString);
+ }
+
+ item.recurrenceInfo.insertRecurrenceItemAt(recRule, 0);
+
+ if (data.Exceptions && syncData.type == "Calendar") { // only events, tasks cannot have exceptions
+ // Exception could be an object or an array of objects
+ let exceptions = [].concat(data.Exceptions.Exception);
+ for (let exception of exceptions) {
+ //exception.ExceptionStartTime is in UTC, but the Recurrence Object is in local timezone
+ let dateTime = TbSync.lightning.cal.createDateTime(exception.ExceptionStartTime).getInTimezone(timezone);
+ if (data.AllDayEvent == "1") {
+ dateTime.isDate = true;
+ // Pass to replacement event unless overriden
+ if (!exception.AllDayEvent) {
+ exception.AllDayEvent = "1";
+ }
+ }
+ if (exception.Deleted == "1") {
+ item.recurrenceInfo.removeOccurrenceAt(dateTime);
+ }
+ else {
+ let replacement = item.recurrenceInfo.getOccurrenceFor(dateTime);
+ // replacement is a native lightning item, so we can access its id via .id
+ eas.sync[syncData.type].setThunderbirdItemFromWbxml(replacement, exception, replacement.id, syncData, "recurrence");
+ // Reminders should carry over from parent, but setThunderbirdItemFromWbxml clears all alarms
+ if (!exception.Reminder && item.getAlarms({}).length) {
+ replacement.addAlarm(item.getAlarms({})[0]);
+ }
+ // Removing a reminder requires EAS 16.0
+ item.recurrenceInfo.modifyException(replacement, true);
+ }
+ }
+ }
+ }
+ },
+
+ getItemRecurrence: async function (item, syncData, localStartDate = null) {
+ let asversion = syncData.accountData.getAccountProperty("asversion");
+ let wbxml = eas.wbxmltools.createWBXML("", syncData.type); //init wbxml with "" and not with precodes, also activate type codePage (Calendar, Tasks etc)
+
+ if (item.recurrenceInfo && (syncData.type == "Calendar" || syncData.type == "Tasks")) {
+ let deleted = [];
+ let hasRecurrence = false;
+ let startDate = (syncData.type == "Calendar") ? item.startDate : item.entryDate;
+
+ for (let recRule of item.recurrenceInfo.getRecurrenceItems({})) {
+ if (recRule.date) {
+ if (recRule.isNegative) {
+ // EXDATE
+ deleted.push(recRule);
+ }
+ else {
+ // RDATE
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Ignoring RDATE rule (not supported)", recRule.icalString);
+ }
+ continue;
+ }
+ if (recRule.isNegative) {
+ // EXRULE
+ TbSync.eventlog.add("info", syncData.eventLogInfo, "Ignoring EXRULE rule (not supported)", recRule.icalString);
+ continue;
+ }
+
+ // RRULE
+ wbxml.otag("Recurrence");
+ hasRecurrence = true;
+
+ let type = 0;
+ let monthDays = recRule.getComponent("BYMONTHDAY", {});
+ let weekDays = recRule.getComponent("BYDAY", {});
+ let months = recRule.getComponent("BYMONTH", {});
+ let weeks = [];
+
+ // Unpack 1MO style days
+ for (let i = 0; i < weekDays.length; ++i) {
+ if (weekDays[i] > 8) {
+ weeks[i] = Math.floor(weekDays[i] / 8);
+ weekDays[i] = weekDays[i] % 8;
+ }
+ else if (weekDays[i] < -8) {
+ // EAS only supports last week as a special value, treat
+ // all as last week or assume every month has 5 weeks?
+ // Change to last week
+ //weeks[i] = 5;
+ // Assumes 5 weeks per month for week <= -2
+ weeks[i] = 6 - Math.floor(-weekDays[i] / 8);
+ weekDays[i] = -weekDays[i] % 8;
+ }
+ }
+ if (monthDays[0] && monthDays[0] == -1) {
+ weeks = [5];
+ weekDays = [1, 2, 3, 4, 5, 6, 7]; // 127
+ monthDays[0] = null;
+ }
+ // Type
+ if (recRule.type == "WEEKLY") {
+ type = 1;
+ if (!weekDays.length) {
+ weekDays = [startDate.weekday + 1];
+ }
+ }
+ else if (recRule.type == "MONTHLY" && weeks.length) {
+ type = 3;
+ }
+ else if (recRule.type == "MONTHLY") {
+ type = 2;
+ if (!monthDays.length) {
+ monthDays = [startDate.day];
+ }
+ }
+ else if (recRule.type == "YEARLY" && weeks.length) {
+ type = 6;
+ }
+ else if (recRule.type == "YEARLY") {
+ type = 5;
+ if (!monthDays.length) {
+ monthDays = [startDate.day];
+ }
+ if (!months.length) {
+ months = [startDate.month + 1];
+ }
+ }
+ wbxml.atag("Type", type.toString());
+
+ //Tasks need a Start tag, but we cannot allow a start date different from the start of the main item (thunderbird does not support that)
+ if (localStartDate) wbxml.atag("Start", localStartDate);
+
+ // TODO: CalendarType: 14.0 and up
+ // DayOfMonth
+ if (monthDays[0]) {
+ // TODO: Multiple days of month - multiple Recurrence tags?
+ wbxml.atag("DayOfMonth", monthDays[0].toString());
+ }
+ // DayOfWeek
+ if (weekDays.length) {
+ let bitfield = 0;
+ for (let day of weekDays) {
+ bitfield |= 1 << (day - 1);
+ }
+ wbxml.atag("DayOfWeek", bitfield.toString());
+ }
+ // FirstDayOfWeek: 14.1 and up
+ //wbxml.atag("FirstDayOfWeek", recRule.weekStart); - (NS_ERROR_NOT_IMPLEMENTED) [calIRecurrenceRule.weekStart]
+ // Interval
+ wbxml.atag("Interval", recRule.interval.toString());
+ // TODO: IsLeapMonth: 14.0 and up
+ // MonthOfYear
+ if (months.length) {
+ wbxml.atag("MonthOfYear", months[0].toString());
+ }
+ // Occurrences
+ if (recRule.isByCount) {
+ wbxml.atag("Occurrences", recRule.count.toString());
+ }
+ // Until
+ else if (recRule.untilDate != null) {
+ //Events need the Until data in compact form, Tasks in the basic form
+ wbxml.atag("Until", eas.tools.getIsoUtcString(recRule.untilDate, (syncData.type == "Tasks")));
+ }
+ // WeekOfMonth
+ if (weeks.length) {
+ wbxml.atag("WeekOfMonth", weeks[0].toString());
+ }
+ wbxml.ctag();
+ }
+
+ if (syncData.type == "Calendar" && hasRecurrence) { //Exceptions only allowed in Calendar and only if a valid Recurrence was added
+ let modifiedIds = item.recurrenceInfo.getExceptionIds({});
+ if (deleted.length || modifiedIds.length) {
+ wbxml.otag("Exceptions");
+ for (let exception of deleted) {
+ wbxml.otag("Exception");
+ wbxml.atag("ExceptionStartTime", eas.tools.getIsoUtcString(exception.date));
+ wbxml.atag("Deleted", "1");
+ //Docs say it is allowed, but if present, it does not work
+ //if (asversion == "2.5") {
+ // wbxml.atag("UID", item.id); //item.id is not valid, use UID or primaryKey
+ //}
+ wbxml.ctag();
+ }
+ for (let exceptionId of modifiedIds) {
+ let replacement = item.recurrenceInfo.getExceptionFor(exceptionId);
+ wbxml.otag("Exception");
+ wbxml.atag("ExceptionStartTime", eas.tools.getIsoUtcString(exceptionId));
+ wbxml.append(await eas.sync.getWbxmlFromThunderbirdItem(replacement, syncData, true));
+ wbxml.ctag();
+ }
+ wbxml.ctag();
+ }
+ }
+ }
+
+ return wbxml.getBytes();
+ }
+
+}
diff -Nru eas4tbsync-4.11/content/includes/tasksync.js eas4tbsync-4.17/content/includes/tasksync.js
--- eas4tbsync-4.11/content/includes/tasksync.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/tasksync.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,212 +1,217 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-
-XPCOMUtils.defineLazyModuleGetters(this, {
- CalAlarm: "resource:///modules/CalAlarm.jsm",
- CalAttachment: "resource:///modules/CalAttachment.jsm",
- CalAttendee: "resource:///modules/CalAttendee.jsm",
- CalEvent: "resource:///modules/CalEvent.jsm",
- CalTodo: "resource:///modules/CalTodo.jsm",
-});
-
-var Tasks = {
-
- // --------------------------------------------------------------------------- //
- // Read WBXML and set Thunderbird item
- // --------------------------------------------------------------------------- //
- setThunderbirdItemFromWbxml: function (tbItem, data, id, syncdata, mode = "standard") {
-
- let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
-
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- item.id = id;
- eas.sync.setItemSubject(item, syncdata, data);
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " task item", item.title + " (" + id + ")");
-
- eas.sync.setItemBody(item, syncdata, data);
- eas.sync.setItemCategories(item, syncdata, data);
- eas.sync.setItemRecurrence(item, syncdata, data);
-
- let dueDate = null;
- if (data.DueDate && data.UtcDueDate) {
- //extract offset from EAS data
- let DueDate = new Date(data.DueDate);
- let UtcDueDate = new Date(data.UtcDueDate);
- let offset = (UtcDueDate.getTime() - DueDate.getTime())/60000;
-
- //timezone is identified by its offset
- let utc = cal.createDateTime(eas.tools.dateToBasicISOString(UtcDueDate)); //format "19800101T000000Z" - UTC
- dueDate = utc.getInTimezone(eas.tools.guessTimezoneByCurrentOffset(offset, utc));
- item.dueDate = dueDate;
- }
-
- if (data.StartDate && data.UtcStartDate) {
- //extract offset from EAS data
- let StartDate = new Date(data.StartDate);
- let UtcStartDate = new Date(data.UtcStartDate);
- let offset = (UtcStartDate.getTime() - StartDate.getTime())/60000;
-
- //timezone is identified by its offset
- let utc = cal.createDateTime(eas.tools.dateToBasicISOString(UtcStartDate)); //format "19800101T000000Z" - UTC
- item.entryDate = utc.getInTimezone(eas.tools.guessTimezoneByCurrentOffset(offset, utc));
- } else {
- //there is no start date? if this is a recurring item, we MUST add an entryDate, otherwise Thunderbird will not display the recurring items
- if (data.Recurrence) {
- if (dueDate) {
- item.entryDate = dueDate;
- TbSync.eventlog.add("info", syncdata, "Copy task dueData to task startDate, because Thunderbird needs a startDate for recurring items.", item.icalString);
- } else {
- TbSync.eventlog.add("info", syncdata, "Task without startDate and without dueDate but with recurrence info is not supported by Thunderbird. Recurrence will be lost.", item.icalString);
- }
- }
- }
-
- eas.sync.mapEasPropertyToThunderbird ("Sensitivity", "CLASS", data, item);
- eas.sync.mapEasPropertyToThunderbird ("Importance", "PRIORITY", data, item);
-
- let msTodoCompat = eas.prefs.getBoolPref("msTodoCompat");
-
- item.clearAlarms();
- if (data.ReminderSet && data.ReminderTime) {
- let UtcAlarmDate = eas.tools.createDateTime(data.ReminderTime);
- let alarm = new CalAlarm();
- alarm.action = "DISPLAY";
-
- if (msTodoCompat)
- {
- // Microsoft To-Do only uses due dates (no start dates) an doesn't have a time part in the due date
- // dirty hack: Use the reminder date as due date and set a reminder exactly to the due date
- // drawback: only works if due date and reminder is set to the same day - this could maybe checked here but I don't know how
- item.entryDate = UtcAlarmDate;
- item.dueDate = UtcAlarmDate;
- alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
- alarm.offset = TbSync.lightning.cal.createDuration();
- alarm.offset.inSeconds = 0;
- }
- else if (data.UtcStartDate)
- {
- let UtcDate = eas.tools.createDateTime(data.UtcStartDate);
- alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
- alarm.offset = UtcAlarmDate.subtractDate(UtcDate);
- }
- else
- {
- // Alternative solution for Microsoft To-Do:
- // alarm correctly set but because time part of due date is always "0:00", all tasks for today are shown as overdue
- alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_ABSOLUTE;
- alarm.alarmDate = UtcAlarmDate;
- }
- item.addAlarm(alarm);
- }
-
- //status/percentage cannot be mapped
- if (data.Complete) {
- if (data.Complete == "0") {
- item.isCompleted = false;
- } else {
- item.isCompleted = true;
- if (data.DateCompleted) item.completedDate = eas.tools.createDateTime(data.DateCompleted);
- }
- }
- },
-
-/*
- Regenerate: After complete, the completed task is removed from the series and stored as an new entry. The series starts an week (as set) after complete date with one less occurence
-
- */
-
-
-
-
-
-
-
- // --------------------------------------------------------------------------- //
- //read TB event and return its data as WBXML
- // --------------------------------------------------------------------------- //
- getWbxmlFromThunderbirdItem: async function (tbItem, syncdata) {
- let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
-
- let asversion = syncdata.accountData.getAccountProperty("asversion");
- let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
-
- //Order of tags taken from: https://msdn.microsoft.com/en-us/library/dn338924(v=exchg.80).aspx
-
- //Subject
- wbxml.atag("Subject", (item.title) ? item.title : "");
-
- //Body
- wbxml.append(eas.sync.getItemBody(item, syncdata));
-
- //Importance
- wbxml.atag("Importance", eas.sync.mapThunderbirdPropertyToEas("PRIORITY", "Importance", item));
-
- //tasks is using extended ISO 8601 (2019-01-18T00:00:00.000Z) instead of basic (20190118T000000Z),
- //eas.tools.getIsoUtcString returns extended if true as second parameter is present
-
- // TB will enforce a StartDate if it has a recurrence
- let localStartDate = null;
- if (item.entryDate) {
- wbxml.atag("UtcStartDate", eas.tools.getIsoUtcString(item.entryDate, true));
- //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
- localStartDate = eas.tools.getIsoUtcString(item.entryDate, true, true);
- wbxml.atag("StartDate", localStartDate);
- }
-
- // Tasks without DueDate are breaking O365 - use StartDate as DueDate
- if (item.entryDate || item.dueDate) {
- wbxml.atag("UtcDueDate", eas.tools.getIsoUtcString(item.dueDate ? item.dueDate : item.entryDate, true));
- //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
- wbxml.atag("DueDate", eas.tools.getIsoUtcString(item.dueDate ? item.dueDate : item.entryDate, true, true));
- }
-
- //Categories
- wbxml.append(eas.sync.getItemCategories(item, syncdata));
-
- //Recurrence (only if localStartDate has been set)
- if (localStartDate) wbxml.append(await eas.sync.getItemRecurrence(item, syncdata, localStartDate));
-
- //Complete
- if (item.isCompleted) {
- wbxml.atag("Complete", "1");
- wbxml.atag("DateCompleted", eas.tools.getIsoUtcString(item.completedDate, true));
- } else {
- wbxml.atag("Complete", "0");
- }
-
- //Sensitivity
- wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
-
- //ReminderTime and ReminderSet
- let alarms = item.getAlarms({});
- if (alarms.length>0 && (item.entryDate || item.dueDate)) {
- let reminderTime;
- if (alarms[0].offset) {
- //create Date obj from entryDate by converting item.entryDate to an extended UTC ISO string, which can be parsed by Date
- //if entryDate is missing, the startDate of this object is set to its dueDate
- let UtcDate = new Date(eas.tools.getIsoUtcString(item.entryDate ? item.entryDate : item.dueDate, true));
- //add offset
- UtcDate.setSeconds(UtcDate.getSeconds() + alarms[0].offset.inSeconds);
- reminderTime = UtcDate.toISOString();
- } else {
- reminderTime = eas.tools.getIsoUtcString(alarms[0].alarmDate, true);
- }
- wbxml.atag("ReminderTime", reminderTime);
- wbxml.atag("ReminderSet", "1");
- } else {
- wbxml.atag("ReminderSet", "0");
- }
-
- return wbxml.getBytes();
- },
-}
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ CalAlarm: "resource:///modules/CalAlarm.sys.mjs",
+ CalAttachment: "resource:///modules/CalAttachment.sys.mjs",
+ CalAttendee: "resource:///modules/CalAttendee.sys.mjs",
+ CalEvent: "resource:///modules/CalEvent.sys.mjs",
+ CalTodo: "resource:///modules/CalTodo.sys.mjs",
+});
+
+var Tasks = {
+
+ // --------------------------------------------------------------------------- //
+ // Read WBXML and set Thunderbird item
+ // --------------------------------------------------------------------------- //
+ setThunderbirdItemFromWbxml: function (tbItem, data, id, syncdata, mode = "standard") {
+
+ let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
+
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ item.id = id;
+ eas.sync.setItemSubject(item, syncdata, data);
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 2) TbSync.dump("Processing " + mode + " task item", item.title + " (" + id + ")");
+
+ eas.sync.setItemBody(item, syncdata, data);
+ eas.sync.setItemCategories(item, syncdata, data);
+ eas.sync.setItemRecurrence(item, syncdata, data);
+
+ let dueDate = null;
+ if (data.DueDate && data.UtcDueDate) {
+ //extract offset from EAS data
+ let DueDate = new Date(data.DueDate);
+ let UtcDueDate = new Date(data.UtcDueDate);
+ let offset = (UtcDueDate.getTime() - DueDate.getTime()) / 60000;
+
+ //timezone is identified by its offset
+ let utc = cal.createDateTime(eas.tools.dateToBasicISOString(UtcDueDate)); //format "19800101T000000Z" - UTC
+ dueDate = utc.getInTimezone(eas.tools.guessTimezoneByCurrentOffset(offset, utc));
+ item.dueDate = dueDate;
+ }
+
+ if (data.StartDate && data.UtcStartDate) {
+ //extract offset from EAS data
+ let StartDate = new Date(data.StartDate);
+ let UtcStartDate = new Date(data.UtcStartDate);
+ let offset = (UtcStartDate.getTime() - StartDate.getTime()) / 60000;
+
+ //timezone is identified by its offset
+ let utc = cal.createDateTime(eas.tools.dateToBasicISOString(UtcStartDate)); //format "19800101T000000Z" - UTC
+ item.entryDate = utc.getInTimezone(eas.tools.guessTimezoneByCurrentOffset(offset, utc));
+ } else {
+ //there is no start date? if this is a recurring item, we MUST add an entryDate, otherwise Thunderbird will not display the recurring items
+ if (data.Recurrence) {
+ if (dueDate) {
+ item.entryDate = dueDate;
+ TbSync.eventlog.add("info", syncdata, "Copy task dueData to task startDate, because Thunderbird needs a startDate for recurring items.", item.icalString);
+ } else {
+ TbSync.eventlog.add("info", syncdata, "Task without startDate and without dueDate but with recurrence info is not supported by Thunderbird. Recurrence will be lost.", item.icalString);
+ }
+ }
+ }
+
+ eas.sync.mapEasPropertyToThunderbird("Sensitivity", "CLASS", data, item);
+ eas.sync.mapEasPropertyToThunderbird("Importance", "PRIORITY", data, item);
+
+ let msTodoCompat = eas.prefs.getBoolPref("msTodoCompat");
+
+ item.clearAlarms();
+ if (data.ReminderSet && data.ReminderTime) {
+ let UtcAlarmDate = eas.tools.createDateTime(data.ReminderTime);
+ let alarm = new CalAlarm();
+ alarm.action = "DISPLAY";
+
+ if (msTodoCompat) {
+ // Microsoft To-Do only uses due dates (no start dates) an doesn't have a time part in the due date
+ // dirty hack: Use the reminder date as due date and set a reminder exactly to the due date
+ // drawback: only works if due date and reminder is set to the same day - this could maybe checked here but I don't know how
+ item.entryDate = UtcAlarmDate;
+ item.dueDate = UtcAlarmDate;
+ alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
+ alarm.offset = TbSync.lightning.cal.createDuration();
+ alarm.offset.inSeconds = 0;
+ }
+ else if (data.UtcStartDate) {
+ let UtcDate = eas.tools.createDateTime(data.UtcStartDate);
+ alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
+ alarm.offset = UtcAlarmDate.subtractDate(UtcDate);
+ }
+ else {
+ // Alternative solution for Microsoft To-Do:
+ // alarm correctly set but because time part of due date is always "0:00", all tasks for today are shown as overdue
+ alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_ABSOLUTE;
+ alarm.alarmDate = UtcAlarmDate;
+ }
+ item.addAlarm(alarm);
+ }
+
+ //status/percentage cannot be mapped
+ if (data.Complete) {
+ if (data.Complete == "0") {
+ item.isCompleted = false;
+ } else {
+ item.isCompleted = true;
+ if (data.DateCompleted) item.completedDate = eas.tools.createDateTime(data.DateCompleted);
+ }
+ }
+ },
+
+ /*
+ Regenerate: After complete, the completed task is removed from the series and stored as an new entry. The series starts an week (as set) after complete date with one less occurence
+
+ */
+
+
+
+
+
+
+
+ // --------------------------------------------------------------------------- //
+ //read TB event and return its data as WBXML
+ // --------------------------------------------------------------------------- //
+ getWbxmlFromThunderbirdItem: async function (tbItem, syncdata) {
+ let item = tbItem instanceof TbSync.lightning.TbItem ? tbItem.nativeItem : tbItem;
+
+ let asversion = syncdata.accountData.getAccountProperty("asversion");
+ let wbxml = eas.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
+
+ //Order of tags taken from: https://msdn.microsoft.com/en-us/library/dn338924(v=exchg.80).aspx
+
+ //Subject
+ wbxml.atag("Subject", (item.title) ? item.title : "");
+
+ //Body
+ wbxml.append(eas.sync.getItemBody(item, syncdata));
+
+ //Importance
+ wbxml.atag("Importance", eas.sync.mapThunderbirdPropertyToEas("PRIORITY", "Importance", item));
+
+ //tasks is using extended ISO 8601 (2019-01-18T00:00:00.000Z) instead of basic (20190118T000000Z),
+ //eas.tools.getIsoUtcString returns extended if true as second parameter is present
+
+ // TB will enforce a StartDate if it has a recurrence
+ let localStartDate = null;
+ if (item.entryDate) {
+ wbxml.atag("UtcStartDate", eas.tools.getIsoUtcString(item.entryDate, true));
+ //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
+ localStartDate = eas.tools.getIsoUtcString(item.entryDate, true, true);
+ wbxml.atag("StartDate", localStartDate);
+ }
+
+ // Tasks without DueDate are breaking O365 - use StartDate as DueDate
+ if (item.entryDate || item.dueDate) {
+ wbxml.atag("UtcDueDate", eas.tools.getIsoUtcString(item.dueDate ? item.dueDate : item.entryDate, true));
+ //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
+ wbxml.atag("DueDate", eas.tools.getIsoUtcString(item.dueDate ? item.dueDate : item.entryDate, true, true));
+ }
+
+ //Categories
+ wbxml.append(eas.sync.getItemCategories(item, syncdata));
+
+ //Recurrence (only if localStartDate has been set)
+ if (localStartDate) wbxml.append(await eas.sync.getItemRecurrence(item, syncdata, localStartDate));
+
+ //Complete
+ if (item.isCompleted) {
+ wbxml.atag("Complete", "1");
+ wbxml.atag("DateCompleted", eas.tools.getIsoUtcString(item.completedDate, true));
+ } else {
+ wbxml.atag("Complete", "0");
+ }
+
+ //Sensitivity
+ wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
+
+ //ReminderTime and ReminderSet
+ let alarms = item.getAlarms({});
+ if (alarms.length > 0 && (item.entryDate || item.dueDate)) {
+ let reminderTime;
+ if (alarms[0].offset) {
+ //create Date obj from entryDate by converting item.entryDate to an extended UTC ISO string, which can be parsed by Date
+ //if entryDate is missing, the startDate of this object is set to its dueDate
+ let UtcDate = new Date(eas.tools.getIsoUtcString(item.entryDate ? item.entryDate : item.dueDate, true));
+ //add offset
+ UtcDate.setSeconds(UtcDate.getSeconds() + alarms[0].offset.inSeconds);
+ reminderTime = UtcDate.toISOString();
+ } else {
+ reminderTime = eas.tools.getIsoUtcString(alarms[0].alarmDate, true);
+ }
+ wbxml.atag("ReminderTime", reminderTime);
+ wbxml.atag("ReminderSet", "1");
+ } else {
+ wbxml.atag("ReminderSet", "0");
+ }
+
+ return wbxml.getBytes();
+ },
+}
diff -Nru eas4tbsync-4.11/content/includes/tools.js eas4tbsync-4.17/content/includes/tools.js
--- eas4tbsync-4.11/content/includes/tools.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/tools.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,535 +1,548 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-var { MailServices } = ChromeUtils.import("resource:///modules/MailServices.jsm");
-var { NetUtil } = ChromeUtils.importESModule(
- "resource://gre/modules/NetUtil.sys.mjs"
-);
-
-var tools = {
-
- setCalItemProperty: function (item, prop, value) {
- if (value == "unset") item.deleteProperty(prop);
- else item.setProperty(prop, value);
- },
-
- getCalItemProperty: function (item, prop) {
- if (item.hasProperty(prop)) return item.getProperty(prop);
- else return "unset";
- },
-
- isString: function (s) {
- return (typeof s == 'string' || s instanceof String);
- },
-
- getIdentityKey: function (email) {
- for (let account of MailServices.accounts.accounts) {
- if (account.defaultIdentity && account.defaultIdentity.email == email) return account.defaultIdentity.key;
- }
- return "";
- },
-
- parentIsTrash: function (folderData) {
- let parentID = folderData.getFolderProperty("parentID");
- if (parentID == "0") return false;
-
- let parentFolder = folderData.accountData.getFolder("serverID", parentID);
- if (parentFolder && parentFolder.getFolderProperty("type") == "4") return true;
-
- return false;
- },
-
- getNewDeviceId: function () {
- //taken from https://jsfiddle.net/briguy37/2MVFd/
- let d = new Date().getTime();
- let uuid = 'xxxxxxxxxxxxxxxxyxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- let r = (d + Math.random()*16)%16 | 0;
- d = Math.floor(d/16);
- return (c=='x' ? r : (r&0x3|0x8)).toString(16);
- });
- return "MZTB" + uuid;
- },
-
- getUriFromDirectoryId: function(ownerId) {
- let directories = MailServices.ab.directories;
- for (let directory of directories) {
- if (directory instanceof Components.interfaces.nsIAbDirectory) {
- if (ownerId.startsWith(directory.dirPrefId)) return directory.URI;
- }
- }
- return null;
- },
-
- //function to get correct uri of current card for global book as well for mailLists
- getSelectedUri : function(aUri, aCard) {
- if (aUri == "moz-abdirectory://?") {
- //get parent via card owner
- return eas.tools.getUriFromDirectoryId(aCard.directoryId);
- } else if (MailServices.ab.getDirectory(aUri).isMailList) {
- //MailList suck, we have to cut the url to get the parent
- return aUri.substring(0, aUri.lastIndexOf("/"))
- } else {
- return aUri;
- }
- },
-
- //read file from within the XPI package
- fetchFile: function (aURL, returnType = "Array") {
- return new Promise((resolve, reject) => {
- let uri = Services.io.newURI(aURL);
- let channel = Services.io.newChannelFromURI(uri,
- null,
- Services.scriptSecurityManager.getSystemPrincipal(),
- null,
- Components.interfaces.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
- Components.interfaces.nsIContentPolicy.TYPE_OTHER);
-
- NetUtil.asyncFetch(channel, (inputStream, status) => {
- if (!Components.isSuccessCode(status)) {
- reject(status);
- return;
- }
-
- try {
- let data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
- if (returnType == "Array") {
- resolve(data.replace("\r","").split("\n"))
- } else {
- resolve(data);
- }
- } catch (ex) {
- reject(ex);
- }
- });
- });
- },
-
-
-
-
-
-
-
-
-
-
- // TIMEZONE STUFF
-
- TimeZoneDataStructure : class {
- constructor() {
- this.buf = new DataView(new ArrayBuffer(172));
- }
-
-/*
- Buffer structure:
- @000 utcOffset (4x8bit as 1xLONG)
-
- @004 standardName (64x8bit as 32xWCHAR)
- @068 standardDate (16x8 as 1xSYSTEMTIME)
- @084 standardBias (4x8bit as 1xLONG)
-
- @088 daylightName (64x8bit as 32xWCHAR)
- @152 daylightDate (16x8 as 1xSTRUCT)
- @168 daylightBias (4x8bit as 1xLONG)
-*/
-
- set easTimeZone64 (b64) {
- //clear buffer
- for (let i=0; i<172; i++) this.buf.setUint8(i, 0);
- //load content into buffer
- let content = (b64 == "") ? "" : atob(b64);
- for (let i=0; i if found, does the stdOffset match? -> if so, done
- 2. Try to parse our own format, split name and test each chunk for IANA -> if found, does the stdOffset match? -> if so, done
- 3. Try if one of the chunks matches international code -> if found, does the stdOffset match? -> if so, done
- 4. Fallback: Use just the offsets */
-
-
- //check for windows timezone name
- if (eas.windowsToIanaTimezoneMap[stdName] && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]] && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].std.offset == stdOffset ) {
- //the windows timezone maps multiple IANA zones to one (Berlin*, Rome, Bruessel)
- //check the windowsZoneName of the default TZ and of the winning, if they match, use default TZ
- //so Rome could win, even Berlin is the default IANA zone
- if (eas.defaultTimezoneInfo.std.windowsZoneName && eas.windowsToIanaTimezoneMap[stdName] != eas.defaultTimezoneInfo.std.id && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].std.offset == eas.defaultTimezoneInfo.std.offset && stdName == eas.defaultTimezoneInfo.std.windowsZoneName) {
- TbSync.dump("Timezone matched via windows timezone name ("+stdName+") with default TZ overtake", eas.windowsToIanaTimezoneMap[stdName] + " -> " + eas.defaultTimezoneInfo.std.id);
- return eas.defaultTimezoneInfo.timezone;
- }
-
- TbSync.dump("Timezone matched via windows timezone name ("+stdName+")", eas.windowsToIanaTimezoneMap[stdName]);
- return eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].timezone;
- }
-
- let parts = stdName.replace(/[;,()\[\]]/g," ").split(" ");
- for (let i = 0; i < parts.length; i++) {
- //check for IANA
- if (eas.cachedTimezoneData.iana[parts[i]] && eas.cachedTimezoneData.iana[parts[i]].std.offset == stdOffset) {
- TbSync.dump("Timezone matched via IANA", parts[i]);
- return eas.cachedTimezoneData.iana[parts[i]].timezone;
- }
-
- //check for international abbreviation for standard period (CET, CAT, ...)
- if (eas.cachedTimezoneData.abbreviations[parts[i]] && eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]] && eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]].std.offset == stdOffset) {
- TbSync.dump("Timezone matched via international abbreviation (" + parts[i] +")", eas.cachedTimezoneData.abbreviations[parts[i]]);
- return eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]].timezone;
- }
- }
-
- //fallback to zone based on stdOffset and dstOffset, if we have that cached
- if (eas.cachedTimezoneData.bothOffsets[stdOffset+":"+dstOffset]) {
- TbSync.dump("Timezone matched via both offsets (std:" + stdOffset +", dst:" + dstOffset + ")", eas.cachedTimezoneData.bothOffsets[stdOffset+":"+dstOffset].tzid);
- return eas.cachedTimezoneData.bothOffsets[stdOffset+":"+dstOffset];
- }
-
- //fallback to zone based on stdOffset only, if we have that cached
- if (eas.cachedTimezoneData.stdOffset[stdOffset]) {
- TbSync.dump("Timezone matched via std offset (" + stdOffset +")", eas.cachedTimezoneData.stdOffset[stdOffset].tzid);
- return eas.cachedTimezoneData.stdOffset[stdOffset];
- }
-
- //return default timezone, if everything else fails
- TbSync.dump("Timezone could not be matched via offsets (std:" + stdOffset +", dst:" + dstOffset + "), using default timezone", eas.defaultTimezoneInfo.std.id);
- return eas.defaultTimezoneInfo.timezone;
- },
-
-
- //extract standard and daylight timezone data
- getTimezoneInfo: function (timezone) {
- let tzInfo = {};
-
- tzInfo.std = eas.tools.getTimezoneInfoObject(timezone, "standard");
- tzInfo.dst = eas.tools.getTimezoneInfoObject(timezone, "daylight");
-
- if (tzInfo.dst === null) tzInfo.dst = tzInfo.std;
-
- tzInfo.timezone = timezone;
- return tzInfo;
- },
-
-
- //get timezone info for standard/daylight
- getTimezoneInfoObject: function (timezone, standardOrDaylight) {
-
- //handle UTC
- if (timezone.isUTC) {
- let obj = {}
- obj.id = "UTC";
- obj.offset = 0;
- obj.abbreviation = "UTC";
- obj.displayname = "Coordinated Universal Time (UTC)";
- return obj;
- }
-
- //we could parse the icalstring by ourself, but I wanted to use ICAL.parse - TODO try catch
- let info = TbSync.lightning.ICAL.parse("BEGIN:VCALENDAR\r\n" + timezone.icalComponent.toString() + "\r\nEND:VCALENDAR");
- let comp = new TbSync.lightning.ICAL.Component(info);
- let vtimezone =comp.getFirstSubcomponent("vtimezone");
- let id = vtimezone.getFirstPropertyValue("tzid").toString();
- let zone = vtimezone.getFirstSubcomponent(standardOrDaylight);
-
- if (zone) {
- let obj = {};
- obj.id = id;
-
- //get offset
- let utcOffset = zone.getFirstPropertyValue("tzoffsetto").toString();
- let o = parseInt(utcOffset.replace(":","")); //-330 = - 3h 30min
- let h = Math.floor(o / 100); //-3 -> -180min
- let m = o - (h*100) //-330 - -300 = -30
- obj.offset = -1*((h*60) + m);
-
- //get international abbreviation (CEST, CET, CAT ... )
- obj.abbreviation = "";
- try {
- obj.abbreviation = zone.getFirstPropertyValue("tzname").toString();
- } catch(e) {
- TbSync.dump("Failed TZ", timezone.icalComponent.toString());
- }
-
- //get displayname
- obj.displayname = /*"("+utcOffset+") " +*/ obj.id;// + ", " + obj.abbreviation;
-
- //get DST switch date
- let rrule = zone.getFirstPropertyValue("rrule");
- let dtstart = zone.getFirstPropertyValue("dtstart");
- if (rrule && dtstart) {
- /*
-
- THE switchdate PART OF THE OBJECT IS MICROSOFT SPECIFIC, EVERYTHING ELSE IS THUNDERBIRD GENERIC, I LET IT SIT HERE ANYHOW
-
- https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
-
- To select the correct day in the month, set the wYear member to zero, the wHour and wMinute members to
- the transition time, the wDayOfWeek member to the appropriate weekday, and the wDay member to indicate
- the occurrence of the day of the week within the month (1 to 5, where 5 indicates the final occurrence during the
- month if that day of the week does not occur 5 times).
-
- Using this notation, specify 02:00 on the first Sunday in April as follows:
- wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1.
- Specify 02:00 on the last Thursday in October as follows:
- wHour = 2, wMonth = 10, wDayOfWeek = 4, wDay = 5.
-
- So we have to parse the RRULE to exract wDay
- RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 */
-
- let parts =rrule.toString().split(";");
- let rules = {};
- for (let i = 0; i< parts.length; i++) {
- let sub = parts[i].split("=");
- if (sub.length == 2) rules[sub[0]] = sub[1];
- }
-
- if (rules.FREQ == "YEARLY" && rules.BYDAY && rules.BYMONTH && rules.BYDAY.length > 2) {
- obj.switchdate = {};
- obj.switchdate.month = parseInt(rules.BYMONTH);
-
- let days = ["SU","MO","TU","WE","TH","FR","SA"];
- obj.switchdate.dayOfWeek = days.indexOf(rules.BYDAY.substring(rules.BYDAY.length-2));
- obj.switchdate.weekOfMonth = parseInt(rules.BYDAY.substring(0, rules.BYDAY.length-2));
- if (obj.switchdate.weekOfMonth<0 || obj.switchdate.weekOfMonth>5) obj.switchdate.weekOfMonth = 5;
-
- //get switch time from dtstart
- let dttime = eas.tools.createDateTime(dtstart.toString());
- obj.switchdate.hour = dttime.hour;
- obj.switchdate.minute = dttime.minute;
- obj.switchdate.second = dttime.second;
- }
- }
-
- return obj;
- }
- return null;
- },
-}
-
-//TODO: Invites
-/*
- cal.itip.checkAndSendOrigial = cal.itip.checkAndSend;
- cal.itip.checkAndSend = function(aOpType, aItem, aOriginalItem) {
- //if this item is added_by_user, do not call checkAndSend yet, because the UID is wrong, we need to sync first to get the correct ID - TODO
- TbSync.dump("cal.checkAndSend", aOpType);
- cal.itip.checkAndSendOrigial(aOpType, aItem, aOriginalItem);
- }
-*/
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+var { MailServices } = ChromeUtils.importESModule(
+ "resource:///modules/MailServices.sys.mjs"
+);
+var { NetUtil } = ChromeUtils.importESModule(
+ "resource://gre/modules/NetUtil.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+var tools = {
+
+ setCalItemProperty: function (item, prop, value) {
+ if (value == "unset") item.deleteProperty(prop);
+ else item.setProperty(prop, value);
+ },
+
+ getCalItemProperty: function (item, prop) {
+ if (item.hasProperty(prop)) return item.getProperty(prop);
+ else return "unset";
+ },
+
+ isString: function (s) {
+ return (typeof s == 'string' || s instanceof String);
+ },
+
+ getIdentityKey: function (email) {
+ for (let account of MailServices.accounts.accounts) {
+ if (account.defaultIdentity && account.defaultIdentity.email == email) return account.defaultIdentity.key;
+ }
+ return "";
+ },
+
+ parentIsTrash: function (folderData) {
+ let parentID = folderData.getFolderProperty("parentID");
+ if (parentID == "0") return false;
+
+ let parentFolder = folderData.accountData.getFolder("serverID", parentID);
+ if (parentFolder && parentFolder.getFolderProperty("type") == "4") return true;
+
+ return false;
+ },
+
+ getNewDeviceId: function () {
+ //taken from https://jsfiddle.net/briguy37/2MVFd/
+ let d = new Date().getTime();
+ let uuid = 'xxxxxxxxxxxxxxxxyxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ let r = (d + Math.random() * 16) % 16 | 0;
+ d = Math.floor(d / 16);
+ return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
+ });
+ return "MZTB" + uuid;
+ },
+
+ getUriFromDirectoryId: function (ownerId) {
+ let directories = MailServices.ab.directories;
+ for (let directory of directories) {
+ if (directory instanceof Components.interfaces.nsIAbDirectory) {
+ if (ownerId.startsWith(directory.dirPrefId)) return directory.URI;
+ }
+ }
+ return null;
+ },
+
+ //function to get correct uri of current card for global book as well for mailLists
+ getSelectedUri: function (aUri, aCard) {
+ if (aUri == "moz-abdirectory://?") {
+ //get parent via card owner
+ return eas.tools.getUriFromDirectoryId(aCard.directoryId);
+ } else if (MailServices.ab.getDirectory(aUri).isMailList) {
+ //MailList suck, we have to cut the url to get the parent
+ return aUri.substring(0, aUri.lastIndexOf("/"))
+ } else {
+ return aUri;
+ }
+ },
+
+ //read file from within the XPI package
+ fetchFile: function (aURL, returnType = "Array") {
+ return new Promise((resolve, reject) => {
+ let uri = Services.io.newURI(aURL);
+ let channel = Services.io.newChannelFromURI(uri,
+ null,
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ null,
+ Components.interfaces.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
+ Components.interfaces.nsIContentPolicy.TYPE_OTHER);
+
+ NetUtil.asyncFetch(channel, (inputStream, status) => {
+ if (!Components.isSuccessCode(status)) {
+ reject(status);
+ return;
+ }
+
+ try {
+ let data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
+ if (returnType == "Array") {
+ resolve(data.replace("\r", "").split("\n"))
+ } else {
+ resolve(data);
+ }
+ } catch (ex) {
+ reject(ex);
+ }
+ });
+ });
+ },
+
+
+
+
+
+
+
+
+
+
+ // TIMEZONE STUFF
+
+ TimeZoneDataStructure: class {
+ constructor() {
+ this.buf = new DataView(new ArrayBuffer(172));
+ }
+
+ /*
+ Buffer structure:
+ @000 utcOffset (4x8bit as 1xLONG)
+
+ @004 standardName (64x8bit as 32xWCHAR)
+ @068 standardDate (16x8 as 1xSYSTEMTIME)
+ @084 standardBias (4x8bit as 1xLONG)
+
+ @088 daylightName (64x8bit as 32xWCHAR)
+ @152 daylightDate (16x8 as 1xSTRUCT)
+ @168 daylightBias (4x8bit as 1xLONG)
+ */
+
+ set easTimeZone64(b64) {
+ //clear buffer
+ for (let i = 0; i < 172; i++) this.buf.setUint8(i, 0);
+ //load content into buffer
+ let content = (b64 == "") ? "" : atob(b64);
+ for (let i = 0; i < content.length; i++) this.buf.setUint8(i, content.charCodeAt(i));
+ }
+
+ get easTimeZone64() {
+ let content = "";
+ for (let i = 0; i < 172; i++) content += String.fromCharCode(this.buf.getUint8(i));
+ return (btoa(content));
+ }
+
+ getstr(byteoffset) {
+ let str = "";
+ //walk thru the buffer in 32 steps of 16bit (wchars)
+ for (let i = 0; i < 32; i++) {
+ let cc = this.buf.getUint16(byteoffset + i * 2, true);
+ if (cc == 0) break;
+ str += String.fromCharCode(cc);
+ }
+ return str;
+ }
+
+ setstr(byteoffset, str) {
+ //clear first
+ for (let i = 0; i < 32; i++) this.buf.setUint16(byteoffset + i * 2, 0);
+ //walk thru the buffer in steps of 16bit (wchars)
+ for (let i = 0; i < str.length && i < 32; i++) this.buf.setUint16(byteoffset + i * 2, str.charCodeAt(i), true);
+ }
+
+ getsystemtime(buf, offset) {
+ let systemtime = {
+ get wYear() { return buf.getUint16(offset + 0, true); },
+ get wMonth() { return buf.getUint16(offset + 2, true); },
+ get wDayOfWeek() { return buf.getUint16(offset + 4, true); },
+ get wDay() { return buf.getUint16(offset + 6, true); },
+ get wHour() { return buf.getUint16(offset + 8, true); },
+ get wMinute() { return buf.getUint16(offset + 10, true); },
+ get wSecond() { return buf.getUint16(offset + 12, true); },
+ get wMilliseconds() { return buf.getUint16(offset + 14, true); },
+ toString() { return [this.wYear, this.wMonth, this.wDay].join("-") + ", " + this.wDayOfWeek + ", " + [this.wHour, this.wMinute, this.wSecond].join(":") + "." + this.wMilliseconds },
+
+ set wYear(v) { buf.setUint16(offset + 0, v, true); },
+ set wMonth(v) { buf.setUint16(offset + 2, v, true); },
+ set wDayOfWeek(v) { buf.setUint16(offset + 4, v, true); },
+ set wDay(v) { buf.setUint16(offset + 6, v, true); },
+ set wHour(v) { buf.setUint16(offset + 8, v, true); },
+ set wMinute(v) { buf.setUint16(offset + 10, v, true); },
+ set wSecond(v) { buf.setUint16(offset + 12, v, true); },
+ set wMilliseconds(v) { buf.setUint16(offset + 14, v, true); },
+ };
+ return systemtime;
+ }
+
+ get standardDate() { return this.getsystemtime(this.buf, 68); }
+ get daylightDate() { return this.getsystemtime(this.buf, 152); }
+
+ get utcOffset() { return this.buf.getInt32(0, true); }
+ set utcOffset(v) { this.buf.setInt32(0, v, true); }
+
+ get standardBias() { return this.buf.getInt32(84, true); }
+ set standardBias(v) { this.buf.setInt32(84, v, true); }
+ get daylightBias() { return this.buf.getInt32(168, true); }
+ set daylightBias(v) { this.buf.setInt32(168, v, true); }
+
+ get standardName() { return this.getstr(4); }
+ set standardName(v) { return this.setstr(4, v); }
+ get daylightName() { return this.getstr(88); }
+ set daylightName(v) { return this.setstr(88, v); }
+
+ toString() {
+ return ["",
+ "utcOffset: " + this.utcOffset,
+ "standardName: " + this.standardName,
+ "standardDate: " + this.standardDate.toString(),
+ "standardBias: " + this.standardBias,
+ "daylightName: " + this.daylightName,
+ "daylightDate: " + this.daylightDate.toString(),
+ "daylightBias: " + this.daylightBias].join("\n");
+ }
+ },
+
+
+ //Date has a toISOString method, which returns the Date obj as extended ISO 8601,
+ //however EAS MS-ASCAL uses compact/basic ISO 8601,
+ dateToBasicISOString: function (date) {
+ function pad(number) {
+ if (number < 10) {
+ return '0' + number;
+ }
+ return number.toString();
+ }
+
+ return pad(date.getUTCFullYear()) +
+ pad(date.getUTCMonth() + 1) +
+ pad(date.getUTCDate()) +
+ 'T' +
+ pad(date.getUTCHours()) +
+ pad(date.getUTCMinutes()) +
+ pad(date.getUTCSeconds()) +
+ 'Z';
+ },
+
+
+ //Save replacement for cal.createDateTime, which accepts compact/basic and also extended ISO 8601,
+ //cal.createDateTime only supports compact/basic
+ createDateTime: function (str) {
+ let datestring = str;
+ if (str.indexOf("-") == 4) {
+ //this looks like extended ISO 8601
+ let tempDate = new Date(str);
+ datestring = eas.tools.dateToBasicISOString(tempDate);
+ }
+ return TbSync.lightning.cal.createDateTime(datestring);
+ },
+
+
+ // Convert TB date to UTC and return it as basic or extended ISO 8601 String
+ getIsoUtcString: function (origdate, requireExtendedISO = false, fakeUTC = false) {
+ let date = origdate.clone();
+ //floating timezone cannot be converted to UTC (cause they float) - we have to overwrite it with the local timezone
+ if (date.timezone.tzid == "floating") date.timezone = eas.defaultTimezoneInfo.timezone;
+ //to get the UTC string we could use icalString (which does not work on allDayEvents, or calculate it from nativeTime)
+ date.isDate = 0;
+ let UTC = date.getInTimezone(eas.utcTimezone);
+ if (fakeUTC) UTC = date.clone();
+
+ function pad(number) {
+ if (number < 10) {
+ return '0' + number;
+ }
+ return number;
+ }
+
+ if (requireExtendedISO) {
+ return UTC.year +
+ "-" + pad(UTC.month + 1) +
+ "-" + pad(UTC.day) +
+ "T" + pad(UTC.hour) +
+ ":" + pad(UTC.minute) +
+ ":" + pad(UTC.second) +
+ "." + "000" +
+ "Z";
+ } else {
+ return UTC.icalString;
+ }
+ },
+
+ getNowUTC: function () {
+ return TbSync.lightning.cal.dtz.jsDateToDateTime(new Date()).getInTimezone(TbSync.lightning.cal.dtz.UTC);
+ },
+
+ //guess the IANA timezone (used by TB) based on the current offset (standard or daylight)
+ guessTimezoneByCurrentOffset: function (curOffset, utcDateTime) {
+ //if we only now the current offset and the current date, we need to actually try each TZ.
+ let tzService = TbSync.lightning.cal.timezoneService;
+
+ //first try default tz
+ let test = utcDateTime.getInTimezone(eas.defaultTimezoneInfo.timezone);
+ TbSync.dump("Matching TZ via current offset: " + test.timezone.tzid + " @ " + curOffset, test.timezoneOffset / -60);
+ if (test.timezoneOffset / -60 == curOffset) return test.timezone;
+
+ //second try UTC
+ test = utcDateTime.getInTimezone(eas.utcTimezone);
+ TbSync.dump("Matching TZ via current offset: " + test.timezone.tzid + " @ " + curOffset, test.timezoneOffset / -60);
+ if (test.timezoneOffset / -60 == curOffset) return test.timezone;
+
+ //third try all others
+ for (let timezoneId of tzService.timezoneIds) {
+ let test = utcDateTime.getInTimezone(tzService.getTimezone(timezoneId));
+ TbSync.dump("Matching TZ via current offset: " + test.timezone.tzid + " @ " + curOffset, test.timezoneOffset / -60);
+ if (test.timezoneOffset / -60 == curOffset) return test.timezone;
+ }
+
+ //return default TZ as fallback
+ return eas.defaultTimezoneInfo.timezone;
+ },
+
+
+ //guess the IANA timezone (used by TB) based on stdandard offset, daylight offset and standard name
+ guessTimezoneByStdDstOffset: function (stdOffset, dstOffset, stdName = "") {
+
+ //get a list of all zones
+ //alternativly use cal.fromRFC3339 - but this is only doing this:
+ //https://dxr.mozilla.org/comm-central/source/calendar/base/modules/calProviderUtils.sys.mjs
+
+ //cache timezone data on first attempt
+ if (eas.cachedTimezoneData === null) {
+ eas.cachedTimezoneData = {};
+ eas.cachedTimezoneData.iana = {};
+ eas.cachedTimezoneData.abbreviations = {};
+ eas.cachedTimezoneData.stdOffset = {};
+ eas.cachedTimezoneData.bothOffsets = {};
+
+ let tzService = TbSync.lightning.cal.timezoneService;
+
+ //cache timezones data from internal IANA data
+ for (let timezoneId of tzService.timezoneIds) {
+ let timezone = tzService.getTimezone(timezoneId);
+ let tzInfo = eas.tools.getTimezoneInfo(timezone);
+
+ eas.cachedTimezoneData.bothOffsets[tzInfo.std.offset + ":" + tzInfo.dst.offset] = timezone;
+ eas.cachedTimezoneData.stdOffset[tzInfo.std.offset] = timezone;
+
+ eas.cachedTimezoneData.abbreviations[tzInfo.std.abbreviation] = timezoneId;
+ eas.cachedTimezoneData.iana[timezoneId] = tzInfo;
+
+ //TbSync.dump("TZ ("+ tzInfo.std.id + " :: " + tzInfo.dst.id + " :: " + tzInfo.std.displayname + " :: " + tzInfo.dst.displayname + " :: " + tzInfo.std.offset + " :: " + tzInfo.dst.offset + ")", tzService.getTimezone(id));
+ }
+
+ //make sure, that UTC timezone is there
+ eas.cachedTimezoneData.bothOffsets["0:0"] = eas.utcTimezone;
+
+ //multiple TZ share the same offset and abbreviation, make sure the default timezone is present
+ eas.cachedTimezoneData.abbreviations[eas.defaultTimezoneInfo.std.abbreviation] = eas.defaultTimezoneInfo.std.id;
+ eas.cachedTimezoneData.bothOffsets[eas.defaultTimezoneInfo.std.offset + ":" + eas.defaultTimezoneInfo.dst.offset] = eas.defaultTimezoneInfo.timezone;
+ eas.cachedTimezoneData.stdOffset[eas.defaultTimezoneInfo.std.offset] = eas.defaultTimezoneInfo.timezone;
+
+ }
+
+ /*
+ 1. Try to find name in Windows names and map to IANA -> if found, does the stdOffset match? -> if so, done
+ 2. Try to parse our own format, split name and test each chunk for IANA -> if found, does the stdOffset match? -> if so, done
+ 3. Try if one of the chunks matches international code -> if found, does the stdOffset match? -> if so, done
+ 4. Fallback: Use just the offsets */
+
+
+ //check for windows timezone name
+ if (eas.windowsToIanaTimezoneMap[stdName] && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]] && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].std.offset == stdOffset) {
+ //the windows timezone maps multiple IANA zones to one (Berlin*, Rome, Bruessel)
+ //check the windowsZoneName of the default TZ and of the winning, if they match, use default TZ
+ //so Rome could win, even Berlin is the default IANA zone
+ if (eas.defaultTimezoneInfo.std.windowsZoneName && eas.windowsToIanaTimezoneMap[stdName] != eas.defaultTimezoneInfo.std.id && eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].std.offset == eas.defaultTimezoneInfo.std.offset && stdName == eas.defaultTimezoneInfo.std.windowsZoneName) {
+ TbSync.dump("Timezone matched via windows timezone name (" + stdName + ") with default TZ overtake", eas.windowsToIanaTimezoneMap[stdName] + " -> " + eas.defaultTimezoneInfo.std.id);
+ return eas.defaultTimezoneInfo.timezone;
+ }
+
+ TbSync.dump("Timezone matched via windows timezone name (" + stdName + ")", eas.windowsToIanaTimezoneMap[stdName]);
+ return eas.cachedTimezoneData.iana[eas.windowsToIanaTimezoneMap[stdName]].timezone;
+ }
+
+ let parts = stdName.replace(/[;,()\[\]]/g, " ").split(" ");
+ for (let i = 0; i < parts.length; i++) {
+ //check for IANA
+ if (eas.cachedTimezoneData.iana[parts[i]] && eas.cachedTimezoneData.iana[parts[i]].std.offset == stdOffset) {
+ TbSync.dump("Timezone matched via IANA", parts[i]);
+ return eas.cachedTimezoneData.iana[parts[i]].timezone;
+ }
+
+ //check for international abbreviation for standard period (CET, CAT, ...)
+ if (eas.cachedTimezoneData.abbreviations[parts[i]] && eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]] && eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]].std.offset == stdOffset) {
+ TbSync.dump("Timezone matched via international abbreviation (" + parts[i] + ")", eas.cachedTimezoneData.abbreviations[parts[i]]);
+ return eas.cachedTimezoneData.iana[eas.cachedTimezoneData.abbreviations[parts[i]]].timezone;
+ }
+ }
+
+ //fallback to zone based on stdOffset and dstOffset, if we have that cached
+ if (eas.cachedTimezoneData.bothOffsets[stdOffset + ":" + dstOffset]) {
+ TbSync.dump("Timezone matched via both offsets (std:" + stdOffset + ", dst:" + dstOffset + ")", eas.cachedTimezoneData.bothOffsets[stdOffset + ":" + dstOffset].tzid);
+ return eas.cachedTimezoneData.bothOffsets[stdOffset + ":" + dstOffset];
+ }
+
+ //fallback to zone based on stdOffset only, if we have that cached
+ if (eas.cachedTimezoneData.stdOffset[stdOffset]) {
+ TbSync.dump("Timezone matched via std offset (" + stdOffset + ")", eas.cachedTimezoneData.stdOffset[stdOffset].tzid);
+ return eas.cachedTimezoneData.stdOffset[stdOffset];
+ }
+
+ //return default timezone, if everything else fails
+ TbSync.dump("Timezone could not be matched via offsets (std:" + stdOffset + ", dst:" + dstOffset + "), using default timezone", eas.defaultTimezoneInfo.std.id);
+ return eas.defaultTimezoneInfo.timezone;
+ },
+
+
+ //extract standard and daylight timezone data
+ getTimezoneInfo: function (timezone) {
+ let tzInfo = {};
+
+ tzInfo.std = eas.tools.getTimezoneInfoObject(timezone, "standard");
+ tzInfo.dst = eas.tools.getTimezoneInfoObject(timezone, "daylight");
+
+ if (tzInfo.dst === null) tzInfo.dst = tzInfo.std;
+
+ tzInfo.timezone = timezone;
+ return tzInfo;
+ },
+
+
+ //get timezone info for standard/daylight
+ getTimezoneInfoObject: function (timezone, standardOrDaylight) {
+
+ //handle UTC
+ if (timezone.isUTC) {
+ let obj = {}
+ obj.id = "UTC";
+ obj.offset = 0;
+ obj.abbreviation = "UTC";
+ obj.displayname = "Coordinated Universal Time (UTC)";
+ return obj;
+ }
+
+ //we could parse the icalstring by ourself, but I wanted to use ICAL.parse - TODO try catch
+ let info = TbSync.lightning.ICAL.parse("BEGIN:VCALENDAR\r\n" + timezone.icalComponent.toString() + "\r\nEND:VCALENDAR");
+ let comp = new TbSync.lightning.ICAL.Component(info);
+ let vtimezone = comp.getFirstSubcomponent("vtimezone");
+ let id = vtimezone.getFirstPropertyValue("tzid").toString();
+ let zone = vtimezone.getFirstSubcomponent(standardOrDaylight);
+
+ if (zone) {
+ let obj = {};
+ obj.id = id;
+
+ //get offset
+ let utcOffset = zone.getFirstPropertyValue("tzoffsetto").toString();
+ let o = parseInt(utcOffset.replace(":", "")); //-330 = - 3h 30min
+ let h = Math.floor(o / 100); //-3 -> -180min
+ let m = o - (h * 100) //-330 - -300 = -30
+ obj.offset = -1 * ((h * 60) + m);
+
+ //get international abbreviation (CEST, CET, CAT ... )
+ obj.abbreviation = "";
+ try {
+ obj.abbreviation = zone.getFirstPropertyValue("tzname").toString();
+ } catch (e) {
+ TbSync.dump("Failed TZ", timezone.icalComponent.toString());
+ }
+
+ //get displayname
+ obj.displayname = /*"("+utcOffset+") " +*/ obj.id;// + ", " + obj.abbreviation;
+
+ //get DST switch date
+ let rrule = zone.getFirstPropertyValue("rrule");
+ let dtstart = zone.getFirstPropertyValue("dtstart");
+ if (rrule && dtstart) {
+ /*
+
+ THE switchdate PART OF THE OBJECT IS MICROSOFT SPECIFIC, EVERYTHING ELSE IS THUNDERBIRD GENERIC, I LET IT SIT HERE ANYHOW
+
+ https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
+
+ To select the correct day in the month, set the wYear member to zero, the wHour and wMinute members to
+ the transition time, the wDayOfWeek member to the appropriate weekday, and the wDay member to indicate
+ the occurrence of the day of the week within the month (1 to 5, where 5 indicates the final occurrence during the
+ month if that day of the week does not occur 5 times).
+
+ Using this notation, specify 02:00 on the first Sunday in April as follows:
+ wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1.
+ Specify 02:00 on the last Thursday in October as follows:
+ wHour = 2, wMonth = 10, wDayOfWeek = 4, wDay = 5.
+
+ So we have to parse the RRULE to exract wDay
+ RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 */
+
+ let parts = rrule.toString().split(";");
+ let rules = {};
+ for (let i = 0; i < parts.length; i++) {
+ let sub = parts[i].split("=");
+ if (sub.length == 2) rules[sub[0]] = sub[1];
+ }
+
+ if (rules.FREQ == "YEARLY" && rules.BYDAY && rules.BYMONTH && rules.BYDAY.length > 2) {
+ obj.switchdate = {};
+ obj.switchdate.month = parseInt(rules.BYMONTH);
+
+ let days = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
+ obj.switchdate.dayOfWeek = days.indexOf(rules.BYDAY.substring(rules.BYDAY.length - 2));
+ obj.switchdate.weekOfMonth = parseInt(rules.BYDAY.substring(0, rules.BYDAY.length - 2));
+ if (obj.switchdate.weekOfMonth < 0 || obj.switchdate.weekOfMonth > 5) obj.switchdate.weekOfMonth = 5;
+
+ //get switch time from dtstart
+ let dttime = eas.tools.createDateTime(dtstart.toString());
+ obj.switchdate.hour = dttime.hour;
+ obj.switchdate.minute = dttime.minute;
+ obj.switchdate.second = dttime.second;
+ }
+ }
+
+ return obj;
+ }
+ return null;
+ },
+}
+
+//TODO: Invites
+/*
+ cal.itip.checkAndSendOrigial = cal.itip.checkAndSend;
+ cal.itip.checkAndSend = function(aOpType, aItem, aOriginalItem) {
+ //if this item is added_by_user, do not call checkAndSend yet, because the UID is wrong, we need to sync first to get the correct ID - TODO
+ TbSync.dump("cal.checkAndSend", aOpType);
+ cal.itip.checkAndSendOrigial(aOpType, aItem, aOriginalItem);
+ }
+*/
diff -Nru eas4tbsync-4.11/content/includes/wbxmltools.js eas4tbsync-4.17/content/includes/wbxmltools.js
--- eas4tbsync-4.11/content/includes/wbxmltools.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/wbxmltools.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,878 +1,888 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-var wbxmltools = {
-
- // Convert a WBXML (WAP Binary XML) to plain XML - returns save xml with all special chars in the user data encoded by encodeURIComponent
- convert2xml: function (wbxml) {
-
- let num = 4; //skip the 4 first bytes which are mostly 0x03 (WBXML Version 1.3), 0x01 (unknown public identifier), 0x6A (utf-8), 0x00 (Length of string table)
-
- //the main code page will be set to the the first codepage used
- let mainCodePage = null;
-
- let tagStack = [];
- let xml = "";
- let codepage = 0;
-
- while (num < wbxml.length) {
- let data = wbxml.substr(num, 1).charCodeAt(0);
- let token = data & 0x3F; //removes content bit(6) and attribute bit(7)
- let tokenHasContent = ((data & 0x40) != 0); //checks if content bit is set
- let tokenHasAttributes = ((data & 0x80) != 0); //checks if attribute bit is set
-
- switch(token) {
- case 0x00: // switch of codepage (new codepage is next byte)
- num = num + 1;
- codepage = (wbxml.substr(num, 1)).charCodeAt(0) & 0xFF;
- break;
-
- case 0x01: // Indicates the end of an attribute list or the end of an element
- // tagStack contains a list of opened tags, which await to be closed
- xml = xml + tagStack.pop();
- break;
-
- case 0x02: // A character entity. Followed by a mb_u_int32 encoding the character entity number.
- TbSync.dump("wbxml", "Encoded character entity has not yet been implemented. Sorry.");
- return false;
- break;
-
- case 0x03: // Inline string followed by a termstr. (0x00)
- let termpos = wbxml.indexOf(String.fromCharCode(0x00), num);
- //encode all special chars in the user data by encodeURIComponent which does not encode the apostrophe, so we need to do that by hand
- xml = xml + encodeURIComponent(wbxml.substring(num + 1, termpos)).replace(/'/g, "%27");
- num = termpos;
- break;
-
- case 0x04: // An unknown tag or attribute name. Followed by an mb_u_int32 that encodes an offset into the string table.
- case 0x40: // Inline string document-type-specific extension token. Token is followed by a termstr.
- case 0x41: // Inline string document-type-specific extension token. Token is followed by a termstr.
- case 0x42: // Inline string document-type-specific extension token. Token is followed by a termstr.
- case 0x43: // Processing instruction.
- case 0x44: // Unknown tag, with content.
- case 0x80: // Inline integer document-type-specific extension token. Token is followed by a mb_uint_32.
- case 0x81: // Inline integer document-type-specific extension token. Token is followed by a mb_uint_32.
- case 0x82: // Inline integer document-type-specific extension token. Token is followed by a mb_uint_32.
- case 0x83: // String table reference. Followed by a mb_u_int32 encoding a byte offset from the beginning of the string table.
- case 0x84: // Unknown tag, with attributes.
- case 0xC0: // Single-byte document-type-specific extension token.
- case 0xC1: // Single-byte document-type-specific extension token.
- case 0xC2: // Single-byte document-type-specific extension token.
- case 0xC3: // Opaque document-type-specific data.
- case 0xC4: // Unknown tag, with content and attributes.
- TbSync.dump("wbxml", "Global token <" + token + "> has not yet been implemented. Sorry.");
- return false;
- break;
-
- default:
- // if this code page is not the mainCodePage (or mainCodePage is not yet set = very first tag), add codePageTag with current codepage
- let codePageTag = (codepage != mainCodePage) ? " xmlns='" + this.getNamespace(codepage) + "'" : "";
-
- // if no mainCodePage has been defined yet, use the current codepage, which is either the initialized/default value of codepage or a value set by SWITCH_PAGE
- if (mainCodePage === null) mainCodePage = codepage;
-
- if (!tokenHasContent) {
- xml = xml + "<" + this. getCodepageToken(codepage, token) + codePageTag + "/>";
- } else {
- xml = xml + "<" +this. getCodepageToken(codepage, token) + codePageTag +">";
- //add the closing tag to the stack, so it can get properly closed later
- tagStack.push("" +this. getCodepageToken(codepage, token) + ">");
- }
-
- if (this.isUnknownToken(codepage, token)) {
- TbSync.eventlog.add("warning", null, "WBXML: Unknown token <" + token + "> for codepage <"+codepage+">.");
- }
- }
- num = num + 1;
- }
- return (xml == "") ? "" : '' + xml;
- },
-
- isUnknownToken: function (codepage, token) {
- if (this.codepages[codepage] && token in this.codepages[codepage]) return false;
- else return true;
- },
-
- getNamespace: function (codepage) {
- return (this.namespaces[codepage]) ? this.namespaces[codepage] : "UnknownCodePage" + codepage ;
- },
-
- getCodepageToken: function (codepage, token) {
- return this.isUnknownToken(codepage, token) ? "Unknown." + codepage + "." + token : this.codepages[codepage][token];
- },
-
- // This returns a wbxml object, which allows to add tags (using names), switch codepages, or open and close tags, it is also possible to append pure (binary) wbxml
- // If no wbxmlstring is present, default to the "init" string ( WBXML Version 1.3, unknown public identifier, UTF-8, Length of string table)
- createWBXML: function (wbxmlstring = String.fromCharCode(0x03, 0x01, 0x6A, 0x00), initialCodepage = "") {
- let wbxml = {
- _codepage : 0,
- _wbxml : wbxmlstring,
-
- append : function (wbxmlstring) {
- this._wbxml = this._wbxml + wbxmlstring;
- },
-
- // adding a string content tag as contentstring
- atag : function (tokenname, content = "") {
- //check if tokenname is in current codepage
- if ((this._codepage in wbxmltools.codepages2) == false) throw "[wbxmltools] Unknown codepage <"+this._codepage+">";
- if ((tokenname in wbxmltools.codepages2[this._codepage]) == false) throw "[wbxmltools] Unknown tokenname <"+tokenname+"> for codepage <"+wbxmltools.namespaces[this._codepage]+">";
-
- if (content == "") {
- //empty, just add token
- this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname]);
- } else {
- //not empty,add token with enabled content bit and also add inlinestringidentifier
- this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname] | 0x40, 0x03);
- //add content
- for (let i=0; i< content.length; i++) this._wbxml += String.fromCharCode(content.charCodeAt(i));
- //add string termination and tag close
- this._wbxml += String.fromCharCode(0x00, 0x01);
- }
- },
-
- switchpage : function (name) {
- let codepage = wbxmltools.namespaces.indexOf(name);
- if (codepage == -1) throw "[wbxmltools] Unknown codepage <"+ name +">";
- this._codepage = codepage;
- this._wbxml += String.fromCharCode(0x00, codepage);
- },
-
- ctag : function () {
- this._wbxml += String.fromCharCode(0x01);
- },
-
- //opentag is assumed to add a token with content, otherwise use addtag
- otag : function (tokenname) {
- this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname] | 0x40);
- },
-
- getCharCodes : function () {
- let value = "";
- for (let i=0; i has not yet been implemented. Sorry.");
+ return false;
+ break;
+
+ default:
+ // if this code page is not the mainCodePage (or mainCodePage is not yet set = very first tag), add codePageTag with current codepage
+ let codePageTag = (codepage != mainCodePage) ? " xmlns='" + this.getNamespace(codepage) + "'" : "";
+
+ // if no mainCodePage has been defined yet, use the current codepage, which is either the initialized/default value of codepage or a value set by SWITCH_PAGE
+ if (mainCodePage === null) mainCodePage = codepage;
+
+ if (!tokenHasContent) {
+ xml = xml + "<" + this.getCodepageToken(codepage, token) + codePageTag + "/>";
+ } else {
+ xml = xml + "<" + this.getCodepageToken(codepage, token) + codePageTag + ">";
+ //add the closing tag to the stack, so it can get properly closed later
+ tagStack.push("" + this.getCodepageToken(codepage, token) + ">");
+ }
+
+ if (this.isUnknownToken(codepage, token)) {
+ TbSync.eventlog.add("warning", null, "WBXML: Unknown token <" + token + "> for codepage <" + codepage + ">.");
+ }
+ }
+ num = num + 1;
+ }
+ return (xml == "") ? "" : '' + xml;
+ },
+
+ isUnknownToken: function (codepage, token) {
+ if (this.codepages[codepage] && token in this.codepages[codepage]) return false;
+ else return true;
+ },
+
+ getNamespace: function (codepage) {
+ return (this.namespaces[codepage]) ? this.namespaces[codepage] : "UnknownCodePage" + codepage;
+ },
+
+ getCodepageToken: function (codepage, token) {
+ return this.isUnknownToken(codepage, token) ? "Unknown." + codepage + "." + token : this.codepages[codepage][token];
+ },
+
+ // This returns a wbxml object, which allows to add tags (using names), switch codepages, or open and close tags, it is also possible to append pure (binary) wbxml
+ // If no wbxmlstring is present, default to the "init" string ( WBXML Version 1.3, unknown public identifier, UTF-8, Length of string table)
+ createWBXML: function (wbxmlstring = String.fromCharCode(0x03, 0x01, 0x6A, 0x00), initialCodepage = "") {
+ let wbxml = {
+ _codepage: 0,
+ _wbxml: wbxmlstring,
+
+ append: function (wbxmlstring) {
+ this._wbxml = this._wbxml + wbxmlstring;
+ },
+
+ // adding a string content tag as contentstring
+ atag: function (tokenname, content = "") {
+ //check if tokenname is in current codepage
+ if ((this._codepage in wbxmltools.codepages2) == false) throw "[wbxmltools] Unknown codepage <" + this._codepage + ">";
+ if ((tokenname in wbxmltools.codepages2[this._codepage]) == false) throw "[wbxmltools] Unknown tokenname <" + tokenname + "> for codepage <" + wbxmltools.namespaces[this._codepage] + ">";
+
+ if (content == "") {
+ //empty, just add token
+ this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname]);
+ } else {
+ //not empty,add token with enabled content bit and also add inlinestringidentifier
+ this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname] | 0x40, 0x03);
+ //add content
+ for (let i = 0; i < content.length; i++) this._wbxml += String.fromCharCode(content.charCodeAt(i));
+ //add string termination and tag close
+ this._wbxml += String.fromCharCode(0x00, 0x01);
+ }
+ },
+
+ switchpage: function (name) {
+ let codepage = wbxmltools.namespaces.indexOf(name);
+ if (codepage == -1) throw "[wbxmltools] Unknown codepage <" + name + ">";
+ this._codepage = codepage;
+ this._wbxml += String.fromCharCode(0x00, codepage);
+ },
+
+ ctag: function () {
+ this._wbxml += String.fromCharCode(0x01);
+ },
+
+ //opentag is assumed to add a token with content, otherwise use addtag
+ otag: function (tokenname) {
+ this._wbxml += String.fromCharCode(wbxmltools.codepages2[this._codepage][tokenname] | 0x40);
+ },
+
+ getCharCodes: function () {
+ let value = "";
+ for (let i = 0; i < this._wbxml.length; i++) value += ("00" + this._wbxml.charCodeAt(i).toString(16)).substr(-2) + " ";
+ return value;
+ },
+
+ getBytes: function () {
+ return this._wbxml;
+ }
+ };
+ if (initialCodepage) wbxml._codepage = wbxmltools.namespaces.indexOf(initialCodepage);
+ return wbxml;
+ },
+
+
+
+
+
+ codepages2: [],
+
+ buildCodepages2: function () {
+ for (let i = 0; i < this.codepages.length; i++) {
+ let inverted = {};
+ for (let token in this.codepages[i]) {
+ inverted[this.codepages[i][token]] = token;
+ }
+ this.codepages2.push(inverted);
+ }
+ },
+
+
+
+
+
+ codepages: [
+ // Code Page 0: AirSync
+ {
+ 0x05: 'Sync',
+ 0x06: 'Responses',
+ 0x07: 'Add',
+ 0x08: 'Change',
+ 0x09: 'Delete',
+ 0x0A: 'Fetch',
+ 0x0B: 'SyncKey',
+ 0x0C: 'ClientId',
+ 0x0D: 'ServerId',
+ 0x0E: 'Status',
+ 0x0F: 'Collection',
+ 0x10: 'Class',
+ 0x12: 'CollectionId',
+ 0x13: 'GetChanges',
+ 0x14: 'MoreAvailable',
+ 0x15: 'WindowSize',
+ 0x16: 'Commands',
+ 0x17: 'Options',
+ 0x18: 'FilterType',
+ 0x1B: 'Conflict',
+ 0x1C: 'Collections',
+ 0x1D: 'ApplicationData',
+ 0x1E: 'DeletesAsMoves',
+ 0x20: 'Supported',
+ 0x21: 'SoftDelete',
+ 0x22: 'MIMESupport',
+ 0x23: 'MIMETruncation',
+ 0x24: 'Wait',
+ 0x25: 'Limit',
+ 0x26: 'Partial',
+ 0x27: 'ConversationMode',
+ 0x28: 'MaxItems',
+ 0x29: 'HeartbeatInterval'
+ },
+ // Code Page 1: Contacts
+ {
+ 0x05: 'Anniversary',
+ 0x06: 'AssistantName',
+ 0x07: 'AssistantPhoneNumber',
+ 0x08: 'Birthday',
+ 0x09: 'Body',
+ 0x0A: 'BodySize',
+ 0x0B: 'BodyTruncated',
+ 0x0C: 'Business2PhoneNumber',
+ 0x0D: 'BusinessAddressCity',
+ 0x0E: 'BusinessAddressCountry',
+ 0x0F: 'BusinessAddressPostalCode',
+ 0x10: 'BusinessAddressState',
+ 0x11: 'BusinessAddressStreet',
+ 0x12: 'BusinessFaxNumber',
+ 0x13: 'BusinessPhoneNumber',
+ 0x14: 'CarPhoneNumber',
+ 0x15: 'Categories',
+ 0x16: 'Category',
+ 0x17: 'Children',
+ 0x18: 'Child',
+ 0x19: 'CompanyName',
+ 0x1A: 'Department',
+ 0x1B: 'Email1Address',
+ 0x1C: 'Email2Address',
+ 0x1D: 'Email3Address',
+ 0x1E: 'FileAs',
+ 0x1F: 'FirstName',
+ 0x20: 'Home2PhoneNumber',
+ 0x21: 'HomeAddressCity',
+ 0x22: 'HomeAddressCountry',
+ 0x23: 'HomeAddressPostalCode',
+ 0x24: 'HomeAddressState',
+ 0x25: 'HomeAddressStreet',
+ 0x26: 'HomeFaxNumber',
+ 0x27: 'HomePhoneNumber',
+ 0x28: 'JobTitle',
+ 0x29: 'LastName',
+ 0x2A: 'MiddleName',
+ 0x2B: 'MobilePhoneNumber',
+ 0x2C: 'OfficeLocation',
+ 0x2D: 'OtherAddressCity',
+ 0x2E: 'OtherAddressCountry',
+ 0x2F: 'OtherAddressPostalCode',
+ 0x30: 'OtherAddressState',
+ 0x31: 'OtherAddressStreet',
+ 0x32: 'PagerNumber',
+ 0x33: 'RadioPhoneNumber',
+ 0x34: 'Spouse',
+ 0x35: 'Suffix',
+ 0x36: 'Title',
+ 0x37: 'WebPage',
+ 0x38: 'YomiCompanyName',
+ 0x39: 'YomiFirstName',
+ 0x3A: 'YomiLastName',
+ 0x3B: 'CompressedRTF',
+ 0x3C: 'Picture',
+ 0x3D: 'Alias',
+ 0x3E: 'WeightedRank'
+ },
+ // Code Page 2: Email
+ {
+ 0x05: 'Attachment',
+ 0x06: 'Attachments',
+ 0x07: 'AttName',
+ 0x08: 'AttSize',
+ 0x09: 'Att0Id',
+ 0x0a: 'AttMethod',
+ 0x0b: 'AttRemoved',
+ 0x0c: 'Body',
+ 0x0d: 'BodySize',
+ 0x0e: 'BodyTruncated',
+ 0x0f: 'DateReceived',
+ 0x10: 'DisplayName',
+ 0x11: 'DisplayTo',
+ 0x12: 'Importance',
+ 0x13: 'MessageClass',
+ 0x14: 'Subject',
+ 0x15: 'Read',
+ 0x16: 'To',
+ 0x17: 'Cc',
+ 0x18: 'From',
+ 0x19: 'ReplyTo',
+ 0x1a: 'AllDayEvent',
+ 0x1b: 'Categories',
+ 0x1c: 'Category',
+ 0x1d: 'DTStamp',
+ 0x1e: 'EndTime',
+ 0x1f: 'InstanceType',
+ 0x20: 'BusyStatus',
+ 0x21: 'Location',
+ 0x22: 'MeetingRequest',
+ 0x23: 'Organizer',
+ 0x24: 'RecurrenceId',
+ 0x25: 'Reminder',
+ 0x26: 'ResponseRequested',
+ 0x27: 'Recurrences',
+ 0x28: 'Recurrence',
+ 0x29: 'Recurrence_Type',
+ 0x2a: 'Recurrence_Until',
+ 0x2b: 'Recurrence_Occurrences',
+ 0x2c: 'Recurrence_Interval',
+ 0x2d: 'Recurrence_DayOfWeek',
+ 0x2e: 'Recurrence_DayOfMonth',
+ 0x2f: 'Recurrence_WeekOfMonth',
+ 0x30: 'Recurrence_MonthOfYear',
+ 0x31: 'StartTime',
+ 0x32: 'Sensitivity',
+ 0x33: 'TimeZone',
+ 0x34: 'GlobalObjId',
+ 0x35: 'ThreadTopic',
+ 0x36: 'MIMEData',
+ 0x37: 'MIMETruncated',
+ 0x38: 'MIMESize',
+ 0x39: 'InternetCPID',
+ 0x3a: 'Flag',
+ 0x3b: 'Status',
+ 0x3c: 'ContentClass',
+ 0x3d: 'FlagType',
+ 0x3e: 'CompleteTime',
+ 0x3f: 'DisallowNewTimeProposal'
+ },
+ // Code Page 3: AirNotify (WBXML code page 3 is no longer in use)
+ {},
+ // Code Page 4: Calendar
+ {
+ 0x05: 'TimeZone',
+ 0x06: 'AllDayEvent',
+ 0x07: 'Attendees',
+ 0x08: 'Attendee',
+ 0x09: 'Email',
+ 0x0a: 'Name',
+ 0x0b: 'Body',
+ 0x0c: 'BodyTruncated',
+ 0x0d: 'BusyStatus',
+ 0x0e: 'Categories',
+ 0x0f: 'Category',
+ 0x10: 'CompressedRTF',
+ 0x11: 'DtStamp',
+ 0x12: 'EndTime',
+ 0x13: 'Exception',
+ 0x14: 'Exceptions',
+ 0x15: 'Deleted',
+ 0x16: 'ExceptionStartTime',
+ 0x17: 'Location',
+ 0x18: 'MeetingStatus',
+ 0x19: 'OrganizerEmail',
+ 0x1a: 'OrganizerName',
+ 0x1b: 'Recurrence',
+ 0x1c: 'Type',
+ 0x1d: 'Until',
+ 0x1e: 'Occurrences',
+ 0x1f: 'Interval',
+ 0x20: 'DayOfWeek',
+ 0x21: 'DayOfMonth',
+ 0x22: 'WeekOfMonth',
+ 0x23: 'MonthOfYear',
+ 0x24: 'Reminder',
+ 0x25: 'Sensitivity',
+ 0x26: 'Subject',
+ 0x27: 'StartTime',
+ 0x28: 'UID',
+ 0x29: 'AttendeeStatus',
+ 0x2a: 'AttendeeType',
+ 0x2b: 'Attachment',
+ 0x2c: 'Attachments',
+ 0x2d: 'AttName',
+ 0x2e: 'AttSize',
+ 0x2f: 'AttOid',
+ 0x30: 'AttMethod',
+ 0x31: 'AttRemoved',
+ 0x32: 'DisplayName',
+ 0x33: 'DisallowNewTimeProposal',
+ 0x34: 'ResponseRequested',
+ 0x35: 'AppointmentReplyTime',
+ 0x36: 'ResponseType',
+ 0x37: 'CalendarType',
+ 0x38: 'IsLeapMonth',
+ 0x39: 'FirstDayOfWeek',
+ 0x3a: 'OnlineMeetingConfLink',
+ 0x3b: 'OnlineMeetingExternalLink'
+ },
+ // Code Page 5: Move
+ {
+ 0x05: 'MoveItems',
+ 0x06: 'Move',
+ 0x07: 'SrcMsgId',
+ 0x08: 'SrcFldId',
+ 0x09: 'DstFldId',
+ 0x0A: 'Response',
+ 0x0B: 'Status',
+ 0x0C: 'DstMsgId'
+ },
+ // Code Page 6: GetItemEstimate
+ {
+ 0x05: 'GetItemEstimate',
+ 0x06: 'Version',
+ 0x07: 'Collections',
+ 0x08: 'Collection',
+ 0x09: 'Class',
+ 0x0A: 'CollectionId',
+ 0x0B: 'DateTime',
+ 0x0C: 'Estimate',
+ 0x0D: 'Response',
+ 0x0E: 'Status'
+ },
+ // Code Page 7: FolderHierarchy
+ {
+ 0x07: 'DisplayName',
+ 0x08: 'ServerId',
+ 0x09: 'ParentId',
+ 0x0A: 'Type',
+ 0x0C: 'Status',
+ 0x0E: 'Changes',
+ 0x0F: 'Add',
+ 0x10: 'Delete',
+ 0x11: 'Update',
+ 0x12: 'SyncKey',
+ 0x13: 'FolderCreate',
+ 0x14: 'FolderDelete',
+ 0x15: 'FolderUpdate',
+ 0x16: 'FolderSync',
+ 0x17: 'Count'
+ },
+ // Code Page 8: MeetingResponse
+ {
+ 0x05: 'CalendarId',
+ 0x06: 'CollectionId',
+ 0x07: 'MeetingResponse',
+ 0x08: 'RequestId',
+ 0x09: 'Request',
+ 0x0a: 'Result',
+ 0x0b: 'Status',
+ 0x0c: 'UserResponse',
+ 0x0e: 'InstanceId'
+ },
+ // Code Page 9: Tasks
+ {
+ 0x05: 'Body',
+ 0x06: 'BodySize',
+ 0x07: 'BodyTruncated',
+ 0x08: 'Categories',
+ 0x09: 'Category',
+ 0x0A: 'Complete',
+ 0x0B: 'DateCompleted',
+ 0x0C: 'DueDate',
+ 0x0D: 'UtcDueDate',
+ 0x0E: 'Importance',
+ 0x0F: 'Recurrence',
+ 0x10: 'Type',
+ 0x11: 'Start',
+ 0x12: 'Until',
+ 0x13: 'Occurrences',
+ 0x14: 'Interval',
+ 0x15: 'DayOfMonth',
+ 0x16: 'DayOfWeek',
+ 0x17: 'WeekOfMonth',
+ 0x18: 'MonthOfYear',
+ 0x19: 'Regenerate',
+ 0x1A: 'DeadOccur',
+ 0x1B: 'ReminderSet',
+ 0x1C: 'ReminderTime',
+ 0x1D: 'Sensitivity',
+ 0x1E: 'StartDate',
+ 0x1F: 'UtcStartDate',
+ 0x20: 'Subject',
+ 0x22: 'OrdinalDate',
+ 0x23: 'SubOrdinalDate',
+ 0x24: 'CalendarType',
+ 0x25: 'IsLeapMonth',
+ 0x26: 'FirstDayOfWeek'
+ },
+ // Code Page 10: ResolveRecipients
+ {
+ 0x05: 'ResolveRecipients',
+ 0x06: 'Response',
+ 0x07: 'Status',
+ 0x08: 'Type',
+ 0x09: 'Recipient',
+ 0x0a: 'DisplayName',
+ 0x0b: 'EmailAddress',
+ 0x0c: 'Certificates',
+ 0x0d: 'Certificate',
+ 0x0e: 'MiniCertificate',
+ 0x0f: 'Options',
+ 0x10: 'To',
+ 0x11: 'CertificateRetrieval',
+ 0x12: 'RecipientCount',
+ 0x13: 'MaxCertificates',
+ 0x14: 'MaxAmbiguousRecipients',
+ 0x15: 'CertificateCount',
+ 0x16: 'Availability',
+ 0x17: 'StartTime',
+ 0x18: 'EndTime',
+ 0x19: 'MergedFreeBusy',
+ 0x1a: 'Picture',
+ 0x1b: 'MaxSize',
+ 0x1c: 'Data',
+ 0x1d: 'MaxPictures'
+ },
+ // Code Page 11: ValidateCert
+ {
+ 0x05: 'ValidateCert',
+ 0x06: 'Certificates',
+ 0x07: 'Certificate',
+ 0x08: 'CertificateChain',
+ 0x09: 'CheckCRL',
+ 0x0a: 'Status'
+ },
+ // Code Page 12: Contacts2
+ {
+ 0x05: 'CustomerId',
+ 0x06: 'GovernmentId',
+ 0x07: 'IMAddress',
+ 0x08: 'IMAddress2',
+ 0x09: 'IMAddress3',
+ 0x0a: 'ManagerName',
+ 0x0b: 'CompanyMainPhone',
+ 0x0c: 'AccountName',
+ 0x0d: 'NickName',
+ 0x0e: 'MMS'
+ },
+ // Code Page 13: Ping
+ {
+ 0x05: 'Ping',
+ 0x06: 'AutdState',
+ //(Not used)
+ 0x07: 'Status',
+ 0x08: 'HeartbeatInterval',
+ 0x09: 'Folders',
+ 0x0A: 'Folder',
+ 0x0B: 'Id',
+ 0x0C: 'Class',
+ 0x0D: 'MaxFolders'
+ },
+ // Code Page 14: Provision
+ {
+ 0x05: 'Provision',
+ 0x06: 'Policies',
+ 0x07: 'Policy',
+ 0x08: 'PolicyType',
+ 0x09: 'PolicyKey',
+ 0x0A: 'Data',
+ 0x0B: 'Status',
+ 0x0C: 'RemoteWipe',
+ 0x0D: 'EASProvisionDoc',
+ 0x0E: 'DevicePasswordEnabled',
+ 0x0F: 'AlphanumericDevicePasswordRequired',
+ 0x10: 'DeviceEncryptionEnabled',
+ 0x10: 'RequireStorageCardEncryption',
+ 0x11: 'PasswordRecoveryEnabled',
+ 0x13: 'AttachmentsEnabled',
+ 0x14: 'MinDevicePasswordLength',
+ 0x15: 'MaxInactivityTimeDeviceLock',
+ 0x16: 'MaxDevicePasswordFailedAttempts',
+ 0x17: 'MaxAttachmentSize',
+ 0x18: 'AllowSimpleDevicePassword',
+ 0x19: 'DevicePasswordExpiration',
+ 0x1A: 'DevicePasswordHistory',
+ 0x1B: 'AllowStorageCard',
+ 0x1C: 'AllowCamera',
+ 0x1D: 'RequireDeviceEncryption',
+ 0x1E: 'AllowUnsignedApplications',
+ 0x1F: 'AllowUnsignedInstallationPackages',
+ 0x20: 'MinDevicePasswordComplexCharacters',
+ 0x21: 'AllowWiFi',
+ 0x22: 'AllowTextMessaging',
+ 0x23: 'AllowPOPIMAPEmail',
+ 0x24: 'AllowBluetooth',
+ 0x25: 'AllowIrDA',
+ 0x26: 'RequireManualSyncWhenRoaming',
+ 0x27: 'AllowDesktopSync',
+ 0x28: 'MaxCalendarAgeFilter',
+ 0x29: 'AllowHTMLEmail',
+ 0x2A: 'MaxEmailAgeFilter',
+ 0x2B: 'MaxEmailBodyTruncationSize',
+ 0x2C: 'MaxEmailHTMLBodyTruncationSize',
+ 0x2D: 'RequireSignedSMIMEMessages',
+ 0x2E: 'RequireEncryptedSMIMEMessages',
+ 0x2F: 'RequireSignedSMIMEAlgorithm',
+ 0x30: 'RequireEncryptionSMIMEAlgorithm',
+ 0x31: 'AllowSMIMEEncryptionAlgorithmNegotiation',
+ 0x32: 'AllowSMIMESoftCerts',
+ 0x33: 'AllowBrowser',
+ 0x34: 'AllowConsumerEmail',
+ 0x35: 'AllowRemoteDesktop',
+ 0x36: 'AllowInternetSharing',
+ 0x37: 'UnapprovedInROMApplicationList',
+ 0x38: 'ApplicationName',
+ 0x39: 'ApprovedApplicationList',
+ 0x3A: 'Hash'
+ },
+ // Code Page 15: Search
+ {
+ 0x05: 'Search',
+ 0x06: 'Stores',
+ 0x07: 'Store',
+ 0x08: 'Name',
+ 0x09: 'Query',
+ 0x0a: 'Options',
+ 0x0b: 'Range',
+ 0x0c: 'Status',
+ 0x0d: 'Response',
+ 0x0e: 'Result',
+ 0x0f: 'Properties',
+ 0x10: 'Total',
+ 0x11: 'EqualTo',
+ 0x12: 'Value',
+ 0x13: 'And',
+ 0x14: 'Or',
+ 0x15: 'FreeText',
+ 0x17: 'DeepTraversal',
+ 0x18: 'LongId',
+ 0x19: 'RebuildResults',
+ 0x1a: 'LessThan',
+ 0x1b: 'GreaterThan',
+ 0x1c: 'Schema',
+ 0x1d: 'Supported',
+ 0x1e: 'UserName',
+ 0x1f: 'Password',
+ 0x20: 'ConversationId',
+ 0x21: 'Picture',
+ 0x22: 'MaxSize',
+ 0x23: 'MaxPictures'
+ },
+ // Code Page 16: GAL
+ {
+ 0x05: 'DisplayName',
+ 0x06: 'Phone',
+ 0x07: 'Office',
+ 0x08: 'Title',
+ 0x09: 'Company',
+ 0x0a: 'Alias',
+ 0x0b: 'FirstName',
+ 0x0c: 'LastName',
+ 0x0d: 'HomePhone',
+ 0x0e: 'MobilePhone',
+ 0x0f: 'EmailAddress',
+ 0x10: 'Picture',
+ 0x11: 'Status',
+ 0x12: 'Data'
+ },
+ // Code Page 17: AirSyncBase
+ {
+ 0x05: 'BodyPreference',
+ 0x06: 'Type',
+ 0x07: 'TruncationSize',
+ 0x08: 'AllOrNone',
+ 0x0A: 'Body',
+ 0x0B: 'Data',
+ 0x0C: 'EstimatedDataSize',
+ 0x0D: 'Truncated',
+ 0x0E: 'Attachments',
+ 0x0F: 'Attachment',
+ 0x10: 'DisplayName',
+ 0x11: 'FileReference',
+ 0x12: 'Method',
+ 0x13: 'ContentId',
+ 0x14: 'ContentLocation',
+ 0x15: 'IsInline',
+ 0x16: 'NativeBodyType',
+ 0x17: 'ContentType',
+ 0x18: 'Preview',
+ 0x19: 'BodyPartPreference',
+ 0x1A: 'BodyPart',
+ 0x1B: 'Status'
+ },
+ // Code Page 18: Settings
+ {
+ 0x05: 'Settings',
+ 0x06: 'Status',
+ 0x07: 'Get',
+ 0x08: 'Set',
+ 0x09: 'Oof',
+ 0x0A: 'OofState',
+ 0x0B: 'StartTime',
+ 0x0C: 'EndTime',
+ 0x0D: 'OofMessage',
+ 0x0E: 'AppliesToInternal',
+ 0x0F: 'AppliesToExternalKnown',
+ 0x10: 'AppliesToExternalUnknown',
+ 0x11: 'Enabled',
+ 0x12: 'ReplyMessage',
+ 0x13: 'BodyType',
+ 0x14: 'DevicePassword',
+ 0x15: 'Password',
+ 0x16: 'DeviceInformation',
+ 0x17: 'Model',
+ 0x18: 'IMEI',
+ 0x19: 'FriendlyName',
+ 0x1A: 'OS',
+ 0x1B: 'OSLanguage',
+ 0x1C: 'PhoneNumber',
+ 0x1D: 'UserInformation',
+ 0x1E: 'EmailAddresses',
+ 0x1F: 'SMTPAddress',
+ 0x20: 'UserAgent',
+ 0x21: 'EnableOutboundSMS',
+ 0x22: 'MobileOperator',
+ 0x23: 'PrimarySmtpAddress',
+ 0x24: 'Accounts',
+ 0x25: 'Account',
+ 0x26: 'AccountId',
+ 0x27: 'AccountName',
+ 0x28: 'UserDisplayName',
+ 0x29: 'SendDisabled',
+ 0x2B: 'RightsManagementInformation'
+ },
+ // Code Page 19: DocumentLibrary
+ {
+ 0x05: 'LinkId',
+ 0x06: 'DisplayName',
+ 0x07: 'IsFolder',
+ 0x08: 'CreationDate',
+ 0x09: 'LastModifiedDate',
+ 0x0a: 'IsHidden',
+ 0x0b: 'ContentLength',
+ 0x0c: 'ContentType'
+ },
+ // Code Page 20: ItemOperations
+ {
+ 0x05: 'ItemOperations',
+ 0x06: 'Fetch',
+ 0x07: 'Store',
+ 0x08: 'Options',
+ 0x09: 'Range',
+ 0x0A: 'Total',
+ 0x0B: 'Properties',
+ 0x0C: 'Data',
+ 0x0D: 'Status',
+ 0x0E: 'Response',
+ 0x0F: 'Version',
+ 0x10: 'Schema',
+ 0x11: 'Part',
+ 0x12: 'EmptyFolderContents',
+ 0x13: 'DeleteSubFolders',
+ 0x14: 'UserName',
+ 0x15: 'Password',
+ 0x16: 'Move',
+ 0x17: 'DstFldId',
+ 0x18: 'ConversationId',
+ 0x19: 'MoveAlways'
+ },
+ // Code Page 21: ComposeMail
+ {
+ 0x05: 'SendMail',
+ 0x06: 'SmartForward',
+ 0x07: 'SmartReply',
+ 0x08: 'SaveInSentItems',
+ 0x09: 'ReplaceMime',
+ 0x0b: 'Source',
+ 0x0c: 'FolderId',
+ 0x0d: 'ItemId',
+ 0x0e: 'LongId',
+ 0x0f: 'InstanceId',
+ 0x10: 'Mime',
+ 0x11: 'ClientId',
+ 0x12: 'Status',
+ 0x13: 'AccountId',
+ 0x15: 'Forwardees',
+ 0x16: 'Forwardee',
+ 0x17: 'ForwardeeName',
+ 0x18: 'ForwardeeEmail'
+ },
+ // Code Page 22: Email2
+ {
+ 0x05: 'UmCallerID',
+ 0x06: 'UmUserNotes',
+ 0x07: 'UmAttDuration',
+ 0x08: 'UmAttOrder',
+ 0x09: 'ConversationId',
+ 0x0a: 'ConversationIndex',
+ 0x0b: 'LastVerbExecuted',
+ 0x0c: 'LastVerbExecutionTime',
+ 0x0d: 'ReceivedAsBcc',
+ 0x0e: 'Sender',
+ 0x0f: 'CalendarType',
+ 0x10: 'IsLeapMonth',
+ 0x11: 'AccountId',
+ 0x12: 'FirstDayOfWeek',
+ 0x13: 'MeetingMessageType',
+ 0x15: 'IsDraft',
+ 0x16: 'Bcc',
+ 0x17: 'Send'
+ },
+ // Code Page 23: Notes
+ {
+ 0x05: 'Subject',
+ 0x06: 'MessageClass',
+ 0x07: 'LastModifiedDate',
+ 0x08: 'Categories',
+ 0x09: 'Category'
+ },
+ // Code Page 24: RightsManagement
+ {
+ 0x05: 'RightsManagementSupport',
+ 0x06: 'RightsManagementTemplates',
+ 0x07: 'RightsManagementTemplate',
+ 0x08: 'RightsManagementLicense',
+ 0x09: 'EditAllowed',
+ 0x0a: 'ReplyAllowed',
+ 0x0b: 'ReplyAllAllowed',
+ 0x0c: 'ForwardAllowed',
+ 0x0d: 'ModifyRecipientsAllowed',
+ 0x0e: 'ExtractAllowed',
+ 0x0f: 'PrintAllowed',
+ 0x10: 'ExportAllowed',
+ 0x11: 'ProgrammaticAccessAllowed',
+ 0x12: 'Owner',
+ 0x13: 'ContentExpiryDate',
+ 0x14: 'TemplateID',
+ 0x15: 'TemplateName',
+ 0x16: 'TemplateDescription',
+ 0x17: 'ContentOwner',
+ 0x18: 'RemoveRightsManagementDistribution'
+ }
+ ],
+
+ namespaces: [
+ 'AirSync',
+ 'Contacts',
+ 'Email',
+ 'AirNotify',
+ 'Calendar',
+ 'Move',
+ 'GetItemEstimate',
+ 'FolderHierarchy',
+ 'MeetingResponse',
+ 'Tasks',
+ 'ResolveRecipients',
+ 'ValidateCert',
+ 'Contacts2',
+ 'Ping',
+ 'Provision',
+ 'Search',
+ 'Gal',
+ 'AirSyncBase',
+ 'Settings',
+ 'DocumentLibrary',
+ 'ItemOperations',
+ 'ComposeMail',
+ 'Email2',
+ 'Notes',
+ 'RightsManagement'
+ ]
+
+};
+
+wbxmltools.buildCodepages2();
diff -Nru eas4tbsync-4.11/content/includes/xmltools.js eas4tbsync-4.17/content/includes/xmltools.js
--- eas4tbsync-4.11/content/includes/xmltools.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/includes/xmltools.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,156 +1,166 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-var xmltools = {
-
- isString : function (obj) {
- return (Object.prototype.toString.call(obj) === '[object String]');
- },
-
- checkString : function(d, fallback = "") {
- if (this.isString(d)) return d;
- else return fallback;
- },
-
- nodeAsArray : function (node) {
- let a = [];
- if (node) {
- //return, if already an array
- if (node instanceof Array) return node;
-
- //else push node into an array
- a.push(node);
- }
- return a;
- },
-
- hasWbxmlDataField: function(wbxmlData, path) {
- if (wbxmlData) {
- let pathElements = path.split(".");
- let data = wbxmlData;
- for (let x = 0; x < pathElements.length; x++) {
- if (data[pathElements[x]]) data = data[pathElements[x]];
- else return false;
- }
- return true;
- }
- return false;
- },
-
- getWbxmlDataField: function(wbxmlData,path) {
- if (wbxmlData) {
- let pathElements = path.split(".");
- let data = wbxmlData;
- let valid = true;
- for (let x = 0; valid && x < pathElements.length; x++) {
- if (data[pathElements[x]]) data = data[pathElements[x]];
- else valid = false;
- }
- if (valid) return data;
- }
- return false
- },
-
- //print content of xml data object (if debug output enabled)
- printXmlData : function (data, printApplicationData) {
- if (TbSync.prefs.getIntPref("log.userdatalevel") > 1 || (TbSync.prefs.getIntPref("log.userdatalevel") == 1 && printApplicationData)) {
- let dump = JSON.stringify(data);
- TbSync.dump("Extracted XML data", "\n" + dump);
- }
- },
-
- getDataFromXMLString: function (str) {
- let data = null;
- let xml = "";
- if (str == "") return data;
-
- let oParser = (Services.vc.compare(Services.appinfo.platformVersion, "61.*") >= 0) ? new DOMParser() : Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
- try {
- xml = oParser.parseFromString(str, "application/xml");
- } catch (e) {
- //however, domparser does not throw an error, it returns an error document
- //https://developer.mozilla.org/de/docs/Web/API/DOMParser
- //just in case
- throw eas.sync.finish("error", "malformed-xml");
- }
-
- //check if xml is error document
- if (xml.documentElement.nodeName == "parsererror") {
- TbSync.dump("BAD XML", "The above XML and WBXML could not be parsed correctly, something is wrong.");
- throw eas.sync.finish("error", "malformed-xml");
- }
-
- try {
- data = this.getDataFromXML(xml);
- } catch (e) {
- throw eas.sync.finish("error", "mailformed-data");
- }
-
- return data;
- },
-
- //create data object from XML node
- getDataFromXML : function (nodes) {
-
- /*
- * The passed nodes value could be an entire document in a single node (type 9) or a
- * single element node (type 1) as returned by getElementById. It could however also
- * be an array of nodes as returned by getElementsByTagName or a nodeList as returned
- * by childNodes. In that case node.length is defined.
- */
-
- // create the return object
- let obj = {};
- let nodeList = [];
- let multiplicity = {};
-
- if (nodes.length === undefined) nodeList.push(nodes);
- else nodeList = nodes;
-
- // nodelist contains all childs, if two childs have the same name, we cannot add the chils as an object, but as an array of objects
- for (let node of nodeList) {
- if (node.nodeType == 1 || node.nodeType == 3) {
- if (!multiplicity.hasOwnProperty(node.nodeName)) multiplicity[node.nodeName] = 0;
- multiplicity[node.nodeName]++;
- //if this nodeName has multiplicity > 1, prepare obj (but only once)
- if (multiplicity[node.nodeName]==2) obj[node.nodeName] = [];
- }
- }
-
- // process nodes
- for (let node of nodeList) {
- switch (node.nodeType) {
- case 9:
- //document node, dive directly and process all children
- if (node.hasChildNodes) obj = this.getDataFromXML(node.childNodes);
- break;
- case 1:
- //element node
- if (node.hasChildNodes) {
- //if this is an element with only one text child, do not dive, but get text childs value
- let o;
- if (node.childNodes.length == 1 && node.childNodes.item(0).nodeType==3) {
- //the passed xml is a save xml with all special chars in the user data encoded by encodeURIComponent
- o = decodeURIComponent(node.childNodes.item(0).nodeValue);
- } else {
- o = this.getDataFromXML(node.childNodes);
- }
- //check, if we can add the object directly, or if we have to push it into an array
- if (multiplicity[node.nodeName]>1) obj[node.nodeName].push(o)
- else obj[node.nodeName] = o;
- }
- break;
- }
- }
- return obj;
- }
-
-};
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+var xmltools = {
+
+ isString: function (obj) {
+ return (Object.prototype.toString.call(obj) === '[object String]');
+ },
+
+ checkString: function (d, fallback = "") {
+ if (this.isString(d)) return d;
+ else return fallback;
+ },
+
+ nodeAsArray: function (node) {
+ let a = [];
+ if (node) {
+ //return, if already an array
+ if (node instanceof Array) return node;
+
+ //else push node into an array
+ a.push(node);
+ }
+ return a;
+ },
+
+ hasWbxmlDataField: function (wbxmlData, path) {
+ if (wbxmlData) {
+ let pathElements = path.split(".");
+ let data = wbxmlData;
+ for (let x = 0; x < pathElements.length; x++) {
+ if (data[pathElements[x]]) data = data[pathElements[x]];
+ else return false;
+ }
+ return true;
+ }
+ return false;
+ },
+
+ getWbxmlDataField: function (wbxmlData, path) {
+ if (wbxmlData) {
+ let pathElements = path.split(".");
+ let data = wbxmlData;
+ let valid = true;
+ for (let x = 0; valid && x < pathElements.length; x++) {
+ if (data[pathElements[x]]) data = data[pathElements[x]];
+ else valid = false;
+ }
+ if (valid) return data;
+ }
+ return false
+ },
+
+ //print content of xml data object (if debug output enabled)
+ printXmlData: function (data, printApplicationData) {
+ if (TbSync.prefs.getIntPref("log.userdatalevel") > 1 || (TbSync.prefs.getIntPref("log.userdatalevel") == 1 && printApplicationData)) {
+ let dump = JSON.stringify(data);
+ TbSync.dump("Extracted XML data", "\n" + dump);
+ }
+ },
+
+ getDataFromXMLString: function (str) {
+ let data = null;
+ let xml = "";
+ if (str == "") return data;
+
+ let oParser = (Services.vc.compare(Services.appinfo.platformVersion, "61.*") >= 0) ? new DOMParser() : Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
+ try {
+ xml = oParser.parseFromString(str, "application/xml");
+ } catch (e) {
+ //however, domparser does not throw an error, it returns an error document
+ //https://developer.mozilla.org/de/docs/Web/API/DOMParser
+ //just in case
+ throw eas.sync.finish("error", "malformed-xml");
+ }
+
+ //check if xml is error document
+ if (xml.documentElement.nodeName == "parsererror") {
+ TbSync.dump("BAD XML", "The above XML and WBXML could not be parsed correctly, something is wrong.");
+ throw eas.sync.finish("error", "malformed-xml");
+ }
+
+ try {
+ data = this.getDataFromXML(xml);
+ } catch (e) {
+ throw eas.sync.finish("error", "mailformed-data");
+ }
+
+ return data;
+ },
+
+ //create data object from XML node
+ getDataFromXML: function (nodes) {
+
+ /*
+ * The passed nodes value could be an entire document in a single node (type 9) or a
+ * single element node (type 1) as returned by getElementById. It could however also
+ * be an array of nodes as returned by getElementsByTagName or a nodeList as returned
+ * by childNodes. In that case node.length is defined.
+ */
+
+ // create the return object
+ let obj = {};
+ let nodeList = [];
+ let multiplicity = {};
+
+ if (nodes.length === undefined) nodeList.push(nodes);
+ else nodeList = nodes;
+
+ // nodelist contains all childs, if two childs have the same name, we cannot add the chils as an object, but as an array of objects
+ for (let node of nodeList) {
+ if (node.nodeType == 1 || node.nodeType == 3) {
+ if (!multiplicity.hasOwnProperty(node.nodeName)) multiplicity[node.nodeName] = 0;
+ multiplicity[node.nodeName]++;
+ //if this nodeName has multiplicity > 1, prepare obj (but only once)
+ if (multiplicity[node.nodeName] == 2) obj[node.nodeName] = [];
+ }
+ }
+
+ // process nodes
+ for (let node of nodeList) {
+ switch (node.nodeType) {
+ case 9:
+ //document node, dive directly and process all children
+ if (node.hasChildNodes) obj = this.getDataFromXML(node.childNodes);
+ break;
+ case 1:
+ //element node
+ if (node.hasChildNodes) {
+ //if this is an element with only one text child, do not dive, but get text childs value
+ let o;
+ if (node.childNodes.length == 1 && node.childNodes.item(0).nodeType == 3) {
+ //the passed xml is a save xml with all special chars in the user data encoded by encodeURIComponent
+ o = decodeURIComponent(node.childNodes.item(0).nodeValue);
+ } else {
+ o = this.getDataFromXML(node.childNodes);
+ }
+ //check, if we can add the object directly, or if we have to push it into an array
+ if (multiplicity[node.nodeName] > 1) obj[node.nodeName].push(o)
+ else obj[node.nodeName] = o;
+ }
+ break;
+ }
+ }
+ return obj;
+ }
+
+};
diff -Nru eas4tbsync-4.11/content/locales.js eas4tbsync-4.17/content/locales.js
--- eas4tbsync-4.11/content/locales.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/locales.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,3 +1,12 @@
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-
-TbSync.localizeOnLoad(window, "eas");
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+TbSync.localizeOnLoad(window, "eas");
diff -Nru eas4tbsync-4.11/content/manager/createAccount.js eas4tbsync-4.17/content/manager/createAccount.js
--- eas4tbsync-4.11/content/manager/createAccount.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/manager/createAccount.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,254 +1,263 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
- "use strict";
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-
-const eas = TbSync.providers.eas;
-
-var tbSyncEasNewAccount = {
-
- startTime: 0,
- maxTimeout: 30,
- validating: false,
-
- onClose: function () {
- //disallow closing of wizard while validating
- return !this.validating;
- },
-
- onCancel: function (event) {
- //disallow closing of wizard while validating
- if (this.validating) {
- event.preventDefault();
- }
- },
-
- onLoad: function () {
- this.providerData = new TbSync.ProviderData("eas");
-
- this.elementName = document.getElementById('tbsync.newaccount.name');
- this.elementUser = document.getElementById('tbsync.newaccount.user');
- this.elementUrl = document.getElementById('tbsync.newaccount.url');
- this.elementPass = document.getElementById('tbsync.newaccount.password');
- this.elementServertype = document.getElementById('tbsync.newaccount.servertype');
-
- document.getElementById("tbsync.newaccount.wizard").getButton("back").hidden = true;
- this.onUserDropdown();
-
- document.getElementById("tbsync.error").hidden = true;
- document.getElementById("tbsync.spinner").hidden = true;
-
- document.addEventListener("wizardfinish", tbSyncEasNewAccount.onFinish.bind(this));
- document.addEventListener("wizardcancel", tbSyncEasNewAccount.onCancel.bind(this));
- // bug https://bugzilla.mozilla.org/show_bug.cgi?id=1618252
- document.getElementById('tbsync.newaccount.wizard')._adjustWizardHeader();
- },
-
- onUnload: function () {
- },
-
- onUserTextInput: function () {
- document.getElementById("tbsync.error").hidden = true;
- switch (this.elementServertype.value) {
- case "select":
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = true;
- break;
-
- case "auto":
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "" || this.elementPass.value == "");
- break;
-
- case "office365":
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "");
- break;
-
- case "custom":
- default:
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "" || this.elementPass.value == "" || this.elementUrl.value.trim() == "");
- break;
- }
- },
-
- onUserDropdown: function () {
- if (this.elementServertype) {
- switch (this.elementServertype.value) {
- case "select":
- document.getElementById('tbsync.newaccount.user.box').hidden = true;
- document.getElementById('tbsync.newaccount.url.box').hidden = true;
- document.getElementById('tbsync.newaccount.password.box').hidden = true;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom","eas");
- break;
-
- case "auto":
- document.getElementById('tbsync.newaccount.user.box').hidden = false;
- document.getElementById('tbsync.newaccount.url.box').hidden = true;
- document.getElementById('tbsync.newaccount.password.box').hidden = false;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_auto","eas");
- break;
-
- case "office365":
- document.getElementById('tbsync.newaccount.user.box').hidden = false;
- document.getElementById('tbsync.newaccount.url.box').hidden = true;
- document.getElementById('tbsync.newaccount.password.box').hidden = true;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom","eas");
- break;
-
- case "custom":
- default:
- document.getElementById('tbsync.newaccount.user.box').hidden = false;
- document.getElementById('tbsync.newaccount.url.box').hidden = false;
- document.getElementById('tbsync.newaccount.password.box').hidden = false;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom","eas");
- break;
- }
- this.onUserTextInput();
- //document.getElementById("tbsync.newaccount.name").focus();
- }
- },
-
- onFinish: function (event) {
- if (document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled == false) {
- //initiate validation of server connection
- this.validate();
- }
- event.preventDefault();
- },
-
- validate: async function () {
- let user = this.elementUser.value;
- let servertype = this.elementServertype.value;
- let accountname = this.elementName.value.trim();
-
- let url = (servertype == "custom") ?this.elementUrl.value.trim() : "";
- let password = (servertype == "auto" || servertype == "custom") ? this.elementPass.value : "";
-
- if ((servertype == "auto" || servertype == "office365") && user.split("@").length != 2) {
- alert(TbSync.getString("autodiscover.NeedEmail","eas"))
- return;
- }
-
- this.validating = true;
- let error = "";
-
- //document.getElementById("tbsync.newaccount.wizard").canRewind = false;
- document.getElementById("tbsync.error").hidden = true;
- document.getElementById("tbsync.newaccount.wizard").getButton("cancel").disabled = true;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = true;
- document.getElementById("tbsync.newaccount.name").disabled = true;
- document.getElementById("tbsync.newaccount.user").disabled = true;
- document.getElementById("tbsync.newaccount.password").disabled = true;
- document.getElementById("tbsync.newaccount.servertype").disabled = true;
-
- tbSyncEasNewAccount.startTime = Date.now();
- tbSyncEasNewAccount.updateAutodiscoverStatus();
- document.getElementById("tbsync.spinner").hidden = false;
-
- //do autodiscover
- if (servertype == "office365" || servertype == "auto") {
- let updateTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
- updateTimer.initWithCallback({notify : function () {tbSyncEasNewAccount.updateAutodiscoverStatus()}}, 1000, 3);
-
- if (servertype == "office365") {
- let v2 = await eas.network.getServerConnectionViaAutodiscoverV2JsonRequest(
- accountname,
- user,
- "https://autodiscover-s.outlook.com/autodiscover/autodiscover.json?Email="+encodeURIComponent(user)+"&Protocol=ActiveSync",
- );
- let oauthData = eas.network.getOAuthObj({ host: v2.server, user, accountname, servertype });
- if (oauthData) {
- // ask for token
- document.getElementById("tbsync.spinner").hidden = true;
- let _rv = {};
- if (await oauthData.asyncConnect(_rv)) {
- password = _rv.tokens;
- } else {
- error = TbSync.getString("status." + _rv.error, "eas");
- }
- document.getElementById("tbsync.spinner").hidden = false;
- url=v2.server;
- } else {
- error = TbSync.getString("status.404", "eas");
- }
- } else {
- let result = await eas.network.getServerConnectionViaAutodiscover(
- accountname,
- user,
- password,
- tbSyncEasNewAccount.maxTimeout*1000
- );
- if (result.server) {
- user = result.user;
- url = result.server;
- } else {
- error = result.error; // is a localized string
- }
- }
-
- updateTimer.cancel();
- }
-
- //now validate the information
- if (!error) {
- if (!password) error = TbSync.getString("status.401", "eas");
- }
-
- //add if valid
- if (!error) {
- await tbSyncEasNewAccount.addAccount(user, password, servertype, accountname, url);
- }
-
- //end validation
- document.getElementById("tbsync.newaccount.name").disabled = false;
- document.getElementById("tbsync.newaccount.user").disabled = false;
- document.getElementById("tbsync.newaccount.password").disabled = false;
- document.getElementById("tbsync.newaccount.servertype").disabled = false;
- document.getElementById("tbsync.newaccount.wizard").getButton("cancel").disabled = false;
- document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = false;
- document.getElementById("tbsync.spinner").hidden = true;
- //document.getElementById("tbsync.newaccount.wizard").canRewind = true;
-
- this.validating = false;
-
- //close wizard, if done
- if (!error) {
- document.getElementById("tbsync.newaccount.wizard").cancel();
- } else {
- document.getElementById("tbsync.error.message").textContent = error;
- document.getElementById("tbsync.error").hidden = false;
- }
- window.sizeToContent();
- },
-
- updateAutodiscoverStatus: function () {
- let offset = Math.round(((Date.now() - tbSyncEasNewAccount.startTime)/1000));
- let timeout = (offset>2) ? " (" + (tbSyncEasNewAccount.maxTimeout - offset) + ")" : "";
-
- document.getElementById('tbsync.newaccount.autodiscoverstatus').value = TbSync.getString("autodiscover.Querying","eas") + timeout;
- },
-
- async addAccount (user, password, servertype, accountname, url) {
- let newAccountEntry = this.providerData.getDefaultAccountEntries();
- newAccountEntry.user = user;
- newAccountEntry.servertype = servertype;
-
- if (url) {
- //if no protocoll is given, prepend "https://"
- if (url.substring(0,4) != "http" || url.indexOf("://") == -1) url = "https://" + url.split("://").join("/");
- newAccountEntry.host = eas.network.stripAutodiscoverUrl(url);
- newAccountEntry.https = (url.substring(0,5) == "https");
- }
-
- // Add the new account.
- let newAccountData = this.providerData.addAccount(accountname, newAccountEntry);
- await eas.network.getAuthData(newAccountData).updateLoginData(user, password);
-
- window.close();
- }
-};
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+const eas = TbSync.providers.eas;
+
+var tbSyncEasNewAccount = {
+
+ startTime: 0,
+ maxTimeout: 30,
+ validating: false,
+
+ onClose: function () {
+ //disallow closing of wizard while validating
+ return !this.validating;
+ },
+
+ onCancel: function (event) {
+ //disallow closing of wizard while validating
+ if (this.validating) {
+ event.preventDefault();
+ }
+ },
+
+ onLoad: function () {
+ this.providerData = new TbSync.ProviderData("eas");
+
+ this.elementName = document.getElementById('tbsync.newaccount.name');
+ this.elementUser = document.getElementById('tbsync.newaccount.user');
+ this.elementUrl = document.getElementById('tbsync.newaccount.url');
+ this.elementPass = document.getElementById('tbsync.newaccount.password');
+ this.elementServertype = document.getElementById('tbsync.newaccount.servertype');
+
+ document.getElementById("tbsync.newaccount.wizard").getButton("back").hidden = true;
+ this.onUserDropdown();
+
+ document.getElementById("tbsync.error").hidden = true;
+ document.getElementById("tbsync.spinner").hidden = true;
+
+ document.addEventListener("wizardfinish", tbSyncEasNewAccount.onFinish.bind(this));
+ document.addEventListener("wizardcancel", tbSyncEasNewAccount.onCancel.bind(this));
+ // bug https://bugzilla.mozilla.org/show_bug.cgi?id=1618252
+ document.getElementById('tbsync.newaccount.wizard')._adjustWizardHeader();
+ },
+
+ onUnload: function () {
+ },
+
+ onUserTextInput: function () {
+ document.getElementById("tbsync.error").hidden = true;
+ switch (this.elementServertype.value) {
+ case "select":
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = true;
+ break;
+
+ case "auto":
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "" || this.elementPass.value == "");
+ break;
+
+ case "office365":
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "");
+ break;
+
+ case "custom":
+ default:
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = (this.elementName.value.trim() == "" || this.elementUser.value == "" || this.elementPass.value == "" || this.elementUrl.value.trim() == "");
+ break;
+ }
+ },
+
+ onUserDropdown: function () {
+ if (this.elementServertype) {
+ switch (this.elementServertype.value) {
+ case "select":
+ document.getElementById('tbsync.newaccount.user.box').hidden = true;
+ document.getElementById('tbsync.newaccount.url.box').hidden = true;
+ document.getElementById('tbsync.newaccount.password.box').hidden = true;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom", "eas");
+ break;
+
+ case "auto":
+ document.getElementById('tbsync.newaccount.user.box').hidden = false;
+ document.getElementById('tbsync.newaccount.url.box').hidden = true;
+ document.getElementById('tbsync.newaccount.password.box').hidden = false;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_auto", "eas");
+ break;
+
+ case "office365":
+ document.getElementById('tbsync.newaccount.user.box').hidden = false;
+ document.getElementById('tbsync.newaccount.url.box').hidden = true;
+ document.getElementById('tbsync.newaccount.password.box').hidden = true;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom", "eas");
+ break;
+
+ case "custom":
+ default:
+ document.getElementById('tbsync.newaccount.user.box').hidden = false;
+ document.getElementById('tbsync.newaccount.url.box').hidden = false;
+ document.getElementById('tbsync.newaccount.password.box').hidden = false;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").label = TbSync.getString("newaccount.add_custom", "eas");
+ break;
+ }
+ this.onUserTextInput();
+ //document.getElementById("tbsync.newaccount.name").focus();
+ }
+ },
+
+ onFinish: function (event) {
+ if (document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled == false) {
+ //initiate validation of server connection
+ this.validate();
+ }
+ event.preventDefault();
+ },
+
+ validate: async function () {
+ let user = this.elementUser.value;
+ let servertype = this.elementServertype.value;
+ let accountname = this.elementName.value.trim();
+
+ let url = (servertype == "custom") ? this.elementUrl.value.trim() : "";
+ let password = (servertype == "auto" || servertype == "custom") ? this.elementPass.value : "";
+
+ if ((servertype == "auto" || servertype == "office365") && user.split("@").length != 2) {
+ alert(TbSync.getString("autodiscover.NeedEmail", "eas"))
+ return;
+ }
+
+ this.validating = true;
+ let error = "";
+
+ //document.getElementById("tbsync.newaccount.wizard").canRewind = false;
+ document.getElementById("tbsync.error").hidden = true;
+ document.getElementById("tbsync.newaccount.wizard").getButton("cancel").disabled = true;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = true;
+ document.getElementById("tbsync.newaccount.name").disabled = true;
+ document.getElementById("tbsync.newaccount.user").disabled = true;
+ document.getElementById("tbsync.newaccount.password").disabled = true;
+ document.getElementById("tbsync.newaccount.servertype").disabled = true;
+
+ tbSyncEasNewAccount.startTime = Date.now();
+ tbSyncEasNewAccount.updateAutodiscoverStatus();
+ document.getElementById("tbsync.spinner").hidden = false;
+
+ //do autodiscover
+ if (servertype == "office365" || servertype == "auto") {
+ let updateTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
+ updateTimer.initWithCallback({ notify: function () { tbSyncEasNewAccount.updateAutodiscoverStatus() } }, 1000, 3);
+
+ if (servertype == "office365") {
+ let v2 = await eas.network.getServerConnectionViaAutodiscoverV2JsonRequest(
+ accountname,
+ user,
+ "https://autodiscover-s.outlook.com/autodiscover/autodiscover.json?Email=" + encodeURIComponent(user) + "&Protocol=ActiveSync",
+ );
+ let oauthData = eas.network.getOAuthObj({ host: v2.server, user, accountname, servertype });
+ if (oauthData) {
+ // ask for token
+ document.getElementById("tbsync.spinner").hidden = true;
+ let _rv = {};
+ if (await oauthData.asyncConnect(_rv)) {
+ password = _rv.tokens;
+ } else {
+ error = TbSync.getString("status." + _rv.error, "eas");
+ }
+ document.getElementById("tbsync.spinner").hidden = false;
+ url = v2.server;
+ } else {
+ error = TbSync.getString("status.404", "eas");
+ }
+ } else {
+ let result = await eas.network.getServerConnectionViaAutodiscover(
+ accountname,
+ user,
+ password,
+ tbSyncEasNewAccount.maxTimeout * 1000
+ );
+ if (result.server) {
+ user = result.user;
+ url = result.server;
+ } else {
+ error = result.error; // is a localized string
+ }
+ }
+
+ updateTimer.cancel();
+ }
+
+ //now validate the information
+ if (!error) {
+ if (!password) error = TbSync.getString("status.401", "eas");
+ }
+
+ //add if valid
+ if (!error) {
+ await tbSyncEasNewAccount.addAccount(user, password, servertype, accountname, url);
+ }
+
+ //end validation
+ document.getElementById("tbsync.newaccount.name").disabled = false;
+ document.getElementById("tbsync.newaccount.user").disabled = false;
+ document.getElementById("tbsync.newaccount.password").disabled = false;
+ document.getElementById("tbsync.newaccount.servertype").disabled = false;
+ document.getElementById("tbsync.newaccount.wizard").getButton("cancel").disabled = false;
+ document.getElementById("tbsync.newaccount.wizard").getButton("finish").disabled = false;
+ document.getElementById("tbsync.spinner").hidden = true;
+ //document.getElementById("tbsync.newaccount.wizard").canRewind = true;
+
+ this.validating = false;
+
+ //close wizard, if done
+ if (!error) {
+ document.getElementById("tbsync.newaccount.wizard").cancel();
+ } else {
+ document.getElementById("tbsync.error.message").textContent = error;
+ document.getElementById("tbsync.error").hidden = false;
+ }
+ window.sizeToContent();
+ },
+
+ updateAutodiscoverStatus: function () {
+ let offset = Math.round(((Date.now() - tbSyncEasNewAccount.startTime) / 1000));
+ let timeout = (offset > 2) ? " (" + (tbSyncEasNewAccount.maxTimeout - offset) + ")" : "";
+
+ document.getElementById('tbsync.newaccount.autodiscoverstatus').value = TbSync.getString("autodiscover.Querying", "eas") + timeout;
+ },
+
+ async addAccount(user, password, servertype, accountname, url) {
+ let newAccountEntry = this.providerData.getDefaultAccountEntries();
+ newAccountEntry.user = user;
+ newAccountEntry.servertype = servertype;
+
+ if (url) {
+ //if no protocoll is given, prepend "https://"
+ if (url.substring(0, 4) != "http" || url.indexOf("://") == -1) url = "https://" + url.split("://").join("/");
+ newAccountEntry.host = eas.network.stripAutodiscoverUrl(url);
+ newAccountEntry.https = (url.substring(0, 5) == "https");
+ }
+
+ // Add the new account.
+ let newAccountData = this.providerData.addAccount(accountname, newAccountEntry);
+ await eas.network.getAuthData(newAccountData).updateLoginData(user, password);
+
+ window.close();
+ }
+};
diff -Nru eas4tbsync-4.11/content/manager/createAccount.xhtml eas4tbsync-4.17/content/manager/createAccount.xhtml
--- eas4tbsync-4.11/content/manager/createAccount.xhtml 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/manager/createAccount.xhtml 2025-05-15 11:21:20.000000000 +0000
@@ -1,97 +1,97 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_add.description__
-
-
-
-
-
-
- __EAS4TBSYNCMSG_servertype.description.auto__
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_servertype.description.custom__
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_servertype.description.office365__
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_add.description__
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_servertype.description.auto__
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_servertype.description.custom__
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_servertype.description.office365__
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -Nru eas4tbsync-4.11/content/manager/editAccountOverlay.js eas4tbsync-4.17/content/manager/editAccountOverlay.js
--- eas4tbsync-4.11/content/manager/editAccountOverlay.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/manager/editAccountOverlay.js 2019-08-26 15:50:48.000000000 +0000
@@ -1,56 +1,56 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-const eas = TbSync.providers.eas;
-
-var tbSyncEditAccountOverlay = {
-
- onload: function (window, accountData) {
- this.accountData = accountData;
-
- // special treatment for configuration label, which is a permanent setting and will not change by switching modes
- let configlabel = window.document.getElementById("tbsync.accountsettings.label.config");
- if (configlabel) {
- configlabel.setAttribute("value", TbSync.getString("config.custom", "eas"));
- }
- },
-
- stripHost: function (document) {
- let host = document.getElementById('tbsync.AccountPropertys.pref.host').value;
- if (host.indexOf("https://") == 0) {
- host = host.replace("https://","");
- document.getElementById('tbsync.AccountPropertys.pref.https').checked = true;
- this.accountData.setAccountProperty("https", true);
- } else if (host.indexOf("http://") == 0) {
- host = host.replace("http://","");
- document.getElementById('tbsync.AccountPropertys.pref.https').checked = false;
- this.accountData.setAccountProperty("https", false);
- }
-
- while (host.endsWith("/")) { host = host.slice(0,-1); }
- document.getElementById('tbsync.AccountPropertys.pref.host').value = host
- this.accountData.setAccountProperty("host", host);
- },
-
- deleteFolder: function() {
- let folderList = document.getElementById("tbsync.accountsettings.folderlist");
- if (folderList.selectedItem !== null && !folderList.disabled) {
- let folderData = folderList.selectedItem.folderData;
-
- //only trashed folders can be purged (for example O365 does not show deleted folders but also does not allow to purge them)
- if (!eas.tools.parentIsTrash(folderData)) return;
-
- if (folderData.getFolderProperty("selected")) window.alert(TbSync.getString("deletefolder.notallowed::" + folderData.getFolderProperty("foldername"), "eas"));
- else if (window.confirm(TbSync.getString("deletefolder.confirm::" + folderData.getFolderProperty("foldername"), "eas"))) {
- folderData.sync({syncList: false, syncJob: "deletefolder"});
- }
- }
- }
-};
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const eas = TbSync.providers.eas;
+
+var tbSyncEditAccountOverlay = {
+
+ onload: function (window, accountData) {
+ this.accountData = accountData;
+
+ // special treatment for configuration label, which is a permanent setting and will not change by switching modes
+ let configlabel = window.document.getElementById("tbsync.accountsettings.label.config");
+ if (configlabel) {
+ configlabel.setAttribute("value", TbSync.getString("config.custom", "eas"));
+ }
+ },
+
+ stripHost: function (document) {
+ let host = document.getElementById('tbsync.AccountPropertys.pref.host').value;
+ if (host.indexOf("https://") == 0) {
+ host = host.replace("https://","");
+ document.getElementById('tbsync.AccountPropertys.pref.https').checked = true;
+ this.accountData.setAccountProperty("https", true);
+ } else if (host.indexOf("http://") == 0) {
+ host = host.replace("http://","");
+ document.getElementById('tbsync.AccountPropertys.pref.https').checked = false;
+ this.accountData.setAccountProperty("https", false);
+ }
+
+ while (host.endsWith("/")) { host = host.slice(0,-1); }
+ document.getElementById('tbsync.AccountPropertys.pref.host').value = host
+ this.accountData.setAccountProperty("host", host);
+ },
+
+ deleteFolder: function() {
+ let folderList = document.getElementById("tbsync.accountsettings.folderlist");
+ if (folderList.selectedItem !== null && !folderList.disabled) {
+ let folderData = folderList.selectedItem.folderData;
+
+ //only trashed folders can be purged (for example O365 does not show deleted folders but also does not allow to purge them)
+ if (!eas.tools.parentIsTrash(folderData)) return;
+
+ if (folderData.getFolderProperty("selected")) window.alert(TbSync.getString("deletefolder.notallowed::" + folderData.getFolderProperty("foldername"), "eas"));
+ else if (window.confirm(TbSync.getString("deletefolder.confirm::" + folderData.getFolderProperty("foldername"), "eas"))) {
+ folderData.sync({syncList: false, syncJob: "deletefolder"});
+ }
+ }
+ }
+};
diff -Nru eas4tbsync-4.11/content/manager/editAccountOverlay.xhtml eas4tbsync-4.17/content/manager/editAccountOverlay.xhtml
--- eas4tbsync-4.11/content/manager/editAccountOverlay.xhtml 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/manager/editAccountOverlay.xhtml 2025-05-15 11:21:20.000000000 +0000
@@ -1,154 +1,154 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_manager.lockedsettings.description__
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_pref.seperator.description__
-
-
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_pref.synclimit.description__
-
-
-
-
-
-
-
-
-
-
-
- __EAS4TBSYNCMSG_manager.lockedsettings.description__
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_manager.lockedsettings.description__
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_pref.seperator.description__
+
+
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_pref.synclimit.description__
+
+
+
+
+
+
+
+
+
+
+
+ __EAS4TBSYNCMSG_manager.lockedsettings.description__
+
+
+
+
+
+
diff -Nru eas4tbsync-4.11/content/provider.js eas4tbsync-4.17/content/provider.js
--- eas4tbsync-4.11/content/provider.js 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/provider.js 2025-05-15 11:21:20.000000000 +0000
@@ -1,733 +1,744 @@
-/*
- * This file is part of EAS-4-TbSync.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-"use strict";
-
-var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
-var { MailServices } = ChromeUtils.import("resource:///modules/MailServices.jsm");
-
-// Every object in here will be loaded into TbSync.providers..
-const eas = TbSync.providers.eas;
-
-eas.prefs = Services.prefs.getBranch("extensions.eas4tbsync.");
-
-//use flags instead of strings to avoid errors due to spelling errors
-eas.flags = Object.freeze({
- allowEmptyResponse: true,
-});
-
-eas.windowsToIanaTimezoneMap = {};
-eas.ianaToWindowsTimezoneMap = {};
-eas.cachedTimezoneData = null;
-eas.defaultTimezoneInfo = null;
-eas.defaultTimezone = null;
-eas.utcTimezone = null;
-
-
-/**
- * Implementing the TbSync interface for external provider extensions.
- */
-var Base = class {
- /**
- * Called during load of external provider extension to init provider.
- */
- static async load() {
- // Set default prefs
- let branch = Services.prefs.getDefaultBranch("extensions.eas4tbsync.");
- branch.setIntPref("timeout", 90000);
- branch.setIntPref("maxitems", 50);
- branch.setBoolPref("msTodoCompat", false);
- branch.setCharPref("clientID.type", "TbSync");
- branch.setCharPref("clientID.useragent", "Thunderbird ActiveSync");
- branch.setCharPref("oauth.clientID", "");
-
- eas.defaultTimezone = null;
- eas.utcTimezone = null;
- eas.defaultTimezoneInfo = null;
- eas.windowsToIanaTimezoneMap = {};
- eas.openWindows = {};
-
- try {
- // Create a basic error info (no accountname or foldername, just the provider)
- let eventLogInfo = new TbSync.EventLogInfo("eas");
-
- //get timezone info of default timezone (old cal. without dtz are depricated)
- eas.defaultTimezone = (TbSync.lightning.cal.dtz && TbSync.lightning.cal.dtz.defaultTimezone) ? TbSync.lightning.cal.dtz.defaultTimezone : TbSync.lightning.cal.calendarDefaultTimezone();
- eas.utcTimezone = (TbSync.lightning.cal.dtz && TbSync.lightning.cal.dtz.UTC) ? TbSync.lightning.cal.dtz.UTC : TbSync.lightning.cal.UTC();
- if (eas.defaultTimezone && eas.defaultTimezone.icalComponent) {
- TbSync.eventlog.add("info", eventLogInfo, "Default timezone has been found.");
- } else {
- TbSync.eventlog.add("info", eventLogInfo, "Default timezone is not defined, using UTC!");
- eas.defaultTimezone = eas.utcTimezone;
- }
-
- eas.defaultTimezoneInfo = eas.tools.getTimezoneInfo(eas.defaultTimezone);
- if (!eas.defaultTimezoneInfo) {
- TbSync.eventlog.add("info", eventLogInfo, "Could not create defaultTimezoneInfo");
- }
-
- //get windows timezone data from CSV
- let aliasData = await eas.tools.fetchFile("chrome://eas4tbsync/content/timezonedata/Aliases.csv");
- let aliasNames = {};
- for (let i = 0; i cannot be mapped to any Exchange timezone.");
- }
- }
-
- //If an EAS calendar is currently NOT associated with an email identity, try to associate,
- //but do not change any explicitly set association
- // - A) find email identity and associate (which sets organizer to that user identity)
- // - B) overwrite default organizer with current best guess
- //TODO: Do this after email accounts changed, not only on restart?
- let providerData = new TbSync.ProviderData("eas");
- let folders = providerData.getFolders({"selected": true, "type": ["8","13"]});
- for (let folder of folders) {
- let manager = TbSync.lightning.cal.manager;
- let calendar = manager.getCalendarById(folder.getFolderProperty("target"));
- if (calendar && calendar.getProperty("imip.identity.key") == "") {
- //is there an email identity for this eas account?
- let authData = eas.network.getAuthData(folder.accountData);
-
- let key = eas.tools.getIdentityKey(authData.user);
- if (key === "") { //TODO: Do this even after manually switching to NONE, not only on restart?
- //set transient calendar organizer settings based on current best guess and
- calendar.setProperty("organizerId", TbSync.lightning.cal.email.prependMailTo(authData.user));
- calendar.setProperty("organizerCN", calendar.getProperty("fallbackOrganizerName"));
- } else {
- //force switch to found identity
- calendar.setProperty("imip.identity.key", key);
- }
- }
- }
- } catch(e) {
- Components.utils.reportError(e);
- }
- }
-
-
- /**
- * Called during unload of external provider extension to unload provider.
- */
- static async unload() {
- // Close all open windows of this provider.
- for (let id in eas.openWindows) {
- if (eas.openWindows.hasOwnProperty(id)) {
- try {
- eas.openWindows[id].close();
- } catch(e) {
- //NOOP
- }
- }
- }
- }
-
-
- /**
- * Returns string for the name of provider for the add account menu.
- */
- static getProviderName() {
- return "Exchange ActiveSync";
- }
-
-
- /**
- * Returns version of the TbSync API this provider is using
- */
- static getApiVersion() { return "2.5"; }
-
-
- /**
- * Returns location of a provider icon.
- */
- static getProviderIcon(size, accountData = null) {
- let base = (accountData && accountData.getAccountProperty("servertype") == "office365") ? "365_" : "eas";
-
- switch (size) {
- case 16:
- return "chrome://eas4tbsync/content/skin/" + base + "16.png";
- case 32:
- return "chrome://eas4tbsync/content/skin/" + base + "32.png";
- default :
- return "chrome://eas4tbsync/content/skin/" + base + "64.png";
- }
- }
-
-
- /**
- * Returns a list of sponsors, they will be sorted by the index
- */
- static getSponsors() {
- return {
- "Schiessl, Michael 1" : {name: "Michael Schiessl", description: "Tine 2.0", icon: "", link: "" },
- "Schiessl, Michael 2" : {name: "Michael Schiessl", description: " Exchange 2007", icon: "", link: "" },
- "netcup GmbH" : {name: "netcup GmbH", description : "SOGo", icon: "chrome://eas4tbsync/content/skin/sponsors/netcup.png", link: "http://www.netcup.de/" },
- "nethinks GmbH" : {name: "nethinks GmbH", description : "Zarafa", icon: "chrome://eas4tbsync/content/skin/sponsors/nethinks.png", link: "http://www.nethinks.com/" },
- "Jau, Stephan" : {name: "Stephan Jau", description: "Horde", icon: "", link: "" },
- "Zavar " : {name: "Zavar", description: "Zoho", icon: "", link: "" },
- };
- }
-
-
- /**
- * Returns the url of a page with details about contributors (used in the manager UI)
- */
- static getContributorsUrl() {
- return "https://github.com/jobisoft/EAS-4-TbSync/blob/master/CONTRIBUTORS.md";
- }
-
-
- /**
- * Returns the email address of the maintainer (used for bug reports).
- */
- static getMaintainerEmail() {
- return "john.bieling@gmx.de";
- }
-
-
- /**
- * Returns URL of the new account window.
- *
- * The URL will be opened via openDialog(), when the user wants to create a
- * new account of this provider.
- */
- static getCreateAccountWindowUrl() {
- return "chrome://eas4tbsync/content/manager/createAccount.xhtml";
- }
-
-
- /**
- * Returns overlay XUL URL of the edit account dialog
- * (chrome://tbsync/content/manager/editAccount.xhtml)
- */
- static getEditAccountOverlayUrl() {
- return "chrome://eas4tbsync/content/manager/editAccountOverlay.xhtml";
- }
-
-
- /**
- * Return object which contains all possible fields of a row in the
- * accounts database with the default value if not yet stored in the
- * database.
- */
- static getDefaultAccountEntries() {
- let row = {
- "policykey" : "0",
- "foldersynckey" : "0",
- "deviceId" : eas.tools.getNewDeviceId(),
- "asversionselected" : "auto",
- "asversion" : "",
- "host" : "",
- "user" : "",
- "servertype" : "",
- "seperator" : "10",
- "https" : true,
- "provision" : false,
- "displayoverride" : false,
- "lastEasOptionsUpdate":"0",
- "allowedEasVersions": "",
- "allowedEasCommands": "",
- "useragent": eas.prefs.getCharPref("clientID.useragent"),
- "devicetype": eas.prefs.getCharPref("clientID.type"),
- "synclimit" : "7",
- };
- return row;
- }
-
-
- /**
- * Return object which contains all possible fields of a row in the folder
- * database with the default value if not yet stored in the database.
- */
- static getDefaultFolderEntries() {
- let folder = {
- "type" : "",
- "synckey" : "",
- "target" : "",
- "targetColor" : "",
- "targetName" : "",
- "parentID" : "0",
- "serverID" : "",
- };
- return folder;
- }
-
-
- /**
- * Is called everytime an account of this provider is enabled in the
- * manager UI.
- */
- static onEnableAccount(accountData) {
- accountData.resetAccountProperty("policykey");
- accountData.resetAccountProperty("foldersynckey");
- accountData.resetAccountProperty("lastEasOptionsUpdate");
- accountData.resetAccountProperty("lastsynctime");
- }
-
-
- /**
- * Is called everytime an account of this provider is disabled in the
- * manager UI.
- *
- * @param accountData [in] AccountData
- */
- static onDisableAccount(accountData) {
- }
-
-
- /**
- * Is called everytime an account of this provider is deleted in the
- * manager UI.
- */
- static onDeleteAccount(accountData) {
- eas.network.getAuthData(accountData).removeLoginData();
- }
-
-
- /**
- * Returns all folders of the account, sorted in the desired order.
- * The most simple implementation is to return accountData.getAllFolders();
- */
- static getSortedFolders(accountData) {
- let allowedTypesOrder = ["9","14","8","13","7","15"];
-
- function getIdChain (aServerID) {
- let serverID = aServerID;
- let chain = [];
- let folder;
- let rootType = "";
-
- // create sort string so that child folders are directly below their parent folders
- do {
- folder = accountData.getFolder("serverID", serverID);
- if (folder) {
- chain.unshift(folder.getFolderProperty("foldername"));
- serverID = folder.getFolderProperty("parentID");
- rootType = folder.getFolderProperty("type");
- }
- } while (folder && serverID != "0")
-
- // different folder types are grouped and trashed folders at the end
- let pos = allowedTypesOrder.indexOf(rootType);
- chain.unshift(pos == -1 ? "ZZZ" : pos.toString().padStart(3,"0"));
-
- return chain.join(".");
- };
-
- let toBeSorted = [];
- let folders = accountData.getAllFolders();
- for (let f of folders) {
- if (!allowedTypesOrder.includes(f.getFolderProperty("type"))) {
- continue;
- }
- toBeSorted.push({"key": getIdChain(f.getFolderProperty("serverID")), "folder": f});
- }
-
- //sort
- toBeSorted.sort(function(a,b) {
- return a.key > b.key;
- });
-
- let sortedFolders = [];
- for (let sortObj of toBeSorted) {
- sortedFolders.push(sortObj.folder);
- }
- return sortedFolders;
- }
-
-
- /**
- * Return the connection timeout for an active sync, so TbSync can append
- * a countdown to the connection timeout, while waiting for an answer from
- * the server. Only syncstates which start with "send." will trigger this.
- */
- static getConnectionTimeout(accountData) {
- return eas.prefs.getIntPref("timeout");
- }
-
-
- /**
- * Is called if TbSync needs to synchronize the folder list.
- */
- static async syncFolderList(syncData, syncJob, syncRunNr) {
- // Recommendation: Put the actual function call inside a try catch, to
- // ensure returning a proper StatusData object, regardless of what
- // happens inside that function. You may also throw custom errors
- // in that function, which have the StatusData obj attached, which
- // should be returned.
-
- try {
- await eas.sync.folderList(syncData);
- } catch (e) {
- if (e.name == "eas4tbsync") {
- return e.statusData;
- } else {
- Components.utils.reportError(e);
- // re-throw any other error and let TbSync handle it
- throw (e);
- }
- }
-
- // Fall through, if there was no error.
- return new TbSync.StatusData();
- }
-
-
- /**
- * Is called if TbSync needs to synchronize a folder.
- */
- static async syncFolder(syncData, syncJob, syncRunNr) {
- // Recommendation: Put the actual function call inside a try catch, to
- // ensure returning a proper StatusData object, regardless of what
- // happens inside that function. You may also throw custom errors
- // in that function, which have the StatusData obj attached, which
- // should be returned.
-
- try {
- switch (syncJob) {
- case "deletefolder":
- await eas.sync.deleteFolder(syncData);
- break;
- default:
- await eas.sync.singleFolder(syncData);
- }
- } catch (e) {
- if (e.name == "eas4tbsync") {
- return e.statusData;
- } else {
- Components.utils.reportError(e);
- // re-throw any other error and let TbSync handle it
- throw (e);
- }
- }
-
- // Fall through, if there was no error.
- return new TbSync.StatusData();
- }
-
-
- /**
- * Return the custom OAuth2 ClientID.
- */
- static getCustomeOauthClientID() {
- return eas.prefs.getCharPref("oauth.clientID");
- }
-}
-
-
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// * TargetData implementation
-// * Using TbSyncs advanced address book TargetData
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
-var TargetData_addressbook = class extends TbSync.addressbook.AdvancedTargetData {
- constructor(folderData) {
- super(folderData);
- }
-
- get primaryKeyField() {
- return "X-EAS-SERVERID";
- }
-
- generatePrimaryKey() {
- return TbSync.generateUUID();
- }
-
- // enable or disable changelog
- get logUserChanges() {
- return true;
- }
-
- directoryObserver(aTopic) {
- switch (aTopic) {
- case "addrbook-removed":
- case "addrbook-updated":
- //Services.console.logStringMessage("["+ aTopic + "] " + this.folderData.getFolderProperty("foldername"));
- break;
- }
- }
-
- cardObserver(aTopic, abCardItem) {
- switch (aTopic) {
- case "addrbook-contact-updated":
- case "addrbook-contact-removed":
- //Services.console.logStringMessage("["+ aTopic + "] " + abCardItem.getProperty("DisplayName"));
- break;
-
- case "addrbook-contact-created":
- {
- //Services.console.logStringMessage("["+ aTopic + "] "+ abCardItem.getProperty("DisplayName")+">");
- break;
- }
- }
- }
-
- listObserver(aTopic, abListItem, abListMember) {
- switch (aTopic) {
- case "addrbook-list-member-added":
- case "addrbook-list-member-removed":
- //Services.console.logStringMessage("["+ aTopic + "] MemberName: " + abListMember.getProperty("DisplayName"));
- break;
-
- case "addrbook-list-removed":
- case "addrbook-list-updated":
- //Services.console.logStringMessage("["+ aTopic + "] ListName: " + abListItem.getProperty("ListName"));
- break;
-
- case "addrbook-list-created":
- //Services.console.logStringMessage("["+ aTopic + "] ListName: "+abListItem.getProperty("ListName")+">");
- break;
- }
- }
-
- async createAddressbook(newname) {
- // https://searchfox.org/comm-central/source/mailnews/addrbook/src/nsDirPrefs.h
- let dirPrefId = MailServices.ab.newAddressBook(newname, "", 101);
- let directory = MailServices.ab.getDirectoryFromId(dirPrefId);
-
- eas.sync.resetFolderSyncInfo(this.folderData);
-
- if (directory && directory instanceof Components.interfaces.nsIAbDirectory && directory.dirPrefId == dirPrefId) {
- directory.setStringValue("tbSyncIcon", "eas" + (this.folderData.accountData.getAccountProperty("servertype") == "office365" ? "_365" : ""));
- directory.setStringValue("tbSyncRevision", "2");
- return directory;
- }
- return null;
- }
-}
-
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// * TargetData implementation
-// * Using TbSyncs advanced calendar TargetData
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
-var TargetData_calendar = class extends TbSync.lightning.AdvancedTargetData {
- constructor(folderData) {
- super(folderData);
- }
-
- // The calendar target does not support a custom primaryKeyField, because
- // the lightning implementation only allows to search for items via UID.
- // Like the addressbook target, the calendar target item element has a
- // primaryKey getter/setter which - however - only works on the UID.
-
- // enable or disable changelog
- get logUserChanges() {
- return true;
- }
-
- calendarObserver(aTopic, tbCalendar, aPropertyName, aPropertyValue, aOldPropertyValue) {
- switch (aTopic) {
- case "onCalendarPropertyChanged":
- //Services.console.logStringMessage("["+ aTopic + "] " + tbCalendar.calendar.name + " : " + aPropertyName);
- break;
-
- case "onCalendarDeleted":
- case "onCalendarPropertyDeleted":
- //Services.console.logStringMessage("["+ aTopic + "] " +tbCalendar.calendar.name);
- break;
- }
- }
-
- itemObserver(aTopic, tbItem, tbOldItem) {
- switch (aTopic) {
- case "onAddItem":
- case "onModifyItem":
- case "onDeleteItem":
- //Services.console.logStringMessage("["+ aTopic + "] " + tbItem.nativeItem.title);
- break;
- }
- }
-
- async createCalendar(newname) {
- let calManager = TbSync.lightning.cal.manager;
-
- //Create the new standard calendar with a unique name
- let newCalendar = calManager.createCalendar("storage", Services.io.newURI("moz-storage-calendar://"));
- newCalendar.id = TbSync.lightning.cal.getUUID();
- newCalendar.name = newname;
-
- eas.sync.resetFolderSyncInfo(this.folderData);
-
- newCalendar.setProperty("color", this.folderData.getFolderProperty("targetColor"));
- newCalendar.setProperty("relaxedMode", true); //sometimes we get "generation too old for modifyItem", check can be disabled with relaxedMode
- // removed in TB78, as it seems to not fully enable the calendar, if present before registering
- // https://searchfox.org/comm-central/source/calendar/base/content/calendar-management.js#385
- //newCalendar.setProperty("calendar-main-in-composite",true);
- newCalendar.setProperty("readOnly", this.folderData.getFolderProperty("downloadonly"));
-
- switch (this.folderData.getFolderProperty("type")) {
- case "8": //event
- case "13":
- newCalendar.setProperty("capabilities.tasks.supported", false);
- newCalendar.setProperty("capabilities.events.supported", true);
- break;
- case "7": //todo
- case "15":
- newCalendar.setProperty("capabilities.tasks.supported", true);
- newCalendar.setProperty("capabilities.events.supported", false);
- break;
- default:
- newCalendar.setProperty("capabilities.tasks.supported", false);
- newCalendar.setProperty("capabilities.events.supported", false);
- }
-
- calManager.registerCalendar(newCalendar);
-
- let authData = eas.network.getAuthData(this.folderData.accountData);
-
- //is there an email identity we can associate this calendar to?
- //getIdentityKey returns "" if none found, which removes any association
- let key = eas.tools.getIdentityKey(authData.user);
- newCalendar.setProperty("fallbackOrganizerName", newCalendar.getProperty("organizerCN"));
- newCalendar.setProperty("imip.identity.key", key);
- if (key === "") {
- //there is no matching email identity - use current default value as best guess and remove association
- //use current best guess
- newCalendar.setProperty("organizerCN", newCalendar.getProperty("fallbackOrganizerName"));
- newCalendar.setProperty("organizerId", TbSync.lightning.cal.email.prependMailTo(authData.user));
- }
-
- return newCalendar;
- }
-}
-
-
-
-
-
-/**
- * This provider is implementing the StandardFolderList class instead of
- * the FolderList class.
- */
-var StandardFolderList = class {
- /**
- * Is called before the context menu of the folderlist is shown, allows to
- * show/hide custom menu options based on selected folder. During an active
- * sync, folderData will be null.
- */
- static onContextMenuShowing(window, folderData) {
- let hideContextMenuDelete = true;
- if (folderData !== null) {
- //if a folder in trash is selected, also show ContextMenuDelete (but only if FolderDelete is allowed)
- if (eas.tools.parentIsTrash(folderData) && folderData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("FolderDelete")) {
- hideContextMenuDelete = false;
- window.document.getElementById("TbSync.eas.FolderListContextMenuDelete").label = TbSync.getString("deletefolder.menuentry::" + folderData.getFolderProperty("foldername"), "eas");
- }
- }
- window.document.getElementById("TbSync.eas.FolderListContextMenuDelete").hidden = hideContextMenuDelete;
- }
-
-
- /**
- * Return the icon used in the folderlist to represent the different folder
- * types.
- */
- static getTypeImage(folderData) {
- let src = "";
- switch (folderData.getFolderProperty("type")) {
- case "9":
- case "14":
- src = "contacts16.png";
- break;
- case "8":
- case "13":
- src = "calendar16.png";
- break;
- case "7":
- case "15":
- src = "todo16.png";
- break;
- }
- return "chrome://tbsync/content/skin/" + src;
- }
-
-
- /**
- * Return the name of the folder shown in the folderlist.
- */
- static getFolderDisplayName(folderData) {
- let folderName = folderData.getFolderProperty("foldername");
- if (eas.tools.parentIsTrash(folderData)) folderName = TbSync.getString("recyclebin", "eas") + " | " + folderName;
- return folderName;
- }
-
-
- /**
- * Return the attributes for the ACL RO (readonly menu element per folder.
- * (label, disabled, hidden, style, ...)
- *
- * Return a list of attributes and their values If both (RO+RW) do
- * not return any attributes, the ACL menu is not displayed at all.
- */
- static getAttributesRoAcl(folderData) {
- return {
- label: TbSync.getString("acl.readonly", "eas"),
- };
- }
-
-
- /**
- * Return the attributes for the ACL RW (readwrite) menu element per folder.
- * (label, disabled, hidden, style, ...)
- *
- * Return a list of attributes and their values. If both (RO+RW) do
- * not return any attributes, the ACL menu is not displayed at all.
- */
- static getAttributesRwAcl(folderData) {
- return {
- label: TbSync.getString("acl.readwrite", "eas"),
- }
- }
-}
-
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/network.js", this, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/wbxmltools.js", this, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/xmltools.js", this, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/tools.js", this, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/sync.js", this, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/contactsync.js", this.sync, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/calendarsync.js", this.sync, "UTF-8");
-Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/tasksync.js", this.sync, "UTF-8");
+/*
+ * This file is part of EAS-4-TbSync.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+var { MailServices } = ChromeUtils.importESModule(
+ "resource:///modules/MailServices.sys.mjs"
+);
+
+var tbsyncExtension = ExtensionParent.GlobalManager.getExtension(
+ "tbsync@jobisoft.de"
+);
+var { TbSync } = ChromeUtils.importESModule(
+ `chrome://tbsync/content/tbsync.sys.mjs?${tbsyncExtension.manifest.version}`
+);
+
+// Every object in here will be loaded into TbSync.providers..
+const eas = TbSync.providers.eas;
+
+eas.prefs = Services.prefs.getBranch("extensions.eas4tbsync.");
+
+//use flags instead of strings to avoid errors due to spelling errors
+eas.flags = Object.freeze({
+ allowEmptyResponse: true,
+});
+
+eas.windowsToIanaTimezoneMap = {};
+eas.ianaToWindowsTimezoneMap = {};
+eas.cachedTimezoneData = null;
+eas.defaultTimezoneInfo = null;
+eas.defaultTimezone = null;
+eas.utcTimezone = null;
+
+
+/**
+ * Implementing the TbSync interface for external provider extensions.
+ */
+var Base = class {
+ /**
+ * Called during load of external provider extension to init provider.
+ */
+ static async load() {
+ // Set default prefs
+ let branch = Services.prefs.getDefaultBranch("extensions.eas4tbsync.");
+ branch.setIntPref("timeout", 90000);
+ branch.setIntPref("maxitems", 50);
+ branch.setBoolPref("msTodoCompat", false);
+ branch.setCharPref("clientID.type", "TbSync");
+ branch.setCharPref("clientID.useragent", "Thunderbird ActiveSync");
+ branch.setCharPref("oauth.clientID", "");
+
+ eas.defaultTimezone = null;
+ eas.utcTimezone = null;
+ eas.defaultTimezoneInfo = null;
+ eas.windowsToIanaTimezoneMap = {};
+ eas.openWindows = {};
+
+ try {
+ // Create a basic error info (no accountname or foldername, just the provider)
+ let eventLogInfo = new TbSync.EventLogInfo("eas");
+
+ //get timezone info of default timezone (old cal. without dtz are depricated)
+ eas.defaultTimezone = (TbSync.lightning.cal.dtz && TbSync.lightning.cal.dtz.defaultTimezone) ? TbSync.lightning.cal.dtz.defaultTimezone : TbSync.lightning.cal.calendarDefaultTimezone();
+ eas.utcTimezone = (TbSync.lightning.cal.dtz && TbSync.lightning.cal.dtz.UTC) ? TbSync.lightning.cal.dtz.UTC : TbSync.lightning.cal.UTC();
+ if (eas.defaultTimezone && eas.defaultTimezone.icalComponent) {
+ TbSync.eventlog.add("info", eventLogInfo, "Default timezone has been found.");
+ } else {
+ TbSync.eventlog.add("info", eventLogInfo, "Default timezone is not defined, using UTC!");
+ eas.defaultTimezone = eas.utcTimezone;
+ }
+
+ eas.defaultTimezoneInfo = eas.tools.getTimezoneInfo(eas.defaultTimezone);
+ if (!eas.defaultTimezoneInfo) {
+ TbSync.eventlog.add("info", eventLogInfo, "Could not create defaultTimezoneInfo");
+ }
+
+ //get windows timezone data from CSV
+ let aliasData = await eas.tools.fetchFile("chrome://eas4tbsync/content/timezonedata/Aliases.csv");
+ let aliasNames = {};
+ for (let i = 0; i < aliasData.length; i++) {
+ let lData = aliasData[i].split(",");
+ if (lData.length < 2) continue;
+ aliasNames[lData[0].toString().trim()] = lData[1].toString().trim().split(" ");
+ }
+
+ let csvData = await eas.tools.fetchFile("chrome://eas4tbsync/content/timezonedata/WindowsTimezone.csv");
+ for (let i = 0; i < csvData.length; i++) {
+ let lData = csvData[i].split(",");
+ if (lData.length < 3) continue;
+
+ let windowsZoneName = lData[0].toString().trim();
+ let zoneType = lData[1].toString().trim();
+ let ianaZoneName = lData[2].toString().trim();
+
+ if (zoneType == "001") eas.windowsToIanaTimezoneMap[windowsZoneName] = ianaZoneName;
+ if (ianaZoneName == eas.defaultTimezoneInfo.std.id) eas.defaultTimezoneInfo.std.windowsZoneName = windowsZoneName;
+
+ // build the revers map as well, which is many-to-one, grap iana aliases from the csvData and from the aliasData
+ // 1. multiple iana zones map to the same windows zone
+ let ianaZones = ianaZoneName.split(" ");
+ for (let ianaZone of ianaZones) {
+ eas.ianaToWindowsTimezoneMap[ianaZone] = windowsZoneName;
+ if (aliasNames.hasOwnProperty(ianaZone)) {
+ for (let aliasName of aliasNames[ianaZone]) {
+ // 2. multiple iana zonescan be an alias to a main iana zone
+ eas.ianaToWindowsTimezoneMap[aliasName] = windowsZoneName;
+ }
+ }
+ }
+ }
+
+ let tzService = TbSync.lightning.cal.timezoneService;
+ for (let timezoneId of tzService.timezoneIds) {
+ if (!eas.ianaToWindowsTimezoneMap[timezoneId]) {
+ TbSync.eventlog.add("info", eventLogInfo, "The IANA timezone <" + timezoneId + "> cannot be mapped to any Exchange timezone.");
+ }
+ }
+
+ //If an EAS calendar is currently NOT associated with an email identity, try to associate,
+ //but do not change any explicitly set association
+ // - A) find email identity and associate (which sets organizer to that user identity)
+ // - B) overwrite default organizer with current best guess
+ //TODO: Do this after email accounts changed, not only on restart?
+ let providerData = new TbSync.ProviderData("eas");
+ let folders = providerData.getFolders({ "selected": true, "type": ["8", "13"] });
+ for (let folder of folders) {
+ let manager = TbSync.lightning.cal.manager;
+ let calendar = manager.getCalendarById(folder.getFolderProperty("target"));
+ if (calendar && calendar.getProperty("imip.identity.key") == "") {
+ //is there an email identity for this eas account?
+ let authData = eas.network.getAuthData(folder.accountData);
+
+ let key = eas.tools.getIdentityKey(authData.user);
+ if (key === "") { //TODO: Do this even after manually switching to NONE, not only on restart?
+ //set transient calendar organizer settings based on current best guess and
+ calendar.setProperty("organizerId", TbSync.lightning.cal.email.prependMailTo(authData.user));
+ calendar.setProperty("organizerCN", calendar.getProperty("fallbackOrganizerName"));
+ } else {
+ //force switch to found identity
+ calendar.setProperty("imip.identity.key", key);
+ }
+ }
+ }
+ } catch (e) {
+ Components.utils.reportError(e);
+ }
+ }
+
+
+ /**
+ * Called during unload of external provider extension to unload provider.
+ */
+ static async unload() {
+ // Close all open windows of this provider.
+ for (let id in eas.openWindows) {
+ if (eas.openWindows.hasOwnProperty(id)) {
+ try {
+ eas.openWindows[id].close();
+ } catch (e) {
+ //NOOP
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns string for the name of provider for the add account menu.
+ */
+ static getProviderName() {
+ return "Exchange ActiveSync";
+ }
+
+
+ /**
+ * Returns version of the TbSync API this provider is using
+ */
+ static getApiVersion() { return "2.5"; }
+
+
+ /**
+ * Returns location of a provider icon.
+ */
+ static getProviderIcon(size, accountData = null) {
+ let base = (accountData && accountData.getAccountProperty("servertype") == "office365") ? "365_" : "eas";
+
+ switch (size) {
+ case 16:
+ return "chrome://eas4tbsync/content/skin/" + base + "16.png";
+ case 32:
+ return "chrome://eas4tbsync/content/skin/" + base + "32.png";
+ default:
+ return "chrome://eas4tbsync/content/skin/" + base + "64.png";
+ }
+ }
+
+
+ /**
+ * Returns a list of sponsors, they will be sorted by the index
+ */
+ static getSponsors() {
+ return {
+ "Schiessl, Michael 1": { name: "Michael Schiessl", description: "Tine 2.0", icon: "", link: "" },
+ "Schiessl, Michael 2": { name: "Michael Schiessl", description: " Exchange 2007", icon: "", link: "" },
+ "netcup GmbH": { name: "netcup GmbH", description: "SOGo", icon: "chrome://eas4tbsync/content/skin/sponsors/netcup.png", link: "http://www.netcup.de/" },
+ "nethinks GmbH": { name: "nethinks GmbH", description: "Zarafa", icon: "chrome://eas4tbsync/content/skin/sponsors/nethinks.png", link: "http://www.nethinks.com/" },
+ "Jau, Stephan": { name: "Stephan Jau", description: "Horde", icon: "", link: "" },
+ "Zavar ": { name: "Zavar", description: "Zoho", icon: "", link: "" },
+ };
+ }
+
+
+ /**
+ * Returns the url of a page with details about contributors (used in the manager UI)
+ */
+ static getContributorsUrl() {
+ return "https://github.com/jobisoft/EAS-4-TbSync/blob/master/CONTRIBUTORS.md";
+ }
+
+
+ /**
+ * Returns the email address of the maintainer (used for bug reports).
+ */
+ static getMaintainerEmail() {
+ return "john.bieling@gmx.de";
+ }
+
+
+ /**
+ * Returns URL of the new account window.
+ *
+ * The URL will be opened via openDialog(), when the user wants to create a
+ * new account of this provider.
+ */
+ static getCreateAccountWindowUrl() {
+ return "chrome://eas4tbsync/content/manager/createAccount.xhtml";
+ }
+
+
+ /**
+ * Returns overlay XUL URL of the edit account dialog
+ * (chrome://tbsync/content/manager/editAccount.xhtml)
+ */
+ static getEditAccountOverlayUrl() {
+ return "chrome://eas4tbsync/content/manager/editAccountOverlay.xhtml";
+ }
+
+
+ /**
+ * Return object which contains all possible fields of a row in the
+ * accounts database with the default value if not yet stored in the
+ * database.
+ */
+ static getDefaultAccountEntries() {
+ let row = {
+ "policykey": "0",
+ "foldersynckey": "0",
+ "deviceId": eas.tools.getNewDeviceId(),
+ "asversionselected": "auto",
+ "asversion": "",
+ "host": "",
+ "user": "",
+ "servertype": "",
+ "seperator": "10",
+ "https": true,
+ "provision": false,
+ "displayoverride": false,
+ "lastEasOptionsUpdate": "0",
+ "allowedEasVersions": "",
+ "allowedEasCommands": "",
+ "useragent": eas.prefs.getCharPref("clientID.useragent"),
+ "devicetype": eas.prefs.getCharPref("clientID.type"),
+ "synclimit": "7",
+ };
+ return row;
+ }
+
+
+ /**
+ * Return object which contains all possible fields of a row in the folder
+ * database with the default value if not yet stored in the database.
+ */
+ static getDefaultFolderEntries() {
+ let folder = {
+ "type": "",
+ "synckey": "",
+ "target": "",
+ "targetColor": "",
+ "targetName": "",
+ "parentID": "0",
+ "serverID": "",
+ };
+ return folder;
+ }
+
+
+ /**
+ * Is called everytime an account of this provider is enabled in the
+ * manager UI.
+ */
+ static onEnableAccount(accountData) {
+ accountData.resetAccountProperty("policykey");
+ accountData.resetAccountProperty("foldersynckey");
+ accountData.resetAccountProperty("lastEasOptionsUpdate");
+ accountData.resetAccountProperty("lastsynctime");
+ }
+
+
+ /**
+ * Is called everytime an account of this provider is disabled in the
+ * manager UI.
+ *
+ * @param accountData [in] AccountData
+ */
+ static onDisableAccount(accountData) {
+ }
+
+
+ /**
+ * Is called everytime an account of this provider is deleted in the
+ * manager UI.
+ */
+ static onDeleteAccount(accountData) {
+ eas.network.getAuthData(accountData).removeLoginData();
+ }
+
+
+ /**
+ * Returns all folders of the account, sorted in the desired order.
+ * The most simple implementation is to return accountData.getAllFolders();
+ */
+ static getSortedFolders(accountData) {
+ let allowedTypesOrder = ["9", "14", "8", "13", "7", "15"];
+
+ function getIdChain(aServerID) {
+ let serverID = aServerID;
+ let chain = [];
+ let folder;
+ let rootType = "";
+
+ // create sort string so that child folders are directly below their parent folders
+ do {
+ folder = accountData.getFolder("serverID", serverID);
+ if (folder) {
+ chain.unshift(folder.getFolderProperty("foldername"));
+ serverID = folder.getFolderProperty("parentID");
+ rootType = folder.getFolderProperty("type");
+ }
+ } while (folder && serverID != "0")
+
+ // different folder types are grouped and trashed folders at the end
+ let pos = allowedTypesOrder.indexOf(rootType);
+ chain.unshift(pos == -1 ? "ZZZ" : pos.toString().padStart(3, "0"));
+
+ return chain.join(".");
+ };
+
+ let toBeSorted = [];
+ let folders = accountData.getAllFolders();
+ for (let f of folders) {
+ if (!allowedTypesOrder.includes(f.getFolderProperty("type"))) {
+ continue;
+ }
+ toBeSorted.push({ "key": getIdChain(f.getFolderProperty("serverID")), "folder": f });
+ }
+
+ //sort
+ toBeSorted.sort(function (a, b) {
+ return a.key > b.key;
+ });
+
+ let sortedFolders = [];
+ for (let sortObj of toBeSorted) {
+ sortedFolders.push(sortObj.folder);
+ }
+ return sortedFolders;
+ }
+
+
+ /**
+ * Return the connection timeout for an active sync, so TbSync can append
+ * a countdown to the connection timeout, while waiting for an answer from
+ * the server. Only syncstates which start with "send." will trigger this.
+ */
+ static getConnectionTimeout(accountData) {
+ return eas.prefs.getIntPref("timeout");
+ }
+
+
+ /**
+ * Is called if TbSync needs to synchronize the folder list.
+ */
+ static async syncFolderList(syncData, syncJob, syncRunNr) {
+ // Recommendation: Put the actual function call inside a try catch, to
+ // ensure returning a proper StatusData object, regardless of what
+ // happens inside that function. You may also throw custom errors
+ // in that function, which have the StatusData obj attached, which
+ // should be returned.
+
+ try {
+ await eas.sync.folderList(syncData);
+ } catch (e) {
+ if (e.name == "eas4tbsync") {
+ return e.statusData;
+ } else {
+ Components.utils.reportError(e);
+ // re-throw any other error and let TbSync handle it
+ throw (e);
+ }
+ }
+
+ // Fall through, if there was no error.
+ return new TbSync.StatusData();
+ }
+
+
+ /**
+ * Is called if TbSync needs to synchronize a folder.
+ */
+ static async syncFolder(syncData, syncJob, syncRunNr) {
+ // Recommendation: Put the actual function call inside a try catch, to
+ // ensure returning a proper StatusData object, regardless of what
+ // happens inside that function. You may also throw custom errors
+ // in that function, which have the StatusData obj attached, which
+ // should be returned.
+
+ try {
+ switch (syncJob) {
+ case "deletefolder":
+ await eas.sync.deleteFolder(syncData);
+ break;
+ default:
+ await eas.sync.singleFolder(syncData);
+ }
+ } catch (e) {
+ if (e.name == "eas4tbsync") {
+ return e.statusData;
+ } else {
+ Components.utils.reportError(e);
+ // re-throw any other error and let TbSync handle it
+ throw (e);
+ }
+ }
+
+ // Fall through, if there was no error.
+ return new TbSync.StatusData();
+ }
+
+
+ /**
+ * Return the custom OAuth2 ClientID.
+ */
+ static getCustomeOauthClientID() {
+ return eas.prefs.getCharPref("oauth.clientID");
+ }
+}
+
+
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// * TargetData implementation
+// * Using TbSyncs advanced address book TargetData
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+var TargetData_addressbook = class extends TbSync.addressbook.AdvancedTargetData {
+ constructor(folderData) {
+ super(folderData);
+ }
+
+ get primaryKeyField() {
+ return "X-EAS-SERVERID";
+ }
+
+ generatePrimaryKey() {
+ return TbSync.generateUUID();
+ }
+
+ // enable or disable changelog
+ get logUserChanges() {
+ return true;
+ }
+
+ directoryObserver(aTopic) {
+ switch (aTopic) {
+ case "addrbook-removed":
+ case "addrbook-updated":
+ //Services.console.logStringMessage("["+ aTopic + "] " + this.folderData.getFolderProperty("foldername"));
+ break;
+ }
+ }
+
+ cardObserver(aTopic, abCardItem) {
+ switch (aTopic) {
+ case "addrbook-contact-updated":
+ case "addrbook-contact-removed":
+ //Services.console.logStringMessage("["+ aTopic + "] " + abCardItem.getProperty("DisplayName"));
+ break;
+
+ case "addrbook-contact-created":
+ {
+ //Services.console.logStringMessage("["+ aTopic + "] "+ abCardItem.getProperty("DisplayName")+">");
+ break;
+ }
+ }
+ }
+
+ listObserver(aTopic, abListItem, abListMember) {
+ switch (aTopic) {
+ case "addrbook-list-member-added":
+ case "addrbook-list-member-removed":
+ //Services.console.logStringMessage("["+ aTopic + "] MemberName: " + abListMember.getProperty("DisplayName"));
+ break;
+
+ case "addrbook-list-removed":
+ case "addrbook-list-updated":
+ //Services.console.logStringMessage("["+ aTopic + "] ListName: " + abListItem.getProperty("ListName"));
+ break;
+
+ case "addrbook-list-created":
+ //Services.console.logStringMessage("["+ aTopic + "] ListName: "+abListItem.getProperty("ListName")+">");
+ break;
+ }
+ }
+
+ async createAddressbook(newname) {
+ // https://searchfox.org/comm-central/source/mailnews/addrbook/src/nsDirPrefs.h
+ let dirPrefId = MailServices.ab.newAddressBook(newname, "", 101);
+ let directory = MailServices.ab.getDirectoryFromId(dirPrefId);
+
+ eas.sync.resetFolderSyncInfo(this.folderData);
+
+ if (directory && directory instanceof Components.interfaces.nsIAbDirectory && directory.dirPrefId == dirPrefId) {
+ directory.setStringValue("tbSyncIcon", "eas" + (this.folderData.accountData.getAccountProperty("servertype") == "office365" ? "_365" : ""));
+ directory.setStringValue("tbSyncRevision", "2");
+ return directory;
+ }
+ return null;
+ }
+}
+
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// * TargetData implementation
+// * Using TbSyncs advanced calendar TargetData
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+var TargetData_calendar = class extends TbSync.lightning.AdvancedTargetData {
+ constructor(folderData) {
+ super(folderData);
+ }
+
+ // The calendar target does not support a custom primaryKeyField, because
+ // the lightning implementation only allows to search for items via UID.
+ // Like the addressbook target, the calendar target item element has a
+ // primaryKey getter/setter which - however - only works on the UID.
+
+ // enable or disable changelog
+ get logUserChanges() {
+ return true;
+ }
+
+ calendarObserver(aTopic, tbCalendar, aPropertyName, aPropertyValue, aOldPropertyValue) {
+ switch (aTopic) {
+ case "onCalendarPropertyChanged":
+ //Services.console.logStringMessage("["+ aTopic + "] " + tbCalendar.calendar.name + " : " + aPropertyName);
+ break;
+
+ case "onCalendarDeleted":
+ case "onCalendarPropertyDeleted":
+ //Services.console.logStringMessage("["+ aTopic + "] " +tbCalendar.calendar.name);
+ break;
+ }
+ }
+
+ itemObserver(aTopic, tbItem, tbOldItem) {
+ switch (aTopic) {
+ case "onAddItem":
+ case "onModifyItem":
+ case "onDeleteItem":
+ //Services.console.logStringMessage("["+ aTopic + "] " + tbItem.nativeItem.title);
+ break;
+ }
+ }
+
+ async createCalendar(newname) {
+ let calManager = TbSync.lightning.cal.manager;
+
+ //Create the new standard calendar with a unique name
+ let newCalendar = calManager.createCalendar("storage", Services.io.newURI("moz-storage-calendar://"));
+ newCalendar.id = TbSync.lightning.cal.getUUID();
+ newCalendar.name = newname;
+
+ eas.sync.resetFolderSyncInfo(this.folderData);
+
+ newCalendar.setProperty("color", this.folderData.getFolderProperty("targetColor"));
+ newCalendar.setProperty("relaxedMode", true); //sometimes we get "generation too old for modifyItem", check can be disabled with relaxedMode
+ // removed in TB78, as it seems to not fully enable the calendar, if present before registering
+ // https://searchfox.org/comm-central/source/calendar/base/content/calendar-management.js#385
+ //newCalendar.setProperty("calendar-main-in-composite",true);
+ newCalendar.setProperty("readOnly", this.folderData.getFolderProperty("downloadonly"));
+
+ switch (this.folderData.getFolderProperty("type")) {
+ case "8": //event
+ case "13":
+ newCalendar.setProperty("capabilities.tasks.supported", false);
+ newCalendar.setProperty("capabilities.events.supported", true);
+ break;
+ case "7": //todo
+ case "15":
+ newCalendar.setProperty("capabilities.tasks.supported", true);
+ newCalendar.setProperty("capabilities.events.supported", false);
+ break;
+ default:
+ newCalendar.setProperty("capabilities.tasks.supported", false);
+ newCalendar.setProperty("capabilities.events.supported", false);
+ }
+
+ calManager.registerCalendar(newCalendar);
+
+ let authData = eas.network.getAuthData(this.folderData.accountData);
+
+ //is there an email identity we can associate this calendar to?
+ //getIdentityKey returns "" if none found, which removes any association
+ let key = eas.tools.getIdentityKey(authData.user);
+ newCalendar.setProperty("fallbackOrganizerName", newCalendar.getProperty("organizerCN"));
+ newCalendar.setProperty("imip.identity.key", key);
+ if (key === "") {
+ //there is no matching email identity - use current default value as best guess and remove association
+ //use current best guess
+ newCalendar.setProperty("organizerCN", newCalendar.getProperty("fallbackOrganizerName"));
+ newCalendar.setProperty("organizerId", TbSync.lightning.cal.email.prependMailTo(authData.user));
+ }
+
+ return newCalendar;
+ }
+}
+
+
+
+
+
+/**
+ * This provider is implementing the StandardFolderList class instead of
+ * the FolderList class.
+ */
+var StandardFolderList = class {
+ /**
+ * Is called before the context menu of the folderlist is shown, allows to
+ * show/hide custom menu options based on selected folder. During an active
+ * sync, folderData will be null.
+ */
+ static onContextMenuShowing(window, folderData) {
+ let hideContextMenuDelete = true;
+ if (folderData !== null) {
+ //if a folder in trash is selected, also show ContextMenuDelete (but only if FolderDelete is allowed)
+ if (eas.tools.parentIsTrash(folderData) && folderData.accountData.getAccountProperty("allowedEasCommands").split(",").includes("FolderDelete")) {
+ hideContextMenuDelete = false;
+ window.document.getElementById("TbSync.eas.FolderListContextMenuDelete").label = TbSync.getString("deletefolder.menuentry::" + folderData.getFolderProperty("foldername"), "eas");
+ }
+ }
+ window.document.getElementById("TbSync.eas.FolderListContextMenuDelete").hidden = hideContextMenuDelete;
+ }
+
+
+ /**
+ * Return the icon used in the folderlist to represent the different folder
+ * types.
+ */
+ static getTypeImage(folderData) {
+ let src = "";
+ switch (folderData.getFolderProperty("type")) {
+ case "9":
+ case "14":
+ src = "contacts16.png";
+ break;
+ case "8":
+ case "13":
+ src = "calendar16.png";
+ break;
+ case "7":
+ case "15":
+ src = "todo16.png";
+ break;
+ }
+ return "chrome://tbsync/content/skin/" + src;
+ }
+
+
+ /**
+ * Return the name of the folder shown in the folderlist.
+ */
+ static getFolderDisplayName(folderData) {
+ let folderName = folderData.getFolderProperty("foldername");
+ if (eas.tools.parentIsTrash(folderData)) folderName = TbSync.getString("recyclebin", "eas") + " | " + folderName;
+ return folderName;
+ }
+
+
+ /**
+ * Return the attributes for the ACL RO (readonly menu element per folder.
+ * (label, disabled, hidden, style, ...)
+ *
+ * Return a list of attributes and their values If both (RO+RW) do
+ * not return any attributes, the ACL menu is not displayed at all.
+ */
+ static getAttributesRoAcl(folderData) {
+ return {
+ label: TbSync.getString("acl.readonly", "eas"),
+ };
+ }
+
+
+ /**
+ * Return the attributes for the ACL RW (readwrite) menu element per folder.
+ * (label, disabled, hidden, style, ...)
+ *
+ * Return a list of attributes and their values. If both (RO+RW) do
+ * not return any attributes, the ACL menu is not displayed at all.
+ */
+ static getAttributesRwAcl(folderData) {
+ return {
+ label: TbSync.getString("acl.readwrite", "eas"),
+ }
+ }
+}
+
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/network.js", this, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/wbxmltools.js", this, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/xmltools.js", this, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/tools.js", this, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/sync.js", this, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/contactsync.js", this.sync, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/calendarsync.js", this.sync, "UTF-8");
+Services.scriptloader.loadSubScript("chrome://eas4tbsync/content/includes/tasksync.js", this.sync, "UTF-8");
diff -Nru eas4tbsync-4.11/content/skin/365.svg eas4tbsync-4.17/content/skin/365.svg
--- eas4tbsync-4.11/content/skin/365.svg 2024-08-19 18:22:14.000000000 +0000
+++ eas4tbsync-4.17/content/skin/365.svg 2019-11-30 12:30:50.000000000 +0000
@@ -1,12 +1,12 @@
-
-