Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Karteek's Etherpad Fork

  • Loading branch information...
commit 595313d1e51635aef51f5f308f6455d6c367ae95 0 parents
@karteek authored
Showing with 33,899 additions and 0 deletions.
  1. +202 −0 COPYING
  2. +391 −0 README
  3. +6 −0 env.sh
  4. +9 −0 etherpad/.gitignore
  5. +1 −0  etherpad/bin/.gitignore
  6. +75 −0 etherpad/bin/rebuildjar.sh
  7. +66 −0 etherpad/bin/run-local.sh
  8. +30 −0 etherpad/bin/setup-mysql-db.sh
  9. +18 −0 etherpad/etc/etherpad.localdev-default.properties
  10. BIN  etherpad/lib/dnsjava-2.0.6.jar
  11. BIN  etherpad/lib/jbcrypt-0.2.jar
  12. BIN  etherpad/lib/jcommon-1.0.15.jar
  13. BIN  etherpad/lib/jfreechart-1.0.12.jar
  14. +127 −0 etherpad/src/etherpad/admin/shell.js
  15. +800 −0 etherpad/src/etherpad/billing/billing.js
  16. +219 −0 etherpad/src/etherpad/billing/fields.js
  17. +422 −0 etherpad/src/etherpad/billing/team_billing.js
  18. +509 −0 etherpad/src/etherpad/collab/ace/contentcollector.js
  19. +210 −0 etherpad/src/etherpad/collab/ace/domline.js
  20. +923 −0 etherpad/src/etherpad/collab/ace/easysync1.js
  21. +1,968 −0 etherpad/src/etherpad/collab/ace/easysync2.js
  22. +877 −0 etherpad/src/etherpad/collab/ace/easysync2_tests.js
  23. +247 −0 etherpad/src/etherpad/collab/ace/linestylefilter.js
  24. +778 −0 etherpad/src/etherpad/collab/collab_server.js
  25. +359 −0 etherpad/src/etherpad/collab/collabroom_server.js
  26. +55 −0 etherpad/src/etherpad/collab/genimg.js
  27. +178 −0 etherpad/src/etherpad/collab/json_sans_eval.js
  28. +174 −0 etherpad/src/etherpad/collab/readonly_server.js
  29. +204 −0 etherpad/src/etherpad/collab/server_utils.js
  30. +263 −0 etherpad/src/etherpad/control/aboutcontrol.js
  31. +1,471 −0 etherpad/src/etherpad/control/admincontrol.js
  32. +199 −0 etherpad/src/etherpad/control/blogcontrol.js
  33. +87 −0 etherpad/src/etherpad/control/connection_diagnostics_control.js
  34. +148 −0 etherpad/src/etherpad/control/global_pro_account_control.js
  35. +226 −0 etherpad/src/etherpad/control/historycontrol.js
  36. +93 −0 etherpad/src/etherpad/control/loadtestcontrol.js
  37. +54 −0 etherpad/src/etherpad/control/maincontrol.js
  38. +280 −0 etherpad/src/etherpad/control/pad/pad_changeset_control.js
  39. +778 −0 etherpad/src/etherpad/control/pad/pad_control.js
  40. +320 −0 etherpad/src/etherpad/control/pad/pad_importexport_control.js
  41. +287 −0 etherpad/src/etherpad/control/pad/pad_view_control.js
  42. +75 −0 etherpad/src/etherpad/control/pne_manual_control.js
  43. +48 −0 etherpad/src/etherpad/control/pne_tracker_control.js
  44. +401 −0 etherpad/src/etherpad/control/pro/account_control.js
  45. +260 −0 etherpad/src/etherpad/control/pro/admin/account_manager_control.js
  46. +128 −0 etherpad/src/etherpad/control/pro/admin/license_manager_control.js
  47. +286 −0 etherpad/src/etherpad/control/pro/admin/pro_admin_control.js
  48. +54 −0 etherpad/src/etherpad/control/pro/admin/pro_config_control.js
  49. +447 −0 etherpad/src/etherpad/control/pro/admin/team_billing_control.js
  50. +151 −0 etherpad/src/etherpad/control/pro/pro_main_control.js
  51. +200 −0 etherpad/src/etherpad/control/pro/pro_padlist_control.js
  52. +136 −0 etherpad/src/etherpad/control/pro_beta_control.js
  53. +60 −0 etherpad/src/etherpad/control/pro_help_control.js
  54. +171 −0 etherpad/src/etherpad/control/pro_signup_control.js
  55. +75 −0 etherpad/src/etherpad/control/scriptcontrol.js
  56. +65 −0 etherpad/src/etherpad/control/static_control.js
  57. +1,214 −0 etherpad/src/etherpad/control/statscontrol.js
  58. +757 −0 etherpad/src/etherpad/control/store/eepnet_checkout_control.js
  59. +201 −0 etherpad/src/etherpad/control/store/storecontrol.js
  60. +74 −0 etherpad/src/etherpad/control/testcontrol.js
  61. +23 −0 etherpad/src/etherpad/db_migrations/m0000_test.js
  62. +38 −0 etherpad/src/etherpad/db_migrations/m0001_eepnet_signups_init.js
  63. +47 −0 etherpad/src/etherpad/db_migrations/m0002_eepnet_signups_2.js
  64. +29 −0 etherpad/src/etherpad/db_migrations/m0003_create_tests_table_v2.js
  65. +38 −0 etherpad/src/etherpad/db_migrations/m0004_convert_all_tables_to_innodb.js
  66. +73 −0 etherpad/src/etherpad/db_migrations/m0005_create_billing_tables.js
  67. +29 −0 etherpad/src/etherpad/db_migrations/m0006_eepnet_signups_3.js
  68. +67 −0 etherpad/src/etherpad/db_migrations/m0007_create_pro_tables_v4.js
  69. +31 −0 etherpad/src/etherpad/db_migrations/m0008_persistent_vars.js
  70. +31 −0 etherpad/src/etherpad/db_migrations/m0009_pad_tables.js
  71. +71 −0 etherpad/src/etherpad/db_migrations/m0010_pad_sqlmeta.js
  72. +33 −0 etherpad/src/etherpad/db_migrations/m0011_pro_users_temppass.js
  73. +30 −0 etherpad/src/etherpad/db_migrations/m0012_pro_users_auto_signin.js
  74. +54 −0 etherpad/src/etherpad/db_migrations/m0013_pne_padv2_upgrade.js
  75. +102 −0 etherpad/src/etherpad/db_migrations/m0014_pne_globalpadids.js
  76. +25 −0 etherpad/src/etherpad/db_migrations/m0015_padmeta_passwords.js
  77. +35 −0 etherpad/src/etherpad/db_migrations/m0016_pne_tracking_data.js
  78. +30 −0 etherpad/src/etherpad/db_migrations/m0017_pne_tracking_data_v2.js
  79. +82 −0 etherpad/src/etherpad/db_migrations/m0018_eepnet_checkout_tables.js
  80. +24 −0 etherpad/src/etherpad/db_migrations/m0019_padmeta_deleted.js
  81. +25 −0 etherpad/src/etherpad/db_migrations/m0020_padmeta_archived.js
  82. +57 −0 etherpad/src/etherpad/db_migrations/m0021_pro_padmeta_json.js
  83. +30 −0 etherpad/src/etherpad/db_migrations/m0022_create_userids_table.js
  84. +32 −0 etherpad/src/etherpad/db_migrations/m0023_create_usagestats_table.js
  85. +42 −0 etherpad/src/etherpad/db_migrations/m0024_statistics_table.js
  86. +26 −0 etherpad/src/etherpad/db_migrations/m0025_rename_pro_users_table.js
  87. +37 −0 etherpad/src/etherpad/db_migrations/m0026_create_guests_table.js
  88. +27 −0 etherpad/src/etherpad/db_migrations/m0027_pro_config.js
  89. +29 −0 etherpad/src/etherpad/db_migrations/m0028_ondemand_beta_emails.js
  90. +31 −0 etherpad/src/etherpad/db_migrations/m0029_lowercase_subdomains.js
  91. +26 −0 etherpad/src/etherpad/db_migrations/m0030_fix_statistics_values.js
  92. +24 −0 etherpad/src/etherpad/db_migrations/m0031_deleted_pro_users.js
  93. +39 −0 etherpad/src/etherpad/db_migrations/m0032_reduce_topvalues_counts.js
  94. +30 −0 etherpad/src/etherpad/db_migrations/m0033_pro_account_usage.js
  95. +42 −0 etherpad/src/etherpad/db_migrations/m0034_create_recurring_billing_table.js
  96. +28 −0 etherpad/src/etherpad/db_migrations/m0035_add_email_to_paymentinfo.js
  97. +45 −0 etherpad/src/etherpad/db_migrations/m0036_create_missing_subscription_records.js
  98. +32 −0 etherpad/src/etherpad/db_migrations/m0037_create_pro_referral_table.js
  99. +26 −0 etherpad/src/etherpad/db_migrations/m0038_pad_coarse_revs.js
  100. +147 −0 etherpad/src/etherpad/db_migrations/migration_runner.js
  101. +26 −0 etherpad/src/etherpad/debug.js
  102. +41 −0 etherpad/src/etherpad/globals.js
  103. +276 −0 etherpad/src/etherpad/helpers.js
  104. +241 −0 etherpad/src/etherpad/importexport/importexport.js
  105. +37 −0 etherpad/src/etherpad/legacy_urls.js
  106. +163 −0 etherpad/src/etherpad/licensing.js
  107. +261 −0 etherpad/src/etherpad/log.js
  108. +438 −0 etherpad/src/etherpad/metrics/metrics.js
  109. +52 −0 etherpad/src/etherpad/pad/activepads.js
  110. +67 −0 etherpad/src/etherpad/pad/chatarchive.js
  111. +338 −0 etherpad/src/etherpad/pad/dbwriter.js
  112. +675 −0 etherpad/src/etherpad/pad/easysync2migration.js
  113. +382 −0 etherpad/src/etherpad/pad/exporthtml.js
  114. +230 −0 etherpad/src/etherpad/pad/importhtml.js
  115. +651 −0 etherpad/src/etherpad/pad/model.js
  116. +110 −0 etherpad/src/etherpad/pad/noprowatcher.js
  117. +206 −0 etherpad/src/etherpad/pad/pad_migrations.js
  118. +237 −0 etherpad/src/etherpad/pad/pad_security.js
  119. +170 −0 etherpad/src/etherpad/pad/padevents.js
  120. +401 −0 etherpad/src/etherpad/pad/padusers.js
  121. +154 −0 etherpad/src/etherpad/pad/padutils.js
  122. +103 −0 etherpad/src/etherpad/pad/revisions.js
  123. +191 −0 etherpad/src/etherpad/pne/pne_utils.js
  124. +137 −0 etherpad/src/etherpad/pro/domains.js
  125. +101 −0 etherpad/src/etherpad/pro/pro_account_auto_signin.js
  126. +503 −0 etherpad/src/etherpad/pro/pro_accounts.js
  127. +92 −0 etherpad/src/etherpad/pro/pro_config.js
  128. +232 −0 etherpad/src/etherpad/pro/pro_pad_db.js
  129. +104 −0 etherpad/src/etherpad/pro/pro_pad_editors.js
  130. +289 −0 etherpad/src/etherpad/pro/pro_padlist.js
  131. +111 −0 etherpad/src/etherpad/pro/pro_padmeta.js
  132. +141 −0 etherpad/src/etherpad/pro/pro_quotas.js
  133. +166 −0 etherpad/src/etherpad/pro/pro_utils.js
  134. +50 −0 etherpad/src/etherpad/quotas.js
  135. +204 −0 etherpad/src/etherpad/sessions.js
  136. +231 −0 etherpad/src/etherpad/statistics/exceptions.js
  137. +1,252 −0 etherpad/src/etherpad/statistics/statistics.js
  138. +300 −0 etherpad/src/etherpad/store/checkout.js
  139. +101 −0 etherpad/src/etherpad/store/eepnet_checkout.js
  140. +241 −0 etherpad/src/etherpad/store/eepnet_trial.js
  141. +23 −0 etherpad/src/etherpad/testing/testutils.js
  142. +22 −0 etherpad/src/etherpad/testing/unit_tests/t0000_test.js
  143. +48 −0 etherpad/src/etherpad/testing/unit_tests/t0001_sqlbase_transaction_rollback.js
  144. +89 −0 etherpad/src/etherpad/testing/unit_tests/t0002_license_generation.js
  145. +42 −0 etherpad/src/etherpad/testing/unit_tests/t0003_persistent_vars.js
  146. +214 −0 etherpad/src/etherpad/testing/unit_tests/t0004_sqlobj.js
  147. +22 −0 etherpad/src/etherpad/testing/unit_tests/t0005_easysync.js
  148. +162 −0 etherpad/src/etherpad/usage_stats/usage_stats.js
  149. +396 −0 etherpad/src/etherpad/utils.js
  150. +423 −0 etherpad/src/main.js
  151. +11 −0 etherpad/src/static/crossdomain.xml
  152. +183 −0 etherpad/src/static/css/admin/admin-stats.css
  153. +49 −0 etherpad/src/static/css/beta.css
  154. +387 −0 etherpad/src/static/css/broadcast.css
  155. +13 −0 etherpad/src/static/css/connection_diagnostics.css
  156. +770 −0 etherpad/src/static/css/etherpad.css
  157. +55 −0 etherpad/src/static/css/fluxbb.css
  158. +175 −0 etherpad/src/static/css/framedpage.css
  159. +52 −0 etherpad/src/static/css/global-pro-account.css
  160. +26 −0 etherpad/src/static/css/home-opensource.css
  161. +264 −0 etherpad/src/static/css/home.css
  162. +244 −0 etherpad/src/static/css/lib/jquery.contextmenu.css
  163. +1,000 −0 etherpad/src/static/css/pad.css
