diff --git site/app/config/constants.php b/site/app/config/constants.php
index 7db78e8..cdec165 100644
--- site/app/config/constants.php
+++ site/app/config/constants.php
@@ -292,4 +292,24 @@ if(defined('ROOT')) {
*/
define('PASSWORD_RESET_EXPIRES', 3);
+/**
+ * We depend on the order of these licenses, so this list is append-only.
+ */
+global $licenses;
+$licenses = array(
+ 'Mozilla Public License, version 1.1' =>
+ 'http://www.mozilla.org/MPL/MPL-1.1.html',
+ 'GNU General Public License, version 2.0' =>
+ 'http://www.gnu.org/licenses/gpl-2.0.html',
+ 'GNU General Public License, version 3.0' =>
+ 'http://www.gnu.org/licenses/gpl-3.0.html',
+ 'GNU Lesser General Public License, version 2.1' =>
+ 'http://www.gnu.org/licenses/lgpl-2.1.html',
+ 'GNU Lesser General Public License, version 3.0' =>
+ 'http://www.gnu.org/licenses/lgpl-3.0.html',
+ 'MIT/X11 License' =>
+ 'http://www.opensource.org/licenses/mit-license.html',
+ 'BSD License' =>
+ 'http://www.opensource.org/licenses/bsd-license.html'
+);
?>
diff --git site/app/config/sql/remora.sql b/site/app/config/sql/remora.sql
index e332f78..4950e3d 100644
--- site/app/config/sql/remora.sql
+++ site/app/config/sql/remora.sql
@@ -56,6 +56,7 @@ CREATE TABLE `addons` (
`target_locale` varchar(25) default NULL,
`locale_disambiguation` varchar(255) default NULL,
`nominationdate` datetime NOT NULL default '0000-00-00 00:00:00',
+ `dev_agreement` tinyint(1) unsigned NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
@@ -614,6 +615,22 @@ CREATE TABLE `groups_users` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
+-- Table structure for table `licenses`
+--
+
+DROP TABLE IF EXISTS `licenses`;
+CREATE TABLE `licenses` (
+ `id` int(11) unsigned NOT NULL auto_increment,
+ `name` int(1) NOT NULL default '-1',
+ `text` int(11) unsigned default NULL,
+ `created` datetime NOT NULL default '0000-00-00 00:00:00',
+ `modified` datetime NOT NULL default '0000-00-00 00:00:00',
+ PRIMARY KEY (`id`),
+ KEY `text` (`text`),
+ CONSTRAINT `licenses_ibfk_1` FOREIGN KEY (`text`) REFERENCES `translations` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
-- Table structure for table `logs_parsed`
--
@@ -867,6 +884,7 @@ DROP TABLE IF EXISTS `versions`;
CREATE TABLE `versions` (
`id` int(11) unsigned NOT NULL auto_increment,
`addon_id` int(11) unsigned NOT NULL default '0',
+ `license_id` int(11) unsigned default NULL,
`version` varchar(255) NOT NULL default '',
`approvalnotes` text,
`releasenotes` int(11) unsigned default NULL,
@@ -875,8 +893,10 @@ CREATE TABLE `versions` (
PRIMARY KEY (`id`),
KEY `addon_id` (`addon_id`),
KEY `versions_ibfk_2` (`releasenotes`),
+ KEY `license_id` (`license_id`),
CONSTRAINT `versions_ibfk_1` FOREIGN KEY (`addon_id`) REFERENCES `addons` (`id`),
- CONSTRAINT `versions_ibfk_2` FOREIGN KEY (`releasenotes`) REFERENCES `translations` (`id`)
+ CONSTRAINT `versions_ibfk_2` FOREIGN KEY (`releasenotes`) REFERENCES `translations` (`id`),
+ CONSTRAINT `versions_ibfk_3` FOREIGN KEY (`license_id`) REFERENCES `licenses` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
diff --git site/app/controllers/addons_controller.php b/site/app/controllers/addons_controller.php
index 0d3c90f..d56a3d2 100644
--- site/app/controllers/addons_controller.php
+++ site/app/controllers/addons_controller.php
@@ -48,7 +48,7 @@ class AddonsController extends AppController
var $name = 'Addons';
var $beforeFilter = array('checkCSRF', 'getNamedArgs', '_checkSandbox');
var $uses = array('Addon', 'AddonTag', 'Addontype', 'Application',
- 'Feature', 'File', 'Platform', 'Preview', 'Tag', 'Translation',
+ 'Feature', 'File', 'License', 'Platform', 'Preview', 'Tag', 'Translation',
'Review', 'Version');
var $components = array('Amo', 'Image', 'Pagination', 'Session', 'Userfunc');
var $helpers = array('Html', 'Link', 'Time', 'Localization', 'Ajax', 'Number', 'Pagination');
diff --git site/app/controllers/components/developers.php b/site/app/controllers/components/developers.php
index 39bc2d9..1597cf3 100644
--- site/app/controllers/components/developers.php
+++ site/app/controllers/components/developers.php
@@ -1171,5 +1171,82 @@ class DevelopersComponent extends Object {
return $addontypes;
}
+
+ function getLicenses($version_id=null) {
+ // TODO: handle nulls
+ if ($version_id != null) {
+ $version = $this->controller->Version->findById($version_id);
+ $version = $version['Version'];
+ $license = $this->controller->License->findById($version['license_id']);
+ }
+
+ // Add 'Please Choose...' only if no license has been selected.
+ if (!isset($version['license_id'])) {
+ $licenses['null'] = array(
+ 'name' => ___('devcp_uploader_please_choose'),
+ 'selected' => True);
+ }
+
+ // Grab all the pre-approved licenses.
+ foreach ($this->controller->License->getNames() as $num => $builtin) {
+ $licenses['builtin_'.$num] = array(
+ 'name' => $builtin,
+ 'selected' => isset($license) && (string)$num === $license['License']['name']);
+ }
+
+ // The trans array holds translations for all the custom licenses we'll
+ // be displaying. `other` starts off empty, for creating new licenses.
+ $trans['other']['text']['en-US'] = '';
+
+ if ($version_id != null) {
+ // Find all the custom licenses in use by this add-on.
+ $q = "SELECT Version.version, Version.license_id
+ FROM versions AS Version INNER JOIN licenses AS License
+ ON Version.license_id = License.id
+ WHERE Version.addon_id = {$version['addon_id']}
+ AND Version.license_id IS NOT NULL
+ AND License.name = -1
+ GROUP BY License.id
+ ORDER BY Version.id DESC";
+ foreach ($this->controller->Version->execute($q) as $existing) {
+ $existing = $existing['Version'];
+ $t = ___('devcp_license_existing');
+ $val = 'existing_'.$existing['license_id'];
+ $licenses[$val] = array(
+ 'name' => sprintf($t, $version['addon_id'], $existing['version']),
+ 'selected' => $existing['license_id'] == $version['license_id']);
+ $trans[$val] = $this->controller->License->getAllTranslations($existing['license_id']);
+ }
+ }
+
+ $licenses['other'] = array('name' => ___('devcp_uploader_option_other'),
+ 'selected' => False);
+ return array($licenses, $trans);
+ }
+
+ function saveLicense($licenseData, $text, $params) {
+ $License = $this->controller->License;
+ if ($licenseData['name'] != 'null') {
+ $license = $licenseData['name'];
+ // If the license is pre-approved, we prefixed the id with builtin_.
+ if (preg_match('/^builtin_(\d+)$/', $license, $matches)) {
+ $license_id = $License->getBuiltin($matches[1]);
+ } else if ($license == 'other' ||
+ preg_match('/^existing_(\d+)$/', $license, $matches)) {
+ // If it's 'other', we need to create a new license.
+ if ($license == 'other') {
+ $data['License']['name'] = -1;
+ $License->save($data);
+ $license_id = $License->getLastInsertId();
+ } else {
+ $license_id = $matches[1];
+ }
+ // Save any changed translation text.
+ $localized['text'] = $text;
+ $License->saveTranslations($license_id, $params, $localized);
+ }
+ return $license_id;
+ }
+ }
}
?>
diff --git site/app/controllers/developers_controller.php b/site/app/controllers/developers_controller.php
index 2e7efca..58faaa0 100644
--- site/app/controllers/developers_controller.php
+++ site/app/controllers/developers_controller.php
@@ -37,11 +37,31 @@
* ***** END LICENSE BLOCK ***** */
require_once('Archive/Zip.php');
+/**
+ * Returns $object[$name], or $default if that's not set.
+ *
+ * If $name is a string of dot-separated names like 'foo.bar.baz',
+ * $object['foo']['bar']['baz'] will be returned. If any name
+ * along the way is not set, $default will be returned.
+ *
+ * If you want to fetch a name with embedded dots, look elsewhere.
+ */
+function getitem($object, $name, $default=null) {
+ $split = explode('.', $name, 2);
+ if (count($split) == 2) {
+ list($a, $b) = $split;
+ return isset($object[$a]) ? getitem($object[$a], $b, $default)
+ : $default;
+ } else {
+ return isset($object[$name]) ? $object[$name] : $default;
+ }
+}
+
class DevelopersController extends AppController
{
var $name = 'Developers';
var $uses = array('Addon', 'Addontype', 'Application', 'Approval', 'Appversion',
- 'EditorSubscription', 'Eventlog', 'File', 'Platform', 'Preview', 'Review',
+ 'EditorSubscription', 'Eventlog', 'File', 'License', 'Platform', 'Preview', 'Review',
'Tag', 'Translation', 'User', 'Version');
var $components = array('Amo', 'Developers', 'Editors', 'Email', 'Error',
'Image', 'Opensearch', 'Rdf', 'Src', 'Versioncompare');
@@ -90,6 +110,9 @@ class DevelopersController extends AppController
// Default "My Add-ons" sidebar data
$session = $this->Session->read('User');
$this->publish('all_addons', $this->Addon->getAddonsByUser($session['id']));
+
+ // Include the dev_agreement column on developer pages.
+ array_push($this->Addon->default_fields, 'dev_agreement');
}
/**
@@ -212,6 +235,7 @@ class DevelopersController extends AppController
*/
function _submitAddon() {
$this->publish('type', 'new');
+ $this->publish('hasAgreement', false);
$this->render('uploader');
}
@@ -242,9 +266,17 @@ class DevelopersController extends AppController
$session = $this->Session->read('User');
$this->Addon->saveAuthor($data['Addon']['id'], $session['id']);
+ // Save License
+ $license_id = $this->Developers->saveLicense(
+ $this->data['License'],
+ getitem($this->data, 'License.text'),
+ getitem($this->params, 'form.data.License'));
+ $this->Addon->saveField('dev_agreement', 1);
+
// Add Version
$this->Version->id = 0;
$data['Version']['addon_id'] = $data['Addon']['id'];
+ $data['Version']['license_id'] = $license_id;
$this->Version->save($data['Version']);
$data['Version']['id'] = $this->Version->getLastInsertId();
@@ -319,13 +351,30 @@ class DevelopersController extends AppController
return $this->Error->getJSONforError(sprintf(___('devcp_update_addon_version_exists_error'), $data['Version']['version'], $this->url('/developers/versions/addfile/'.$vcheck['Version']['id'])));
}
-
+ // Save License
+ if ($addon['Addon']['dev_agreement'] == true) {
+ // If we already have an agreement, we didn't show the license
+ // picker, so use the previously selected license.
+ global $valid_status;
+ $old_id = $this->Version->getVersionByAddonId($addon_id, $valid_status);
+ $oldVersion = $this->Version->findById($old_id);
+ $license_id = $oldVersion['Version']['license_id'];
+ } else {
+ $license_id = $this->Developers->saveLicense(
+ $this->data['License'],
+ getitem($this->data, 'License.text'),
+ getitem($this->params, 'form.data.License'));
+ }
+ $this->Addon->save(array('Addon' => array('id' => $addon_id,
+ 'dev_agreement' => 1)));
+
// Add Version
$this->Version->id = 0;
$data['Version']['addon_id'] = $addon_id;
+ $data['Version']['license_id'] = $license_id;
$this->Version->save($data['Version']);
$version_id = $this->Version->getLastInsertId();
-
+
// If add-on is public, cancel any pending files
if ($addon['Addon']['status'] == STATUS_PUBLIC) {
$this->Addon->execute("UPDATE files SET status = ".STATUS_SANDBOX." WHERE files.version_id IN (SELECT id FROM versions WHERE versions.addon_id={$addon_id}) AND files.status = ".STATUS_PENDING);
@@ -1022,6 +1071,9 @@ class DevelopersController extends AppController
$this->publish('version', $version['Version']['version']);
}
+ $addon = $this->Addon->findById($addon_id, array('Addon.dev_agreement'));
+ $this->publish('hasAgreement', $addon['Addon']['dev_agreement']);
+
$this->render('uploader');
}
@@ -1125,6 +1177,13 @@ class DevelopersController extends AppController
}
}
+ // Save license.
+ $license_id = $this->Developers->saveLicense(
+ $this->data['License'],
+ getitem($this->data, 'Version.License.text'),
+ getitem($this->params, 'form.data.Version.License'));
+ $this->Version->saveField('license_id', $license_id);
+
// flush cached add-on objects
if (QUERY_CACHE) $this->Addon->Cache->markListForFlush("addon:{$addon_id}");
@@ -1152,6 +1211,13 @@ class DevelopersController extends AppController
// Get all translations
$translations = $this->Version->getAllTranslations($version_id);
+ if (isset($version['Version']['license_id'])) {
+ $trans = $this->License->getAllTranslations($version['Version']['license_id']);
+ $translations['license_text'] = $trans['text'];
+ } else {
+ $translations['license_text'] = array();
+ }
+
$this->set('translations', $translations);
// Other info
@@ -1426,5 +1492,4 @@ class DevelopersController extends AppController
$this->render();
}
}
-
?>
diff --git site/app/locale/en_US/LC_MESSAGES/messages.po b/site/app/locale/en_US/LC_MESSAGES/messages.po
index cad4dab..d9ccaa6 100644
--- site/app/locale/en_US/LC_MESSAGES/messages.po
+++ site/app/locale/en_US/LC_MESSAGES/messages.po
@@ -286,6 +286,10 @@ msgstr "Browse %s"
msgid "addons_browse_categories_header_theme"
msgstr "Browse %1$s Themes :: %2$s Add-ons"
+#: views/addons/display.thtml:219
+msgid "addons_display_a_license_what"
+msgstr "What's this?"
+
#: views/reviews/display.thtml:221
msgid "addons_display_add_review"
msgstr "Add a review"
@@ -328,7 +332,11 @@ msgstr "Developer Comments"
msgid "addons_display_header_homepage"
msgstr "Homepage"
-#: views/addons/display.thtml:251
+#: views/addons/display.thtml:217 views/addons/versions.thtml:103
+msgid "addons_display_header_license"
+msgstr "Source Code License"
+
+#: views/addons/display.thtml:264
msgid "addons_display_header_reviews"
msgstr "Reviews"
@@ -2643,6 +2651,14 @@ msgstr "Remove Application Compatibility"
msgid "devcp_js_input_list_author"
msgstr "List as author in public listings"
+#: views/pages/js_constants.js.thtml:83
+msgid "devcp_js_license_select"
+msgstr "Please select a license."
+
+#: views/pages/js_constants.js.thtml:84
+msgid "devcp_js_license_text"
+msgstr "Please enter text for your license."
+
#. text in a for Author role in an add-on.
#: views/pages/js_constants.js.thtml:75
msgid "devcp_js_option_developer"
@@ -2670,6 +2686,12 @@ msgstr "Are you sure you wish to remove this author?"
msgid "devcp_js_upload_alert"
msgstr "You must select a file to upload."
+#. %1$s is an addon id, like 32.
+#. %2$s is a version number, like 3.5.
+#: controllers/components/developers.php:1213
+msgid "devcp_license_existing"
+msgstr "Custom license for add-on %1$s v%2$s"
+
#: views/elements/developers/localebox.thtml:44
msgid "devcp_localebox_header_localizedfields"
msgstr "Localized Fields"
@@ -3038,14 +3060,6 @@ msgstr ""
msgid "devcp_status_nominate_header"
msgstr "Add-on Nomination"
-#: views/developers/uploader.thtml:76
-msgid "devcp_submit_accept_dev_agreement"
-msgstr "I Accept"
-
-#: views/developers/uploader.thtml:75
-msgid "devcp_submit_decline_dev_agreement"
-msgstr "I Decline"
-
#: views/developers/dashboard.thtml:85
msgid "devcp_summary_lastversion"
msgstr "Latest Version:"
@@ -3264,6 +3278,10 @@ msgstr "Supported Platforms:"
msgid "devcp_uploader_label_upload_field"
msgstr "Add-on File: "
+#: controllers/components/developers.php:1222
+msgid "devcp_uploader_option_other"
+msgstr "Other"
+
#. %1$s is a number, %2$s is href="..." and should stay in the tag.
#: views/developers/uploader.thtml:142
msgid "devcp_uploader_p_pending_file"
@@ -3318,6 +3336,11 @@ msgstr "All"
msgid "devcp_uploader_platformtype_specific"
msgstr "Specific:"
+#. Used as first item in a .
+#: controllers/components/developers.php:1186
+msgid "devcp_uploader_please_choose"
+msgstr "Please Choose..."
+
#. %1$s is the add-on name, %2$s is the version number.
#: views/developers/uploader.thtml:57
msgid "devcp_uploader_title_file"
@@ -3460,6 +3483,10 @@ msgstr "Compatible Applications"
msgid "devcp_versions_edit_header_file"
msgstr "File Information"
+#: views/developers/versions_edit.thtml:189
+msgid "devcp_versions_edit_header_license"
+msgstr "License"
+
#. %s is the version number.
#: views/developers/versions_edit.thtml:53
msgid "devcp_versions_edit_header_manage"
@@ -3482,6 +3509,12 @@ msgstr "Delete File"
msgid "devcp_versions_edit_li_file"
msgstr "File %1$s (%2$s) created on %3$s and changed to %4$s on %5$s"
+#: views/developers/versions_edit.thtml:190
+msgid "devcp_versions_edit_license_description"
+msgstr ""
+"Please select the appropriate license for your add-on. This license "
+"specifies the rights you grant on your source code."
+
#: views/developers/versions_edit.thtml:111
msgid "devcp_versions_edit_no_files"
msgstr "No files found."
@@ -4725,6 +4758,10 @@ msgstr "Language Pack"
msgid "langtools_tableheader_language"
msgstr "Language"
+#: models/license.php:76
+msgid "license_custom"
+msgstr "Custom License"
+
#: views/users/emailchange.thtml:51 views/users/delete.thtml:53
#: views/users/delete.thtml:130 views/users/edit.thtml:59
#: views/reviews/flag.thtml:52
diff --git site/app/locale/en_US/pages/developer_agreement.thtml b/site/app/locale/en_US/pages/developer_agreement.thtml
index ba4c436..99fb644 100644
--- site/app/locale/en_US/pages/developer_agreement.thtml
+++ site/app/locale/en_US/pages/developer_agreement.thtml
@@ -1,15 +1,213 @@
-By uploading your add-on to this site, you agree that the following are true:
-
-
- you have the right to distribute this add-on, including any rights required for
- material that may be trademarked or copyrighted by someone else; and
- if any information about the user or usage of this add-on is collected or transmitted outside of
- the user's computer, the details of this collection will be provided in the description of the
- software, and you will provide a link to a privacy policy detailing how the information is
- managed and protected; and
- your add-on may be removed from the site, re-categorized, have its
- description or other information changed, or otherwise have its listing changed or removed, at the
- sole discretion of Mozilla and its authorized agents; and
- the descriptions and other data you provide about the add-on are true to the best
- of your knowledge.
-
+
+
+ If you upload add-on software or otherwise make information or material
+ available (each an “AMO
+ Contribution ”) by means of the services provided by Mozilla
+ Corporation (“Mozilla ”) via the
+ addons.mozilla.org website or any of its subdomains (“AMO
+ Services ”), you (“Contributor ”)
+ and the AMO Contribution are subject to the following terms, as well as
+ Mozilla’s Privacy Policy,
+ web site notices
+ and other policies, guidelines or requirements that may be posted on an AMO
+ Services web site (the “Terms ”). By acting as a
+ Contributor, you agree to these Terms. If you are an individual acting as a
+ representative of a corporation or other legal entity that wishes to use any
+ AMO Services, you represent and agree that you accept the Terms on behalf of
+ such entity. If you have any questions about these terms or the AMO Service,
+ please email:
+ amo-editors@mozilla.org
+
+
+
+
+ Responsibility Re AMO Contributions.
+ You represent and warrant that:
+
+
+
+ if any information about the user or usage of the AMO Contribution is
+ collected or transmitted outside of the user's computer, the details of this
+ collection will be provided in the description of the AMO Contribution and
+ you will provide a link to a privacy policy detailing how the information is
+ managed and protected;
+
+
+ the descriptions and other data you provide about the AMO Contribution are
+ true to the best of your knowledge; and
+
+
+ if the AMO Contribution is an add-on, such add-on is accompanied by an
+ accessible license that describes the rights of users;
+
+
+ the AMO Contribution does not violate any applicable law, regulation or
+ ordinance, nor infringe or misappropriate the rights of any third party.
+
+
+
+
+
+ Licenses.
+ In order to provide the AMO Service, you grant to Mozilla and its
+ Affiliates a non-exclusive, worldwide, royalty-free, sublicensable license
+ to distribute, transmit, reproduce, publish, publicly and privately
+ perform and display and otherwise use the AMO Contribution, including any
+ updates, solely in connection with Mozilla’s provision of the AMO
+ Services. Mozilla may also (i) bundle and/or package your AMO Contribution
+ with third party add-ons for delivery and promotion of the AMO
+ Contributions to users and (ii) maintain and/or update your AMO
+ Contribution for the purpose of providing compatibility with current and
+ new versions of Firefox or other Mozilla software that the AMO
+ Contribution interoperates with.
+
+
+
+
+ Management of AMO Services.
+ Mozilla may manage the AMO Services in a manner designed to facilitate the
+ integrity and proper functioning of the AMO Services without limitation or
+ liability. The following is a list of exemplary activities that Mozilla in
+ its sole discretion may undertake as part of its management of the AMO
+ Services: (i) monitor, test and review AMO Contributions; (ii) remove or
+ disable AMO Contributions or change their listing or description; (iii)
+ move an AMO Service and related AMO Contributions to a new domain or
+ website; (iv) rate limit, throttle and/or block requests or access to any
+ AMO Service; (v) use, modify or remove authentication requirements for
+ access to AMO Services; and (vi) collect statistics and other data
+ regarding your AMO Contribution, which may be made publicly available
+ through the AMO API (as described below).
+
+
+
+
+ AMO API .
+ As part of the AMO Services, Mozilla provides the addons.mozilla.org API
+ (“AMO API ”), which allows you to get
+ information about certain AMO Contributions distributed by Mozilla via the
+ AMO Service and is currently served via calls to
+ http://www.mozilla.com/en-US/about/legal.html .
+ You may use the AMO API solely to retrieve data made publicly available by
+ Mozilla via the AMO API, which data may be used solely for your own
+ reasonable business purposes or personal use. In addition to the
+ restrictions otherwise set forth in the Terms regarding AMO Services
+ generally, you agree that you are responsible for your use of and
+ contribution to the AMO API and you will not:
+
+
+
+ hide or mask from Mozilla the identity of your service as it uses the
+ AMO API, including by failing to follow required identification
+ conventions; or
+
+
+ use the AMO API for any application that replicates or attempts to
+ replicate the Mozilla AMO Service or experienc such thatexperience
+ unless your use of the AMO API is non-confusing. By non-confusing,
+ Mozilla means that people should always know with whom they are dealing
+ and where the information or software they are downloading came from.
+ Websites and software that are not produced by Mozilla shouldn’t imply,
+ either directly or by omission, that they are.
+
+
+
+
+
+ Ownership, Reservation of Rights.
+ You are welcome to use the AMO Services subject to these Terms, and
+ Mozilla grants you the right to do so. Mozilla and its licensors reserve
+ all other rights in the AMO Services. Further, nothing in the Terms shall
+ be deemed to grant you any right to use the trademarks, trade names,
+ service marks, or trade dress of Mozilla or its licensors and Mozilla
+ hereby reserves all right, title and interest therein. For information on
+ our trademarks, please see our
+ Trademark and Logo Usage Policies .
+
+
+
+
+
+ The AMO Services are provided “as-is”. Mozilla, its
+ contributors, licensors, and distributors, disclaim all warranties,
+ whether express or implied, including without limitation, implied
+ warranties of merchantability, fitness for a particular purpose and
+ non-infringement. Some jurisdictions do not allow the exclusion or
+ limitation of implied warranties, so this disclaimer may not apply to
+ you.
+
+
+
+
+
+
+ Except as required by law, Mozilla, its contributors, licensors, and
+ distributors will not be liable for any indirect, special, incidental,
+ consequential, punitive, or exemplary damages arising out of or in any way
+ relating to the use of AMO Services. The and their collective liability
+ under these Terms will not exceed $500 (five hundred dollars). Some
+ jurisdictions do not allow the exclusion or limitation of certain damages,
+ so this exclusion and limitation may not apply to you.
+
+
+
+
+
+ Changes to the Terms.
+ Mozilla may update these Terms as necessary from time to time. These Terms
+ may not be modified or cancelled without Mozilla’s written agreement.
+
+
+
+
+ Eligibility.
+ You represent that you are of legal age to form a binding contract and
+ that you not are a person barred from receiving or using the AMO Services
+ under the laws of any country, including the country in which you are
+ resident or from which you use the AMO Services.
+
+
+
+
+ Export Control.
+ The AMO Services are subject to all applicable export restrictions
+ including the export and import laws, restrictions and regulations of any
+ United States or foreign agency.
+
+
+
+
+ Miscellaneous.
+ These Terms are governed by the laws of the state of California, U.S.A.,
+ excluding its conflict of law provisions. If any portion of these Terms is
+ held to be invalid or unenforceable, the remaining portions will remain in
+ full force and effect. In the event of a conflict between a translated
+ version of these Terms and the English language version, the English
+ language version shall control. Mozilla’s subsidiaries and affiliates
+ shall be third party beneficiaries of these Terms, entitled to enforce and
+ rely upon the provisions hereof.
+
+
+
+
+ Termination.
+ You may terminate your use of the AMO Services at any time. Mozilla may
+ modify or discontinue the AMO Services at its sole discretion.
+
+
+
+
+
+
+ DEVELOPER LICENSE DISCLOSURE STATEMENT FOR ADD-ON UPLOAD/REGISTRATION PAGE:
+
+
+ For both your benefit and the benefit of users that download your add-on,
+ Mozilla requests that you identify the license terms applicable to use of your
+ add-on by users. Unless you specify otherwise, any updates to your add-on will
+ be assumed to be under the same license as that specified for your add-on.
+ Please select the applicable license terms from the list below or, if your
+ license terms are not listed, select “Other” and identify the
+ license terms in the dialog box provided. Please note that you must include an
+ accessible copy of your license terms with your add-on (such as in a parent
+ directory).
+
diff --git site/app/locale/en_US/pages/developer_faq.thtml b/site/app/locale/en_US/pages/developer_faq.thtml
new file mode 100644
index 0000000..46bc988
--- /dev/null
+++ site/app/locale/en_US/pages/developer_faq.thtml
@@ -0,0 +1,63 @@
+REFERENCES ABOUT OPEN SOURCE LICENSES
+
+ Do you need more information about the various open source licenses? Are you
+ confused as to which license you should select? What rights does a specific
+ license grant? While nothing replaces reading the full terms of a license,
+ below are some sites that contain information about some of the key open
+ source licenses that may help you sort out the differences between them. These
+ sites are being provided solely for your convenience and as a reference for
+ your personal use. These resources do not constitute legal advice nor should
+ they be used in lieu of such advice. Mozilla neither guarantees nor is
+ responsible for the content of these sites or your reliance on such content.
+
+
+
+ http://www.mozilla.org/MPL/
+
+
+ In addition to the full text of the Mozilla Public License
+ (&8220;MPL&8221;), this also provides an annotated version of the MPL and an
+ FAQ to help you if you want
+ to use or distribute code licensed under it.
+
+
+
+ http://developer.kde.org/documentation/licensing/licenses_summary.html
+
+
+
+ A table summarizing and comparing how some of the key open source licenses
+ treat distributions, proprietary software linking, and redistribution of
+ code with changes.
+
+
+
+ http://www.fsf.org/licensing/licenses/
+
+
+
+ Free Software Foundation provides short summaries of the key open source
+ licenses, including whether the license qualifies as a free software license
+ or a copyleft license. Also includes a discussion of what constitutes a
+ free software license or a copyleft license (e.g., a Copyleft license is a
+ general method for making a program or other work free, and requiring all
+ modified and extended versions of the program to be free as well.)
+
+
+
+ http://www.opensource.org/licenses/category
+
+
+
+ Open Source Initiative provides the terms of some of the key open source
+ licenses.
+
+
+
+ http://en.wikipedia.org/wiki/Open_source_license
+
+
+
+ Wikipedia discussion of BSD style licenses.
+
+
diff --git site/app/models/license.php b/site/app/models/license.php
new file mode 100644
index 0000000..cb91db7
--- /dev/null
+++ site/app/models/license.php
@@ -0,0 +1,75 @@
+ (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+class License extends AppModel {
+ var $name = 'License';
+ var $hasMany = array('Version' =>
+ array('className' => 'Version',
+ 'foreignKey' => 'license_id'
+ )
+ );
+ var $translated_fields = array('text');
+
+ function getNames() {
+ global $licenses;
+ return array_keys($licenses);
+ }
+
+ function getBuiltin($license_num) {
+ $license = $this->findByName($license_num);
+ if ($license == false) {
+ $data['License']['name'] = $license_num;
+ $this->save($data);
+ return $this->getLastInsertId();
+ } else {
+ return $license['License']['id'];
+ }
+ }
+
+ function getDetails($license_id) {
+ $license = $this->findById($license_id);
+ if ($license['License']['name'] == -1) {
+ $name = ___('license_custom');
+ } else {
+ $names = $this->getNames();
+ $name = $names[$license['License']['name']];
+ }
+
+ $href = "#FIXME";
+ return array($href, $name);
+ }
+}
+?>
diff --git site/app/models/version.php b/site/app/models/version.php
index d563d8b..70c7468 100644
--- site/app/models/version.php
+++ site/app/models/version.php
@@ -43,7 +43,13 @@ class Version extends AppModel
{
var $name = 'Version';
var $belongsTo_full = array('Addon' =>
- array('className' => 'Addon')
+ array('className' => 'Addon'),
+ 'License' =>
+ array('className' => 'License',
+ 'conditions' => '',
+ 'order' => '',
+ 'foreignKey' => 'license_id'
+ )
);
var $hasMany = array('Review' =>
diff --git site/app/views/addons/display.thtml b/site/app/views/addons/display.thtml
index 25b7e3d..ff7c6e1 100644
--- site/app/views/addons/display.thtml
+++ site/app/views/addons/display.thtml
@@ -208,6 +208,19 @@
+ controller->License->getDetails($license_id);
+ ?>
+
+ =$license_text?>
+
$addon['Addon']['id'],
'version' => $version['Version']['version'],
'created' => $version['Version']['created'],
- 'fileSize' => $version['File'][0]['size']
+ 'fileSize' => $version['File'][0]['size'],
+ 'license_id' => $version['Version']['license_id']
);
// Create a fake Addon to pass to $html->extraClass and $html->flag.
@@ -93,15 +94,22 @@ foreach ($versions as $version):
);
echo $this->renderElement('install', $_install_render_options);
?>
-
- controller->Session->check('User')) {
- echo '
';
- echo $html->link(_('addons_display_view_source'), "/files/browse/{$version['File'][0]['id']}");
- echo '
';
- }
- ?>
-
+ controller->License->getDetails($_version_data['license_id']);
+ list($license_href, $license_text) = $details;
+ ?>
+
+ =___('addons_display_header_license')?>
+ =$license_text?>
+
+ controller->Session->check('User')) {
+ echo '';
+ echo $html->link(_('addons_display_view_source'), "/files/browse/{$version['File'][0]['id']}");
+ echo '
';
+ }
+ ?>
@@ -112,7 +120,7 @@ foreach ($versions as $version):
-
- >
+
+
>
=___('devcp_uploader_header_upload')?>
=___('devcp_uploader_p_upload')?>
diff --git site/app/views/developers/versions_edit.thtml b/site/app/views/developers/versions_edit.thtml
index e4bec67..cc6bc7f 100644
--- site/app/views/developers/versions_edit.thtml
+++ site/app/views/developers/versions_edit.thtml
@@ -172,7 +172,7 @@
echo '
';
echo '
';
}
-
+
// Version Notes
echo $this->renderElement('translationbox', array(
'field' => 'releasenotes',
@@ -182,9 +182,26 @@
'displayName' => ___('devcp_versions_edit_transbox_releasenotes_name'),
'description' => ___('devcp_versions_edit_transbox_releasenotes_description'),
));
-
- echo '';
- echo '
'.___('devcp_versions_edit_header_approval').' ';
+ ?>
+
+
+
+
=___('devcp_versions_edit_header_license')?>
+
=___('devcp_versions_edit_license_description')?>
+ controller->Developers->getLicenses($version['Version']['id']);
+ echo $this->renderElement('developers/license_picker',
+ array('licenses' => $licenses));
+ echo $this->renderElement('developers/license_translationbox',
+ array('translations' => $trans,
+ // The transbox wraps fieldname with []
+ 'fieldname' => 'License][text'));
+ ?>
+
+
+
+
=___('devcp_versions_edit_header_approval')?>
+ ';
foreach ($version['File'] as $file) {
diff --git site/app/views/elements/developers/license_picker.thtml b/site/app/views/elements/developers/license_picker.thtml
new file mode 100644
index 0000000..c829723
--- /dev/null
+++ site/app/views/elements/developers/license_picker.thtml
@@ -0,0 +1,49 @@
+
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Required parameters:
+ * - $licenses: array to populate options (value => array(name, selected))
+ */
+?>
+
+ $license) {
+ $selected = $license['selected'] ? 'selected="selected"' : '';
+ echo "{$license['name']} ";
+ }
+?>
+
diff --git site/app/views/elements/developers/license_translationbox.thtml b/site/app/views/elements/developers/license_translationbox.thtml
new file mode 100644
index 0000000..9ff9919
--- /dev/null
+++ site/app/views/elements/developers/license_translationbox.thtml
@@ -0,0 +1,62 @@
+
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Required parameters:
+ * - $translations: array mapping (license picker values => locales)
+ * - $fieldname: name of the translation box field
+ */
+$boxes = array();
+// Create all the HTML strings, but store them in JSON.
+// We use jQuery to create and manipulate the DOM elements later.
+foreach($translations as $name => $locale) {
+ $boxes[$name] = $this->renderElement('translationbox', array(
+ 'field' => $fieldname,
+ 'type' => 'textarea',
+ 'translations' => $locale['text'],
+ 'height' => '130',
+ 'width' => 'inherit',
+ 'graybox' => false));
+}
+?>
+
+
+
diff --git site/app/views/pages/about.thtml b/site/app/views/pages/about.thtml
index 548086f..7b9f83c 100644
--- site/app/views/pages/about.thtml
+++ site/app/views/pages/about.thtml
@@ -1,4 +1,39 @@
(Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
$this->layout = 'mozilla';
?>
diff --git site/app/views/pages/developer_faq.thtml b/site/app/views/pages/developer_faq.thtml
new file mode 100644
index 0000000..d76e0ca
--- /dev/null
+++ site/app/views/pages/developer_faq.thtml
@@ -0,0 +1,49 @@
+ (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+$this->layout = 'mozilla';
+?>
+
+
+ renderElement('search');
+ echo $this->renderElement('sidebar', array('pitch' => true));
+ echo $this->renderElement('app_chooser');
+ ?>
+
+ =$localization->includeLocalPage('developer_faq')?>
+
+
diff --git site/app/views/pages/js_constants.js.thtml b/site/app/views/pages/js_constants.js.thtml
index bd61078..e9174d5 100644
--- site/app/views/pages/js_constants.js.thtml
+++ site/app/views/pages/js_constants.js.thtml
@@ -80,6 +80,8 @@ var devcp_js_remove_author = '=___('devcp_js_remove_author')?>';
var devcp_js_a_cancel = '=___('devcp_js_a_cancel')?>';
var devcp_js_add_email = '=___('devcp_js_add_email')?>';
var devcp_js_img_remove_compat = '=___('devcp_js_img_remove_compat')?>';
+var devcp_js_license_select = '=___('devcp_js_license_select')?>';
+var devcp_js_license_text = '=___('devcp_js_license_text')?>';
var app_compat_ignore_check = '=___('app_compat_ignore_check')?>';
diff --git site/app/webroot/css/developers.css b/site/app/webroot/css/developers.css
index b9e1c72..6bd440a 100644
--- site/app/webroot/css/developers.css
+++ site/app/webroot/css/developers.css
@@ -147,14 +147,17 @@ a.button:hover {
text-decoration: underline;
}
-.agreement-text {
+#dev-agreement {
background-color: #EEEEEE;
- margin: 0 5%;
+ margin: 0 5% 10px;
padding: 10px;
+ max-height: 300px;
+ overflow: auto;
+ border: 1px solid #AAA;
+ font-size: 85%;
}
-.agreement-buttons {
- text-align: center;
- margin: 5px 0;
+#license-disclosure {
+ font-size: 95%;
}
#step-agreement,
@@ -1149,6 +1152,9 @@ div.addonName {
#fileList td.separator {
padding: 0 15px;
}
+#license-translationbox {
+ margin-top: 1em;
+}
/* developers/tshirtrequest */
#tshirtRequestForm {
diff --git site/app/webroot/css/remora.css b/site/app/webroot/css/remora.css
index 1967bd1..bd69e9c 100644
--- site/app/webroot/css/remora.css
+++ site/app/webroot/css/remora.css
@@ -151,3 +151,9 @@ dl.faq dd {
dl.faq dt:target {
color: #df731b;
}
+
+
+/* Developer Agreement */
+#dev-agreement ul {
+ list-style-type: disc;
+}
diff --git site/app/webroot/css/type.css b/site/app/webroot/css/type.css
index 24fd903..e72776c 100644
--- site/app/webroot/css/type.css
+++ site/app/webroot/css/type.css
@@ -144,6 +144,8 @@ h4#moz { font-weight: bold; font-size: 130%; }
.addon-images, .addon-reviews { list-style: none; }
.addon-images a img { vertical-align: top; }
.addon-reviews .cite { font-size: 95%; }
+#license a { font-size: 70%; }
+.oldversion .license a { font-size: 80%; }
/* =Review form */
#form-review #review-submit { font-size: 90%; }
diff --git site/app/webroot/js/developers.js b/site/app/webroot/js/developers.js
index 220f350..f13ac3b 100644
--- site/app/webroot/js/developers.js
+++ site/app/webroot/js/developers.js
@@ -32,8 +32,17 @@ var upload = {
},
acceptAgreement: function() {
- $('#step-agreement').slideUp();
- $('#file-upload').slideDown();
+ if (license_picker.acceptable()) {
+ $('#step-agreement').slideUp();
+ $('#file-upload').slideDown();
+ } else {
+ if ($('#license-name').val() == 'other') {
+ // The license text box must be empty.
+ alert(devcp_js_license_text);
+ } else {
+ alert(devcp_js_license_select);
+ }
+ }
},
platformAll: function() {
@@ -47,10 +56,19 @@ var upload = {
},
uploadFile: function() {
- if ($('#upload-field').val() != '') {
+ if (!license_picker.acceptable()) {
+ $('#file-upload').slideUp();
+ upload.showAgreement();
+ upload.acceptAgreement();
+ return false;
+ }
+ else if ($('#upload-field').val() != '') {
$('#file-upload input[type=submit]').attr('disabled', 'disabled');
$('#upload-loading').show();
$('#upload-error').slideUp('slow');
+ $.each(['#license-name', '#license-translationbox'], function(i, s){
+ $(s).hide().appendTo('#upload-form');
+ });
upload.pastFirstLoad = true;
return true;
}
@@ -413,6 +431,37 @@ var versions_edit = {
save: function() {
$('#versions-edit-form').submit();
}
+
+};
+
+var license_picker = {
+ // Called from document.ready.
+ // license_trans is a dict {"license picker vals": "transbox HTML"}
+ init: function(license_trans) {
+ // Turn the strings into DOM elements.
+ for (var k in license_trans) {
+ license_trans[k] = $(license_trans[k]);
+ }
+ $("#license-name").change(function() {
+ var val = $(this).val();
+ $("#license-translationbox").contents().remove();
+ if(val in license_trans) {
+ license_trans[val].appendTo($('#license-translationbox'));
+ }
+ });
+ $('#license-name').change();
+ },
+
+ acceptable: function() {
+ var val = $("#license-name").val();
+ var trans = $.grep($("#license-translationbox textarea"),
+ function(e) {
+ return $(e).val() != "";
+ });
+ var is_null = val == 'null';
+ var empty_custom = val == 'other' && trans.length < 1;
+ return !(is_null || empty_custom);
+ }
};
var previews = {