Sorry, we could not display the entire diff because too many files (1,102) changed.
202 COPYING
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
391 README
@@ -0,0 +1,391 @@
+--------------------------------------------------------------------------
+| From Karteek |
+--------------------------------------------------------------------------
+
+== Karteek's Etherpad Fork ==
+Package
++ Etherpad source from http://code.google.com/p/etherpad
++ Some minor fixes/changes here and there
++ Oo.org integration for file exports and file imports from DOC/RTF format
+- Commented code for File imports due to license restrictions
+
+How to
+1. Grab the code from github
+ $ git clone git://github.com/karteek/etherpad.git
+
+2. Set up the environment in env.sh and source the file. The settings inside are
+from my MBP. Do update them to meet your machine's settings.
+ $ source env.sh
+
+3. Create a database "etherpad" with password "password" on a MySQL database server
+
+4. Update etherpad.SQL_JDBC_URL, etherpad.SQL_USERNAME, etherpad.SQL_PASSWORD and
+etherpad.adminPass in the file "etherpad/etc/etherpad.localdev-default.properties"
+
+5. Change dir to etherpad, compile the jar and start the server
+ $ cd etherpad
+ $ bin/rebuildjar.sh
+ $ bin/run-local.sh
+
+6. You are done. Visit http://localhost:9000 to check your instance
+
+How to Enable File Imports
+1. File Imports depend on cos.jar (http://www.servlets.com/cos/) - com.oreilly.servlet
+
+2. Do read the license http://www.servlets.com/cos/license.htmls
+
+3. Even now, if you want to continue with imports,
+ - Download cos.jar from the site and copy it to infrastructure/lib folder
+ - In infrastructure folder, find out the files, where imports functionality is commented
+ $ grep -R "REMOVED_COS_OF_COS" *
+ - Uncomment and recompile JAR
+
+How to Enable Exports
+1. Make sure that there is a "etherpad.soffice" entry in the file
+"etherpad/etc/etherpad.localdev-default.properties"
+
+2. You need Openoffice.org to be running on your machine as service. It usually on linux is
+ $ /path/to/openoffice/program/soffice.bin -headless -nofirststartwizard
+ -accept="socket,host=localhost,port=8100;urp;StarOffice.Service"
+
+3. Check the file "infrastructure/com.etherpad.openofficeservice/importexport.scala"
+for more info
+
+How to deploy the same on example.com
+1. Edit your dns and point *.example.com to the same server where example.com resides
+2. Make sure that your SMTP is working
+3. Open etherpad/src/main.js, and update domain in line #273
+4. Open etherpad/src/etherpad/globals.js and change the domain in variable
+SUPERDOMAINS found at line #30
+5. Open etherpad/src/static/crossdomain.xml and add your domain to crossdomains.xml
+6. Look into the src folder and update your domain where etherpad.com is used (especially emails)
+ $ grep -ir "etherpad.com" *
+and update domain in all the files.
+7. Open etherpad/etc/etherpad.localdev-default.properties and update
+ - devMode to false
+ - etherpad.isProduction to true
+ - listen to example.com:80
+and change passwords too.
+8. Now start the server. You will need root access on OS X to bind to ports < 1000.
+ $ bin/run-local.sh
+
+How to do the same on example.com but with a reverse proxy on Apache
+1. Do steps 1 thru 7 in above. But dont update listen as told in 7, rather update
+listen to example.com:9000
+2. Create a vhost entry. It might look like ..
+--
+<VirtualHost *:80>
+ ServerName example.com
+ ServerAdmin admin@example.com
+ ErrorLog /var/log/apache2/etherpad.error.log
+ LogLevel warn
+ CustomLog /var/log/apache2/etherpad.access.log combined
+ ServerSignature Off
+ ProxyPass / http://localhost:9000/
+ ProxyPassReverse / http://localhost:9000/
+ ProxyPreserveHost on
+ <Proxy *>
+ Options FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ allow from all
+ </Proxy>
+</VirtualHost>
+3. Restart apache, and things should work
+
+
+--------------------------------------------------------------------------
+| From Etherpad Team |
+--------------------------------------------------------------------------
+
+
+EtherPad is a web-based realtime collaborative document editor.
+
+EtherPad currently lives at http://code.google.com/p/etherpad
+
+For instructions to build and run EtherPad, see: http://code.google.com/p/etherpad/wiki/Instructions
+
+This distribution includes some code written by other organizations.
+The rest is Copyright 2007-2009 Google Inc. and licensed under the Apache License 2.0.
+
+>>>>>>>>>>>>>>
+Apache Commons Lang
+Copyright 2001-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+=========================================================================
+== NOTICE file corresponding to section 4(d) of the Apache License, ==
+== Version 2.0, in this case for the Apache Derby distribution. ==
+=========================================================================
+
+>>>>>>>>>>>>>>
+Apache Derby
+Copyright 2004-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of Derby were originally developed by
+International Business Machines Corporation and are
+licensed to the Apache Software Foundation under the
+"Software Grant and Corporate Contribution License Agreement",
+informally known as the "Derby CLA".
+The following copyright notice(s) were affixed to portions of the code
+with which this file is now or was at one time distributed
+and are placed here unaltered.
+
+(C) Copyright 1997,2004 International Business Machines Corporation. All rights reserved.
+
+(C) Copyright IBM Corp. 2003.
+
+The portion of the functionTests under 'nist' was originally
+developed by the National Institute of Standards and Technology (NIST),
+an agency of the United States Department of Commerce, and adapted by
+International Business Machines Corporation in accordance with the NIST
+Software Acknowledgment and Redistribution document at
+http://www.itl.nist.gov/div897/ctg/sql_form.htm
+
+>>>>>>>>>>>>>>
+Apache Harmony
+Copyright 2006, 2009 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of Apache Harmony were originally developed by
+Intel Corporation and are licensed to the Apache Software
+Foundation under the "Software Grant and Corporate Contribution
+License Agreement" and for which the following copyright notices
+apply
+ (C) Copyright 2005 Intel Corporation
+ (C) Copyright 2005-2006 Intel Corporation
+ (C) Copyright 2006 Intel Corporation
+
+>>>>>>>>>>>>>>
+==============================================================
+ Jetty Web Container
+ Copyright 1995-2006 Mort Bay Consulting Pty Ltd
+==============================================================
+
+The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd
+unless otherwise noted. It is licensed under the apache 2.0
+license.
+
+The javax.servlet package used by Jetty is copyright
+Sun Microsystems, Inc and Apache Software Foundation. It is
+distributed under the Common Development and Distribution License.
+You can obtain a copy of the license at
+https://glassfish.dev.java.net/public/CDDLv1.0.html.
+
+The UnixCrypt.java code ~Implements the one way cryptography used by
+Unix systems for simple password protection. Copyright 1996 Aki Yoshida,
+modified April 2001 by Iris Van den Broeke, Daniel Deville.
+Permission to use, copy, modify and distribute UnixCrypt
+for non-commercial or commercial purposes and without fee is
+granted provided that the copyright notice appears in all copies.
+
+The default JSP implementation is provided by the Glassfish JSP engine
+from project Glassfish http://glassfish.dev.java.net. Copyright 2005
+Sun Microsystems, Inc. and portions Copyright Apache Software Foundation.
+
+Some portions of the code are Copyright:
+ 2006 Tim Vernum
+ 1999 Jason Gilbert.
+
+The jboss integration module contains some LGPL code.
+
+The win32 Java Service Wrapper (v3.2.3) is Copyright (c) 1999, 2006
+Tanuki Software, Inc. and 2001 Silver Egg Technology. It is
+covered by an open license which is viewable at
+http://svn.codehaus.org/jetty/jetty/branches/jetty-6.1/extras/win32service/LICENSE.txt
+
+>>>>>>>>>>>>>>
+Apache Sanselan
+Copyright 2007-2009 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+>>>>>>>>>>>>>>
+TagSoup
+Copyright 2002-2008 by John Cowan
+
+>>>>>>>>>>>>>>
+dnsjava:
+
+Copyright (c) 1999-2005, Brian Wellington
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the dnsjava project nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+>>>>>>>>>>>>>>
+jBCrypt:
+
+Copyright (c) 2006 Damien Miller
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+>>>>>>>>>>>>>>
+Scala:
+
+Copyright (c) 2002-2009 EPFL, Lausanne, unless otherwise specified.
+All rights reserved.
+
+This software was developed by the Programming Methods Laboratory of the
+Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland.
+
+Permission to use, copy, modify, and distribute this software in source
+or binary form for any purpose with or without fee is hereby granted,
+provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the EPFL nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+>>>>>>>>>>>>>>
+YUI Compressor:
+
+Copyright (c) 2009, Yahoo! Inc.
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+>>>>>>>>>>>>>>
+jQuery
+Copyright (c) 2009 John Resig, http://jquery.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+>>>>>>>>>>>>>>
+jQuery Pulse:
+
+Copyright (c) 2008 James Padolsey - jp(at)qd9(dot)co.uk | http://james.padolsey.com / http://enhance.qd-creative.co.uk
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+>>>>>>>>>>>>>>
+SWFObject v1.5
+Copyright (c) 2007 Geoff Stearns
+
+Licensed under the MIT License
+
+>>>>>>>>>>>>>>
+jQuery Context Menu Plugin:
+
+Original version copyright 2008 A Beautiful Site, LLC. Modifications by AppJet, Inc. released under the same license.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+>>>>>>>>>>>>>>
+c3p0
+Copyright (c) 2006 Machinery for Change, Inc.
+
+Licensed under the LGPL 2.1
+
+>>>>>>>>>>>>>>
+JCommon, JFreeChart
+Copyright (c) 2007-2009 Object Refinery Limited
+
+Licensed under the LGPL 2.1
+
+>>>>>>>>>>>>>>
+Mozilla Rhino
+
+Licensed under the MPL 1.1, GPL 2.0 or later
+
+
+>>>>>>>>>>>>>>
+MySQL Connector
+
+Licensed uder the GPL 2.0 or later with the FOSS exception
6 env.sh
@@ -0,0 +1,6 @@
+export JAVA_HOME="/Library/Java/Home"
+export SCALA_HOME="/opt/local/share/scala"
+export JAVA="$JAVA_HOME/bin/java"
+export SCALA="$SCALA_HOME/bin/scala"
+export PATH="$JAVA_HOME/bin:$SCALA_HOME/bin:/Applications/MAMP/Library/bin:$PATH"
+export MYSQL_CONNECTOR_JAR=`pwd`"/lib/mysql-connector-java-5.1.10-bin.jar"
9 etherpad/.gitignore
@@ -0,0 +1,9 @@
+data/
+build
+derby.log
+local
+*.swp
+appjet-eth*.jar
+etherpad-pne-*.jar
+
+
1  etherpad/bin/.gitignore
@@ -0,0 +1 @@
+run-david.sh
75 etherpad/bin/rebuildjar.sh
@@ -0,0 +1,75 @@
+#!/bin/bash -e
+
+# Copyright 2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -z "$JAR" ]; then
+ if [ ! -z `which fastjar` ]; then
+ JAR=fastjar
+ else
+ JAR=jar
+ fi
+fi
+
+function notify {
+ if [ ! -z `which growlnotify` ]; then
+ echo $0 finished | growlnotify
+ fi
+}
+trap notify EXIT
+
+source ../infrastructure/bin/compilecache.sh
+
+suffix="-dev";
+if [ "$1" == "prod" ]; then
+ suffix="";
+ shift;
+fi
+
+OWD=`pwd`
+cd ../infrastructure
+JAR=$JAR bin/makejar.sh $@
+
+rm -rf build/etherpad-jars
+mkdir -p build/etherpad-jars
+
+echo "including etherpad JARs..."
+
+JARFILES="echo ../etherpad/lib/*.jar"
+function genjar {
+ echo "unzipping JARs..."
+ pushd $1 >> /dev/null
+
+ for a in ../../../etherpad/lib/*.jar; do
+ $JAR xf $a
+ rm -rf META-INF/{MANIFEST.MF,NOTICE{,.txt},LICENSE{,.txt},INDEX.LIST,SUN_MICR.{RSA,SF},maven}
+ done
+
+ popd >> /dev/null
+}
+cacheonfiles JAR-etherpad "$JARFILES" genjar 1
+
+echo "updating..."
+
+pushd buildcache/JAR-etherpad >> /dev/null
+$JAR uf ../../build/appjet.jar `ls . | grep -v "^t$"`
+
+echo "done."
+
+popd >> /dev/null
+
+dst="$OWD/appjet-eth$suffix.jar"
+cp -f build/appjet.jar $dst
+cd $OWD
+echo "wrote $dst"
66 etherpad/bin/run-local.sh
@@ -0,0 +1,66 @@
+#!/bin/bash -e
+
+# Copyright 2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+mkdir -p data/appjet
+
+MXRAM="1G"
+if [ ! -z $1 ]; then
+ if [ ! '-' = `echo $1 | head -c 1` ]; then
+ MXRAM="$1";
+ shift;
+ fi
+fi
+
+CP="appjet-eth-dev.jar:data"
+for f in lib/*.jar; do
+ CP="$CP:$f"
+done
+
+if [ -z "$JAVA" ]; then
+ JAVA=java
+fi
+
+# etherpad properties file
+cfg_file=./data/etherpad.local.properties
+if [ ! -f $cfg_file ]; then
+ cfg_file=./etc/etherpad.localdev-default.properties
+fi
+if [[ $1 == "--cfg" ]]; then
+ cfg_file=${2}
+ shift;
+ shift;
+fi
+
+echo "Using config file: ${cfg_file}"
+
+$JAVA -classpath $CP \
+ -server \
+ -Xmx${MXRAM} \
+ -Xms${MXRAM} \
+ -Djava.awt.headless=true \
+ -XX:MaxGCPauseMillis=500 \
+ -XX:+UseConcMarkSweepGC \
+ -XX:+CMSIncrementalMode \
+ -XX:CMSIncrementalSafetyFactor=50 \
+ -XX:+PrintGCDetails \
+ -XX:+PrintGCTimeStamps \
+ -Xloggc:./data/logs/backend/jvm-gc.log \
+ -Dappjet.jmxremote=true \
+ $JAVA_OPTS \
+ net.appjet.oui.main \
+ --configFile=${cfg_file} \
+ "$@"
+
30 etherpad/bin/setup-mysql-db.sh
@@ -0,0 +1,30 @@
+#!/bin/bash -e
+
+# Copyright 2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ `whoami` != "root" ]; then
+ echo "Must run as root, i.e., sudo $0"
+ exit 1
+fi
+
+db="etherpad"
+
+echo "Creating etherpad ${db}..."
+echo "create database ${db};" | ${mysql} -u root
+
+echo "Granting priviliges..."
+echo "grant all privileges on ${db}.* to 'etherpad'@'localhost' identified by 'password';" | ${mysql} -u root
+
+echo "Success"
18 etherpad/etc/etherpad.localdev-default.properties
@@ -0,0 +1,18 @@
+ajstdlibHome = ../infrastructure/framework-src/modules
+appjetHome = ./data/appjet
+devMode = false
+etherpad.adminPass = password
+etherpad.fakeProduction = false
+etherpad.isProduction = true
+etherpad.SQL_JDBC_DRIVER = com.mysql.jdbc.Driver
+etherpad.SQL_JDBC_URL = jdbc:mysql://localhost:3306/etherpad
+etherpad.SQL_PASSWORD = password
+etherpad.SQL_USERNAME = etherpad
+etherpad.soffice = /Applications/OpenOffice.org.app/Contents/MacOS/soffice
+etherpad.isPNE = false
+listen = 9000
+logDir = ./data/logs
+modulePath = ./src
+transportPrefix = /comet
+transportUseWildcardSubdomains = false
+useVirtualFileRoot = ./src
BIN  etherpad/lib/dnsjava-2.0.6.jar
Binary file not shown
BIN  etherpad/lib/jbcrypt-0.2.jar
Binary file not shown
BIN  etherpad/lib/jcommon-1.0.15.jar
Binary file not shown
BIN  etherpad/lib/jfreechart-1.0.12.jar
Binary file not shown
127 etherpad/src/etherpad/admin/shell.js
@@ -0,0 +1,127 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import("funhtml.*");
+import("jsutils.cmp");
+import("jsutils.eachProperty");
+import("exceptionutils");
+import("execution");
+import("stringutils.trim");
+
+import("etherpad.sessions.getSession");
+import("etherpad.utils.*");
+
+function _splitCommand(cmd) {
+ var parts = [[], []];
+ var importing = true;
+ cmd.split("\n").forEach(function(l) {
+ if ((trim(l).length > 0) &&
+ (trim(l).indexOf("import") != 0)) {
+ importing = false;
+ }
+
+ if (importing) {
+ parts[0].push(l);
+ } else {
+ parts[1].push(l);
+ }
+ });
+
+ parts[0] = parts[0].join("\n");
+ parts[1] = parts[1].join("\n");
+ return parts;
+}
+
+function getResult(cmd) {
+ var resultString = (function() {
+ try {
+ var parts = _splitCommand(cmd);
+ result = execution.fancyAssEval(parts[0], parts[1]);
+ } catch (e) {
+ // if (e instanceof JavaException) {
+ // e = new net.appjet.bodylock.JSRuntimeException(e.getMessage(), e.javaException);
+ // }
+ if (appjet.config.devMode) {
+ (e.javaException || e.rhinoException || e).printStackTrace();
+ }
+ result = exceptionutils.getStackTracePlain(e);
+ }
+ var resultString;
+ try {
+ resultString = ((result && result.toString) ? result.toString() : String(result));
+ } catch (ex) {
+ resultString = "Error converting result to string: "+ex.toString();
+ }
+ return resultString;
+ })();
+ return resultString;
+}
+
+function _renderCommandShell() {
+ // run command if necessary
+ if (request.params.cmd) {
+ var cmd = request.params.cmd;
+ var resultString = getResult(cmd);
+
+ getSession().shellCommand = cmd;
+ getSession().shellResult = resultString;
+ response.redirect(request.path+(request.query?'?'+request.query:''));
+ }
+
+ var div = DIV({style: "padding: 4px; margin: 4px; background: #eee; "
+ + "border: 1px solid #338"});
+ // command div
+ var oldCmd = getSession().shellCommand || "";
+ var commandDiv = DIV({style: "width: 100%; margin: 4px 0;"});
+ commandDiv.push(FORM({style: "width: 100%;",
+ method: "POST", action: request.path + (request.query?'?'+request.query:'')},
+ TEXTAREA({name: "cmd",
+ style: "border: 1px solid #555;"
+ + "width: 100%; height: 160px; font-family: monospace;"},
+ html(oldCmd)),
+ INPUT({type: "submit"})));
+
+ // result div
+ var resultDiv = DIV({style: ""});
+ var isResult = getSession().shellResult != null;
+ if (isResult) {
+ resultDiv.push(DIV(
+ PRE({style: 'border: 1px solid #555; font-family: monospace; margin: 4px 0; padding: 4px;'},
+ getSession().shellResult)));
+ delete getSession().shellResult;
+ resultDiv.push(DIV({style: "text-align: right;"},
+ A({href: qpath({})}, "clear")));
+ } else {
+ resultDiv.push(P("result will go here"));
+ }
+
+ var t = TABLE({border: 0, cellspacing: 0, cellpadding: 0, width: "100%",
+ style: "width: 100%;"});
+ t.push(TR(TH({width: "49%", align: "left"}, " Command:"),
+ TH({width: "49%", align: "left"}, " "+(isResult ? "Result:" : ""))),
+ TR(TD({valign: "top", style: 'padding: 4px;'}, commandDiv),
+ TD({valign: "top", style: 'padding: 4px;'}, resultDiv)));
+ div.push(t);
+ return div;
+}
+
+function handleRequest() {
+ var body = BODY();
+ body.push(A({href: '/ep/admin/'}, html("&laquo; Admin")));
+ body.push(BR(), BR());
+ body.push(_renderCommandShell());
+ response.write(HTML(body));
+}
800 etherpad/src/etherpad/billing/billing.js
@@ -0,0 +1,800 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import("dateutils.*");
+import("fastJSON");
+import("jsutils.eachProperty");
+import("netutils.urlPost");
+import("sqlbase.sqlbase");
+import("sqlbase.sqlcommon");
+import("sqlbase.sqlobj");
+import("stringutils.{md5,repeat}");
+
+import("etherpad.log.{custom=>eplog}");
+
+
+jimport("java.lang.System.out.println");
+
+function clearKeys(obj, keys) {
+ var newObj = {};
+ eachProperty(obj, function(k, v) {
+ var isCopied = false;
+ keys.forEach(function(key) {
+ if (k == key.name &&
+ key.valueTest(v)) {
+ newObj[k] = key.valueReplace(v);
+ isCopied = true;
+ }
+ });
+ if (! isCopied) {
+ if (typeof(obj[k]) == 'object') {
+ newObj[k] = clearKeys(v, keys);
+ } else {
+ newObj[k] = v;
+ }
+ }
+ });
+ return newObj;
+}
+
+function replaceWithX(s) {
+ return repeat("X", s.length);
+}
+
+function log(obj) {
+ eplog('billing', clearKeys(obj, [
+ {name: "ACCT",
+ valueTest: function(s) { return /^\d{15,16}$/.test(s) },
+ valueReplace: replaceWithX},
+ {name: "CVV2",
+ valueTest: function(s) { return /^\d{3,4}$/.test(s) },
+ valueReplace: replaceWithX}]));
+}
+
+var _USER = function() { return appjet.config['etherpad.paypal.user'] || "zamfir_1239051855_biz_api1.gmail.com"; }
+var _PWD = function() { return appjet.config['etherpad.paypal.pwd'] || "1239051867"; }
+var _SIGNATURE = function() { return appjet.config['etherpad.paypal.signature'] || "AQU0e5vuZCvSg-XJploSa.sGUDlpAwAy5fz.FhtfOQ25Qa9sFLDt7Bmp"; }
+var _RECEIVER = function() { return appjet.config['etherpad.paypal.receiver'] || "zamfir_1239051855_biz@gmail.com"; }
+var _paypalApiUrl = function() { return appjet.config['etherpad.paypal.apiUrl'] || "https://api-3t.sandbox.paypal.com/nvp"; }
+var _paypalWebUrl = function() { return appjet.config['etherpad.paypal.webUrl'] || "https://www.sandbox.paypal.com/cgi-bin/webscr"; }
+function paypalPurchaseUrl(token) {
+ return (appjet.config['etherpad.paypal.purchaseUrl'] || "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=")+token;
+}
+
+function getPurchase(id) {
+ return sqlobj.selectSingle('billing_purchase', {id: id});
+}
+
+function getPurchaseForCustomer(customerId) {
+ return sqlobj.selectSingle('billing_purchase', {customer: customerId});
+}
+
+function updatePurchase(id, fields) {
+ sqlobj.updateSingle('billing_purchase', {id: id}, fields);
+}
+
+function getInvoicesForPurchase(purchaseId) {
+ return sqlobj.selectMulti('billing_invoice', {purchase: purchaseId});
+}
+
+function getInvoice(id) {
+ return sqlobj.selectSingle('billing_invoice', {id: id});
+}
+
+function createInvoice() {
+ return _newInvoice();
+}
+
+function updateInvoice(id, fields) {
+ sqlobj.updateSingle('billing_invoice', {id: id}, fields)
+}
+
+function getTransaction(id) {
+ return sqlobj.selectSingle('billing_transaction', {id: id});
+}
+function getTransactionByExternalId(txnId) {
+ return sqlobj.selectSingle('billing_transaction', {txnId: txnId});
+}
+
+function getTransactionsForCustomer(customerId) {
+ return sqlobj.selectMulti('billing_transaction', {customer: customerId});
+}
+
+function getPendingTransactionsForCustomer(customerId) {
+ return sqlobj.selectMulti('billing_transaction', {customer: customerId, status: 'pending'});
+}
+
+function _updateTransaction(id, fields) {
+ return sqlobj.updateSingle('billing_transaction', {id: id}, fields);
+}
+
+function getAdjustments(invoiceId) {
+ return sqlobj.selectMulti('billing_adjustment', {invoice: invoiceId});
+}
+
+function createSubscription(customer, product, dollars, couponCode) {
+ var purchaseId = _newPurchase(customer, product, dollarsToCents(dollars), couponCode);
+ _purchaseActive(purchaseId);
+ updatePurchase(purchaseId, {type: 'subscription', paidThrough: nextMonth(noon(new Date))});
+ return purchaseId;
+}
+
+function _newPurchase(customer, product, cents, couponCode) {
+ var purchaseId = sqlobj.insert('billing_purchase', {
+ customer: customer,
+ product: product,
+ cost: cents,
+ coupon: couponCode,
+ status: 'inactive'
+ });
+ return purchaseId;
+}
+
+function _newInvoice() {
+ var invoiceId = sqlobj.insert('billing_invoice', {
+ time: new Date(),
+ purchase: -1,
+ amt: 0,
+ status: 'pending'
+ });
+ return invoiceId;
+}
+
+function _newTransaction(customer, cents) {
+ var transactionId = sqlobj.insert('billing_transaction', {
+ customer: customer,
+ time: new Date(),
+ amt: cents,
+ status: 'new'
+ });
+ return transactionId;
+}
+
+function _newAdjustment(transaction, invoice, cents) {
+ sqlobj.insert('billing_adjustment', {
+ transaction: transaction,
+ invoice: invoice,
+ time: new Date(),
+ amt: cents
+ });
+}
+
+function _transactionSuccess(transaction, txnId, payInfo) {
+ _updateTransaction(transaction, {
+ status: 'success', txnId: txnId, time: new Date(), payInfo: payInfo
+ });
+}
+
+function _transactionFailure(transaction, txnId) {
+ _updateTransaction(transaction, {
+ status: 'failure', txnId: txnId, time: new Date()
+ });
+}
+
+function _transactionPending(transaction, txnId) {
+ _updateTransaction(transaction, {
+ status: 'pending', txnId: txnId, time: new Date()
+ });
+}
+
+function _invoicePaid(invoice) {
+ updateInvoice(invoice, {status: 'paid'});
+}
+
+function _purchaseActive(purchase) {
+ updatePurchase(purchase, {status: 'active'});
+}
+
+function _purchaseExtend(purchase, monthCount) {
+ var expiration = getPurchase(purchase).paidThrough;
+ for (var i = monthCount; i > 0; i--) {
+ expiration = nextMonth(expiration);
+ }
+ // paying your invoice always makes you current.
+ if (expiration < new Date) {
+ expiration = nextMonth(new Date);
+ }
+ updatePurchase(purchase, {paidThrough: expiration});
+}
+
+function _doPost(url, body) {
+ try {
+ var ret = urlPost(url, body);
+ } catch (e) {
+ if (e.javaException) {
+ net.appjet.oui.exceptionlog.apply(e.javaException);
+ }
+ return { error: e };
+ }
+ return { value: ret };
+}
+
+function _doPaypalNvpPost(properties0) {
+ return {
+ status: 'failure',
+ errorMessage: "Billing has been discontinued. No new services may be purchased."
+ }
+ // var properties = {
+ // USER: _USER(),
+ // PWD: _PWD(),
+ // SIGNATURE: _SIGNATURE(),
+ // VERSION: "56.0"
+ // }
+ // eachProperty(properties0, function(k, v) {
+ // if (v !== undefined) {
+ // properties[k] = v;
+ // }
+ // })
+ // log({'type': 'api call', 'value': properties});
+ // var ret = _doPost(_paypalApiUrl(), properties);
+ // if (ret.error) {
+ // return {
+ // status: 'failure',
+ // exception: ret.error.javaException || ret.error,
+ // errorMessage: ret.error.message
+ // }
+ // }
+ // ret = ret.value;
+ // var paypalResponse = {};
+ // ret.content.split("&").forEach(function(x) {
+ // var parts = x.split("=");
+ // paypalResponse[decodeURIComponent(parts[0])] =
+ // decodeURIComponent(parts[1]);
+ // })
+ //
+ // var res = paypalResponse;
+ // log(res)
+ // if (res.ACK == "Success" || res.ACK == "SuccessWithWarning") {
+ // return {
+ // status: 'success',
+ // response: res
+ // }
+ // } else {
+ // errors = [];
+ // for (var i = 0; res['L_LONGMESSAGE'+i]; ++i) {
+ // errors.push(res['L_LONGMESSAGE'+i]);
+ // }
+ // return {
+ // status: 'failure',
+ // errorMessage: errors.join(", "),
+ // errorMessages: errors,
+ // response: res
+ // }
+ // }
+}
+
+// status -> 'completion', 'bad', 'redundant', 'possible_fraud'
+function handlePaypalNotification() {
+ var content = (typeof(request.content) == 'string' ? request.content : undefined);
+ if (! content) {
+ return new BillingResult('bad', "no content");
+ }
+ log({'type': 'paypal-notification', 'content': content});
+ var params = {};
+ content.split("&").forEach(function(x) {
+ var parts = x.split("=");
+ params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
+ });
+ var txnId = params.txn_id;
+ var properties = [];
+ for(var i in params) {
+ properties.push(i+" -> "+params[i]);
+ }
+ var debugString = properties.join(", ");
+ log({'type': 'parsed-paypal-notification', 'value': debugString});
+ var transaction = getTransactionByExternalId(txnId);
+ log({'type': 'notification-transaction', 'value': (transaction || {})});
+ if (_RECEIVER() != params.receiver_email) {
+ return new BillingResult('possible_fraud', debugString);
+ }
+ if (params.payment_status == "Completed" && transaction &&
+ (transaction.status == 'pending' || transaction.status == 'new')) {
+ var ret = _doPost(_paypalWebUrl(), "cmd=_notify-validate&"+content);
+ if (ret.error || ret.value.content != "VERIFIED") {
+ return new BillingResult('possible_fraud', debugString);
+ }
+ var invoice = getInvoice(params.invoice);
+ if (invoice.amt != dollarsToCents(params.mc_gross)) {
+ return new BillingResult('possible_fraud', debugString);
+ }
+
+ sqlcommon.inTransaction(function () {
+ _transactionSuccess(transaction.id, txnId, "via eCheck");
+ _invoicePaid(invoice.id);
+ _purchaseActive(invoice.purchase);
+ });
+ var purchase = getPurchase(invoice.purchase);
+ return new BillingResult('completion', debugString, null,
+ new PurchaseInfo(params.custom,
+ invoice.id,
+ transaction.id,
+ params.txn_id,
+ purchase.id,
+ centsToDollars(invoice.amt),
+ purchase.couponCode,
+ purchase.time,
+ undefined));
+ } else {
+ return new BillingResult('redundant', debugString);
+ }
+}
+
+function _expressCheckoutCustom(invoiceId, transactionId) {
+ return md5("zimki_sucks"+invoiceId+transactionId);
+}
+
+function PurchaseInfo(custom, invoiceId, transactionId, paypalId, purchaseId, dollars, couponCode, time, token, description) {
+ this.__defineGetter__("custom", function() { return custom });
+ this.__defineGetter__("invoiceId", function() { return invoiceId });
+ this.__defineGetter__("transactionId", function() { return transactionId });
+ this.__defineGetter__("paypalId", function() { return paypalId });
+ this.__defineGetter__("purchaseId", function() { return purchaseId });
+ this.__defineGetter__("cost", function() { return dollars });
+ this.__defineGetter__("couponCode", function() { return couponCode });
+ this.__defineGetter__("time", function() { return time });
+ this.__defineGetter__("token", function() { return token });
+ this.__defineGetter__("description", function() { return description });
+}
+
+function PayerInfo(paypalResult) {
+ this.__defineGetter__("payerId", function() { return paypalResult.response.PAYERID });
+ this.__defineGetter__("email", function() { return paypalResult.response.EMAIL });
+ this.__defineGetter__("businessName", function() { return paypalResult.response.BUSINESS });
+ this.__defineGetter__("nameSalutation", function() { return paypalResult.response.SALUTATION });
+ this.__defineGetter__("nameFirst", function() { return paypalResult.response.FIRSTNAME });
+ this.__defineGetter__("nameMiddle", function() { return paypalResult.response.MIDDLENAME });
+ this.__defineGetter__("nameLast", function() { return paypalResult.response.LASTNAME });
+}
+
+function BillingResult(status, debug, errorField, purchaseInfo, payerInfo) {
+ this.__defineGetter__("status", function() { return status });
+ this.__defineGetter__("debug", function() { return debug });
+ this.__defineGetter__("errorField", function() { return errorField });
+ this.__defineGetter__("purchaseInfo", function() { return purchaseInfo });
+ this.__defineGetter__("payerInfo", function() { return payerInfo });
+}
+
+function dollarsToCents(dollars) {
+ return Math.round(Number(dollars)*100);
+}
+
+function centsToDollars(cents) {
+ return Math.round(Number(cents)) / 100;
+}
+
+function verifyDollars(dollars) {
+ return Math.round(Number(dollars)*100)/100;
+}
+
+function beginExpressPurchase(invoiceId, customerId, productId, dollars, couponCode, successUrl, failureUrl, notifyUrl, authorizeOnly) {
+ var cents = dollarsToCents(dollars);
+ var time = new Date();
+ var purchaseId;
+ var transactionid;
+ if (! authorizeOnly) {
+ try {
+ sqlcommon.inTransaction(function() {
+ purchaseId = _newPurchase(customerId, productId, cents, couponCode);
+ updateInvoice(invoiceId, {purchase: purchaseId, amt: cents});
+ transactionId = _newTransaction(customerId, cents);
+ _newAdjustment(transactionId, invoiceId, cents);
+ });
+ } catch (e) {
+ if (e instanceof BillingResult) { return e; }
+ throw e;
+ }
+ }
+
+ var paypalResult =
+ _setExpressCheckout(invoiceId, transactionId, cents,
+ successUrl, failureUrl, notifyUrl, authorizeOnly);
+
+ if (paypalResult.status == 'success') {
+ var token = paypalResult.response.TOKEN;
+ return new BillingResult('success', paypalResult, null, new PurchaseInfo(
+ _expressCheckoutCustom(invoiceId, transactionId),
+ invoiceId,
+ transactionId,
+ undefined,
+ purchaseId,
+ verifyDollars(dollars),
+ couponCode,
+ time,
+ token));
+ } else {
+ return new BillingResult('failure', paypalResult);
+ }
+}
+
+function _setExpressCheckout(invoiceId, transactionId, cents, successUrl, failureUrl, notifyUrl, authorizeOnly) {
+ var properties = {
+ INVNUM: invoiceId,
+
+ METHOD: 'SetExpressCheckout',
+ CUSTOM:
+ _expressCheckoutCustom(invoiceId, transactionId),
+ MAXAMT: centsToDollars(cents),
+ RETURNURL: successUrl,
+ CANCELURL: failureUrl,
+ NOTIFYURL: notifyUrl,
+ NOSHIPPING: 1,
+ PAYMENTACTION: (authorizeOnly ? 'Authorization' : 'Sale'),
+
+ AMT: centsToDollars(cents)
+ }
+
+ return _doPaypalNvpPost(properties);
+}
+
+function continueExpressPurchase(purchaseInfo, authorizeOnly) {
+ var paypalResult = _getExpressCheckoutDetails(purchaseInfo.token, authorizeOnly)
+ if (paypalResult.status == 'success') {
+ if (! authorizeOnly) {
+ if (paypalResult.response.INVNUM != purchaseInfo.invoiceId) {
+ return new BillingResult('failure', "invoice id mismatch");
+ }
+ }
+ if (paypalResult.response.CUSTOM !=
+ _expressCheckoutCustom(purchaseInfo.invoiceId, purchaseInfo.transactionId)) {
+ return new BillingResult('failure', "custom mismatch");
+ }
+ return new BillingResult('success', paypalResult, null, null, new PayerInfo(paypalResult));
+ } else {
+ return new BillingResult('failure', paypalResult);
+ }
+}
+
+function _getExpressCheckoutDetails(token, authorizeOnly) {
+ var properties = {
+ METHOD: 'GetExpresscheckoutDetails',
+ TOKEN: token,
+ }
+
+ return _doPaypalNvpPost(properties);
+}
+
+function completeExpressPurchase(purchaseInfo, payerInfo, notifyUrl, authorizeOnly) {
+ var paypalResult = _doExpressCheckoutPayment(purchaseInfo, payerInfo, notifyUrl, authorizeOnly);
+
+ if (paypalResult.status == 'success') {
+ if (paypalResult.response.PAYMENTSTATUS == 'Completed') {
+ if (! authorizeOnly) {
+ sqlcommon.inTransaction(function() {
+ _transactionSuccess(purchaseInfo.transactionId,
+ paypalResult.response.TRANSACTIONID, "via PayPal");
+ _invoicePaid(purchaseInfo.invoiceId);
+ _purchaseActive(purchaseInfo.purchaseId);
+ });
+ }
+ return new BillingResult('success', paypalResult);
+ } else if (paypalResult.response.PAYMENTSTATUS == 'Pending') {
+ if (! authorizeOnly) {
+ sqlcommon.inTransaction(function() {
+ _transactionPending(purchaseInfo.transactionId,
+ paypalResult.response.TRANSACTIONID);
+ });
+ }
+ return new BillingResult('pending', paypalResult);
+ }
+ } else {
+ if (! authorizeOnly) {
+ sqlcommon.inTransaction(function() {
+ _transactionFailure(purchaseInfo.transactionId,
+ (paypalResult.response ?
+ paypalResult.response.TRANSACTIONID || "" :
+ ""));
+ });
+ }
+ return new BillingResult('failure', paypalResult);
+ }
+}
+
+function _doExpressCheckoutPayment(purchaseInfo, payerInfo, notifyUrl, authorizeOnly) {
+ var properties = {
+ METHOD: 'DoExpressCheckoutPayment',
+ TOKEN: purchaseInfo.token,
+ PAYMENTACTION: (authorizeOnly ? 'Authorization' : 'Sale'),
+
+ NOTIFYURL: notifyUrl,
+
+ PAYERID: payerInfo.payerId,
+
+ AMT: verifyDollars(purchaseInfo.cost), // dollars
+ INVNUM: purchaseInfo.invoiceId,
+ CUSTOM:
+ _expressCheckoutCustom(purchaseInfo.invoiceId, purchaseInfo.transactionId)
+ }
+
+ return _doPaypalNvpPost(properties);
+}
+
+// which field has error? and, is it not user-correctable?
+var _directErrorCodes = {
+ '10502': ['cardExpiration'],
+ '10504': ['cardCvv'],
+ '10505': ['addressStreet', true],
+ '10508': ['cardExpiration'],
+ '10510': ['cardType'],
+ '10512': ['nameFirst'],
+ '10513': ['nameLast'],
+ '10519': ['cardNumber'],
+ '10521': ['cardNumber'],
+ '10527': ['cardNumber'],
+ '10534': ['cardNumber', true],
+ '10535': ['cardNumber'],
+ '10536': ['invoiceId', true],
+ '10537': ['addressCountry', true],
+ '10540': ['addressStreet', true],
+ '10541': ['cardNumber', true],
+ '10554': ['address', true],
+ '10555': ['address', true],
+ '10556': ['address', true],
+ '10561': ['address'],
+ '10562': ['cardExpiration'],
+ '10563': ['cardExpiration'],
+ '10565': ['addressCountry'],
+ '10566': ['cardType'],
+ '10571': ['cardCvv'],
+ '10701': ['address'],
+ '10702': ['addressStreet'],
+ '10703': ['addressStreet2'],
+ '10704': ['addressCity'],
+ '10705': ['addressState'],
+ '10706': ['addressZip'],
+ '10707': ['addressCountry'],
+ '10708': ['address'],
+ '10709': ['addressStreet'],
+ '10710': ['addressCity'],
+ '10711': ['addressState'],
+ '10712': ['addressZip'],
+ '10713': ['addressCountry'],
+ '10714': ['address'],
+ '10715': ['addressState'],
+ '10716': ['addressZip'],
+ '10717': ['addressZip'],
+ '10718': ['addressCity,addressState'],
+ '10748': ['cardCvv'],
+ '10752': ['card'],
+ '10756': ['address,card'],
+ '10759': ['cardNumber'],
+ '10762': ['cardCvv'],
+ '11611': function(response) {
+ var avsCode = response.AVSCODE;
+ var cvv2Match = response.CVV2MATCH;
+ var errorFields = [];
+ switch (avsCode) {
+ case 'N': case 'C': case 'A': case 'B':
+ case 'R': case 'S': case 'U': case 'G':
+ case 'I': case 'E':
+ errorFields.push('address');
+ }
+ switch (cvv2Match) {
+ case 'N':
+ errorFields.push('cardCvv');
+ }
+ return [errorFields.join(",")];
+ },
+ '15004': ['cardCvv'],
+ '15005': ['cardNumber'],
+ '15006': ['cardNumber'],
+ '15007': ['cardNumber']
+}
+
+function authorizePurchase(payinfo, notifyUrl) {
+ return directPurchase(undefined, undefined, undefined, 1, undefined, payinfo, notifyUrl, true);
+}
+
+function directPurchase(invoiceId, customerId, productId, dollars, couponCode, payinfo, notifyUrl, authorizeOnly) {
+ var time = new Date();
+ var cents = dollarsToCents(dollars);
+
+ var purchaseId, transactionId;
+
+ if (! authorizeOnly) {
+ try {
+ sqlcommon.inTransaction(function() {
+ purchaseId = _newPurchase(customerId, productId, cents, couponCode);
+ updateInvoice(invoiceId, {purchase: purchaseId, amt: cents});
+ transactionId = _newTransaction(customerId, cents);
+ _newAdjustment(transactionId, invoiceId, cents);
+ });
+ } catch (e) {
+ if (e instanceof BillingResult) { return e; }
+ if (e.javaException || e.rhinoException) {
+ throw e.javaException || e.rhinoException;
+ }
+ throw e;
+ }
+ }
+
+ var paypalResult = _doDirectPurchase(invoiceId, cents, payinfo, notifyUrl, authorizeOnly);
+
+ if (paypalResult.status == 'success') {
+ if (! authorizeOnly) {
+ sqlcommon.inTransaction(function() {
+ _transactionSuccess(transactionId,
+ paypalResult.response.TRANSACTIONID,
+ payinfo.cardType+" ending in "+payinfo.cardNumber.substr(-4));
+ _invoicePaid(invoiceId);
+ _purchaseActive(purchaseId);
+ });
+ }
+ return new BillingResult('success', paypalResult, null, new PurchaseInfo(
+ undefined,
+ invoiceId,
+ transactionId,
+ paypalResult.response.TRANSACTIONID,
+ purchaseId,
+ verifyDollars(dollars),
+ couponCode,
+ time,
+ undefined));
+ } else {
+ if (! authorizeOnly) {
+ sqlcommon.inTransaction(function() {
+ _transactionFailure(transactionId,
+ (paypalResult.response ?
+ paypalResult.response.TRANSACTIONID || "":
+ ""));
+ });
+ }
+ return new BillingResult('failure', paypalResult, _getErrorCodes(paypalResult.response));
+ }
+}
+
+function _getErrorCodes(paypalResponse) {
+ var errorCodes = {userErrors: [], permanentErrors: []};
+ if (! paypalResponse) {
+ return undefined;
+ }
+ for (var i = 0; paypalResponse['L_ERRORCODE'+i]; ++i) {
+ var code = paypalResponse['L_ERRORCODE'+i];
+ var errorField = _directErrorCodes[code];
+ if (typeof(errorField) == 'function') {
+ errorField = errorField(paypalResponse);
+ }
+ if (errorField && errorField[1]) {
+ Array.prototype.push.apply(errorCodes.permanentErrors, errorField[0].split(","));
+ } else if (errorField) {
+ Array.prototype.push.apply(errorCodes.userErrors, errorField[0].split(","));
+ }
+ }
+ return errorCodes;
+}
+
+function _doDirectPurchase(invoiceId, cents, payinfo, notifyUrl, authorizeOnly) {
+ var properties = {
+ INVNUM: invoiceId,
+
+ METHOD: 'DoDirectPayment',
+ PAYMENTACTION: (authorizeOnly ? 'Authorization' : 'Sale'),
+ IPADDRESS: request.clientAddr,
+ NOTIFYURL: notifyUrl,
+
+ CREDITCARDTYPE: payinfo.cardType,
+ ACCT: payinfo.cardNumber,
+ EXPDATE: payinfo.cardExpiration,
+ CVV2: payinfo.cardCvv,
+
+ SALUTATION: payinfo.nameSalutation,
+ FIRSTNAME: payinfo.nameFirst,
+ MIDDLENAME: payinfo.nameMiddle,
+ LASTNAME: payinfo.nameLast,
+ SUFFIX: payinfo.nameSuffix,
+
+ STREET: payinfo.addressStreet,
+ STREET2: payinfo.addressStreet2,
+ CITY: payinfo.addressCity,
+ STATE: payinfo.addressState,
+ COUNTRYCODE: payinfo.addressCountry,
+ ZIP: payinfo.addressZip,
+
+ AMT: centsToDollars(cents)
+ }
+
+ return _doPaypalNvpPost(properties);
+}
+
+// function directAuthorization(payInfo, dollars, notifyUrl) {
+// var paypalResult = _doDirectPurchase(undefined, dollarsToCents(dollars), payInfo, notifyUrl, true);
+// if (paypalResult.status == 'success') {
+// return new BillingResult('success', paypalResult, null, new PurchaseInfo(
+// undefined,
+// undefined,
+// paypalResult.response.TRANSACTIONID,
+// undefined,
+// verifyDollars(dollars),
+// undefined,
+// undefined,
+// undefined));
+// } else {
+// return new BillingResult('failure', paypalResult, _getErrorCodes(paypalResult.response));
+// }
+// }
+
+function asyncRecurringPurchase(invoiceId, purchaseId, oldTransactionId, paymentInfo, dollars, monthCount, notifyUrl) {
+ var time = new Date();
+ var cents = dollarsToCents(dollars);
+
+ var purchase, transactionId;
+
+ try {
+ sqlcommon.inTransaction(function() {
+ // purchaseId = _newPurchase(customerId, productId, cents, couponCode);
+ purchase = getPurchase(purchaseId);
+ updateInvoice(invoiceId, {purchase: purchaseId, amt: cents});
+ transactionId = _newTransaction(purchase.customer, cents);
+ _newAdjustment(transactionId, invoiceId, cents);
+ });
+ } catch (e) {
+ if (e instanceof BillingResult) { return e; }
+ if (e.rhinoException) {
+ throw e.rhinoException;
+ }
+ throw e;
+ }
+
+ // do transaction using previous transaction as template
+ var paypalResult;
+ if (cents == 0) {
+ // can't actually charge nothing, so fake it.
+ paypalResult = { status: 'success', response: { TRANSACTIONID: null }}
+ } else {
+ paypalResult = _doReferenceTransaction(invoiceId, cents, oldTransactionId, notifyUrl);
+ }
+
+ if (paypalResult.status == 'success') {
+ sqlcommon.inTransaction(function() {
+ _transactionSuccess(transactionId,
+ paypalResult.response.TRANSACTIONID,
+ paymentInfo);
+ _invoicePaid(invoiceId);
+ _purchaseActive(purchaseId);
+ _purchaseExtend(purchaseId, monthCount);
+ });
+ return new BillingResult('success', paypalResult, null, new PurchaseInfo(
+ undefined,
+ invoiceId,
+ transactionId,
+ paypalResult.response.TRANSACTIONID,
+ purchaseId,
+ verifyDollars(dollars),
+ undefined,
+ time,
+ undefined));
+ } else {
+ sqlcommon.inTransaction(function() {
+ _transactionFailure(transactionId,
+ (paypalResult.response ?
+ paypalResult.response.TRANSACTIONID || "":
+ ""));
+ });
+ return new BillingResult('failure', paypalResult, _getErrorCodes(paypalResult.response));
+ }
+}
+
+function _doReferenceTransaction(invoiceId, cents, transactionId, notifyUrl) {
+ var properties = {
+ METHOD: 'DoReferenceTransaction',
+ PAYMENTACTION: 'Sale',
+
+ REFERENCEID: transactionId,
+ AMT: centsToDollars(cents),
+ INVNUM: invoiceId
+ }
+
+ return _doPaypalNvpPost(properties);
+}
219 etherpad/src/etherpad/billing/fields.js
@@ -0,0 +1,219 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// Taken from paypal's form
+var countryList = [
+ ["US", "United States"],
+ ["AL", "Albania"],
+ ["DZ", "Algeria"],
+ ["AD", "Andorra"],
+ ["AO", "Angola"],
+ ["AI", "Anguilla"],
+ ["AG", "Antigua and Barbuda"],
+ ["AR", "Argentina"],
+ ["AM", "Armenia"],
+ ["AW", "Aruba"],
+ ["AU", "Australia"],
+ ["AT", "Austria"],
+ ["AZ", "Azerbaijan Republic"],
+ ["BS", "Bahamas"],
+ ["BH", "Bahrain"],
+ ["BB", "Barbados"],
+ ["BE", "Belgium"],
+ ["BZ", "Belize"],
+ ["BJ", "Benin"],
+ ["BM", "Bermuda"],
+ ["BT", "Bhutan"],
+ ["BO", "Bolivia"],
+ ["BA", "Bosnia and Herzegovina"],
+ ["BW", "Botswana"],
+ ["BR", "Brazil"],
+ ["VG", "British Virgin Islands"],
+ ["BN", "Brunei"],
+ ["BG", "Bulgaria"],
+ ["BF", "Burkina Faso"],
+ ["BI", "Burundi"],
+ ["KH", "Cambodia"],
+ ["CA", "Canada"],
+ ["CV", "Cape Verde"],
+ ["KY", "Cayman Islands"],
+ ["TD", "Chad"],
+ ["CL", "Chile"],
+ ["C2", "China"],
+ ["CO", "Colombia"],
+ ["KM", "Comoros"],
+ ["CK", "Cook Islands"],
+ ["CR", "Costa Rica"],
+ ["HR", "Croatia"],
+ ["CY", "Cyprus"],
+ ["CZ", "Czech Republic"],
+ ["CD", "Democratic Republic of the Congo"],
+ ["DK", "Denmark"],
+ ["DJ", "Djibouti"],
+ ["DM", "Dominica"],
+ ["DO", "Dominican Republic"],
+ ["EC", "Ecuador"],
+ ["SV", "El Salvador"],
+ ["ER", "Eritrea"],
+ ["EE", "Estonia"],
+ ["ET", "Ethiopia"],
+ ["FK", "Falkland Islands"],
+ ["FO", "Faroe Islands"],
+ ["FM", "Federated States of Micronesia"],
+ ["FJ", "Fiji"],
+ ["FI", "Finland"],
+ ["FR", "France"],
+ ["GF", "French Guiana"],
+ ["PF", "French Polynesia"],
+ ["GA", "Gabon Republic"],
+ ["GM", "Gambia"],
+ ["DE", "Germany"],
+ ["GI", "Gibraltar"],
+ ["GR", "Greece"],
+ ["GL", "Greenland"],
+ ["GD", "Grenada"],
+ ["GP", "Guadeloupe"],
+ ["GT", "Guatemala"],
+ ["GN", "Guinea"],
+ ["GW", "Guinea Bissau"],
+ ["GY", "Guyana"],
+ ["HN", "Honduras"],
+ ["HK", "Hong Kong"],
+ ["HU", "Hungary"],
+ ["IS", "Iceland"],
+ ["IN", "India"],
+ ["ID", "Indonesia"],
+ ["IE", "Ireland"],
+ ["IL", "Israel"],
+ ["IT", "Italy"],
+ ["JM", "Jamaica"],
+ ["JP", "Japan"],
+ ["JO", "Jordan"],
+ ["KZ", "Kazakhstan"],
+ ["KE", "Kenya"],
+ ["KI", "Kiribati"],
+ ["KW", "Kuwait"],
+ ["KG", "Kyrgyzstan"],
+ ["LA", "Laos"],
+ ["LV", "Latvia"],
+ ["LS", "Lesotho"],
+ ["LI", "Liechtenstein"],
+ ["LT", "Lithuania"],
+ ["LU", "Luxembourg"],
+ ["MG", "Madagascar"],
+ ["MW", "Malawi"],
+ ["MY", "Malaysia"],
+ ["MV", "Maldives"],
+ ["ML", "Mali"],
+ ["MT", "Malta"],
+ ["MH", "Marshall Islands"],
+ ["MQ", "Martinique"],
+ ["MR", "Mauritania"],
+ ["MU", "Mauritius"],
+ ["YT", "Mayotte"],
+ ["MX", "Mexico"],
+ ["MN", "Mongolia"],
+ ["MS", "Montserrat"],
+ ["MA", "Morocco"],
+ ["MZ", "Mozambique"],
+ ["NA", "Namibia"],
+ ["NR", "Nauru"],
+ ["NP", "Nepal"],
+ ["NL", "Netherlands"],
+ ["AN", "Netherlands Antilles"],
+ ["NC", "New Caledonia"],
+ ["NZ", "New Zealand"],
+ ["NI", "Nicaragua"],
+ ["NE", "Niger"],
+ ["NU", "Niue"],
+ ["NF", "Norfolk Island"],
+ ["NO", "Norway"],
+ ["OM", "Oman"],
+ ["PW", "Palau"],
+ ["PA", "Panama"],
+ ["PG", "Papua New Guinea"],
+ ["PE", "Peru"],
+ ["PN", "Pitcairn Islands"],
+ ["PL", "Poland"],
+ ["PT", "Portugal"],
+ ["QA", "Qatar"],
+ ["CG", "Republic of the Congo"],
+ ["RE", "Reunion"],
+ ["RO", "Romania"],
+ ["RU", "Russia"],
+ ["VC", "Saint Vincent and the Grenadines"],
+ ["WS", "Samoa"],
+ ["SM", "San Marino"],
+ ["ST", "São Tomé and Príncipe"],
+ ["SA", "Saudi Arabia"],
+ ["SN", "Senegal"],
+ ["SC", "Seychelles"],
+ ["SL", "Sierra Leone"],
+ ["SG", "Singapore"],
+ ["SK", "Slovakia"],
+ ["SI", "Slovenia"],
+ ["SB", "Solomon Islands"],
+ ["SO", "Somalia"],
+ ["ZA", "South Africa"],
+ ["KR", "South Korea"],
+ ["ES", "Spain"],
+ ["LK", "Sri Lanka"],
+ ["SH", "St. Helena"],
+ ["KN", "St. Kitts and Nevis"],
+ ["LC", "St. Lucia"],
+ ["PM", "St. Pierre and Miquelon"],
+ ["SR", "Suriname"],
+ ["SJ", "Svalbard and Jan Mayen Islands"],
+ ["SZ", "Swaziland"],
+ ["SE", "Sweden"],
+ ["CH", "Switzerland"],
+ ["TW", "Taiwan"],
+ ["TJ", "Tajikistan"],
+ ["TZ", "Tanzania"],
+ ["TH", "Thailand"],
+ ["TG", "Togo"],
+ ["TO", "Tonga"],
+ ["TT", "Trinidad and Tobago"],
+ ["TN", "Tunisia"],
+ ["TR", "Turkey"],
+ ["TM", "Turkmenistan"],
+ ["TC", "Turks and Caicos Islands"],
+ ["TV", "Tuvalu"],
+ ["UG", "Uganda"],
+ ["UA", "Ukraine"],
+ ["AE", "United Arab Emirates"],
+ ["GB", "United Kingdom"],
+ ["UY", "Uruguay"],
+ ["VU", "Vanuatu"],
+ ["VA", "Vatican City State"],
+ ["VE", "Venezuela"],
+ ["VN", "Vietnam"],
+ ["WF", "Wallis and Futuna Islands"],
+ ["YE", "Yemen"],
+ ["ZM", "Zambia"],
+];
+
+var usaStateList = [
+ "", "AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DC", "DE",
+ "FL", "GA", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA",
+ "MA", "MD", "ME", "MI", "MN", "MO", "MS", "MT", "NC", "ND",
+ "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA",
+ "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WI",
+ "WV", "WY", "AA", "AE", "AP", "AS", "FM", "GU", "MH", "MP",
+ "PR", "PW", "VI"
+];
+
422 etherpad/src/etherpad/billing/team_billing.js
<
@@ -0,0 +1,422 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import("execution");
+import("exceptionutils");
+import("sqlbase.sqlobj");
+import("sqlbase.sqlcommon.inTransaction");
+
+import("etherpad.billing.billing");
+import("etherpad.globals");
+import("etherpad.log");
+import("etherpad.pro.domains");
+import("etherpad.pro.pro_quotas");
+import("etherpad.store.checkout");
+import("etherpad.utils.renderTemplateAsString");
+
+jimport("java.lang.System.out.println");
+
+function recurringBillingNotifyUrl() {
+ return "";
+}
+
+function _billing() {
+ if (! appjet.cache.billing) {
+ appjet.cache.billing = {};
+ }
+ return appjet.cache.billing;
+}
+
+function _lpad(str, width, padDigit) {
+ str = String(str);
+ padDigit = (padDigit === undefined ? ' ' : padDigit);
+ var count = width - str.length;
+ var prepend = []
+ for (var i = 0; i < count; ++i) {
+ prepend.push(padDigit);
+ }
+ return prepend.join("")+str;
+}
+
+// utility functions
+
+function _dayToDateTime(date) {
+ return [date.getFullYear(), _lpad(date.getMonth()+1, 2, '0'), _lpad(date.getDate(), 2, '0')].join("-");
+}
+
+function _createInvoice(subscription) {
+ var maxUsers = getMaxUsers(subscription.customer);
+ var invoice = inTransaction(function() {
+ var invoiceId = billing.createInvoice();
+ billing.updateInvoice(
+ invoiceId,
+ {purchase: subscription.id,
+ amt: billing.dollarsToCents(calculateSubscriptionCost(maxUsers, subscription.coupon)),
+ users: maxUsers});
+ return billing.getInvoice(invoiceId);
+ });
+ if (invoice) {
+ resetMaxUsers(subscription.customer)
+ }
+ return invoice;
+}
+
+function getExpiredSubscriptions(date) {
+ return sqlobj.selectMulti('billing_purchase',
+ {type: 'subscription',
+ status: 'active',
+ paidThrough: ['<', _dayToDateTime(date)]});
+}
+
+function getAllSubscriptions() {
+ return sqlobj.selectMulti('billing_purchase', {type: 'subscription', status: 'active'});
+}
+
+function getSubscriptionForCustomer(customerId) {
+ return sqlobj.selectSingle('billing_purchase',
+ {type: 'subscription',
+ customer: customerId});
+}
+
+function getOrCreateInvoice(subscription) {
+ return inTransaction(function() {
+ var existingInvoice =
+ sqlobj.selectSingle('billing_invoice',
+ {purchase: subscription.id, status: 'pending'});
+ if (existingInvoice) {
+ return existingInvoice;
+ } else {
+ return _createInvoice(subscription);
+ }
+ });
+}
+
+function getLatestPendingInvoice(subscriptionId) {
+ return sqlobj.selectMulti('billing_invoice',