Merge lp:~gesha/linaro-license-protection/build-info-support into lp:~linaro-automation/linaro-license-protection/trunk

Proposed by Georgy Redkozubov
Status: Merged
Approved by: Stevan Radaković
Approved revision: 95
Merged at revision: 78
Proposed branch: lp:~gesha/linaro-license-protection/build-info-support
Merge into: lp:~linaro-automation/linaro-license-protection/trunk
Diff against target: 724 lines (+560/-39)
12 files modified
.htaccess (+4/-3)
android/build-info/BUILD-INFO.txt (+38/-0)
android/build-info/origen-blob.txt (+1/-0)
android/build-info/panda-open.txt (+1/-0)
android/build-info/snowball-blob.txt (+1/-0)
licenses/BuildInfo.php (+168/-0)
licenses/license.php (+58/-34)
tests/BUILD-INFO.txt (+18/-0)
tests/BuildInfoTest.php (+244/-0)
tests/LicenseHelperTest.php (+1/-1)
tests/test_click_through_license.py (+25/-0)
tests/test_php_unit.py (+1/-1)
To merge this branch: bzr merge lp:~gesha/linaro-license-protection/build-info-support
Reviewer Review Type Date Requested Status
Stevan Radaković Approve
Данило Шеган Pending
Review via email: mp+107599@code.launchpad.net

Description of the change

This branch adds support for BUILD-INFO.txt license protection.
BUILD-INFO.txt describes files to be protected, the license type, it contains license text. For the first step Version info, Build name, OpenID protection and User info collection are not used.
If the BUILD-INFO.txt is absent then previous EULA/OPEN-EULA protection is used.

To post a comment you must log in.
85. By Georgy Redkozubov

Added missing files

86. By Georgy Redkozubov

[merge] Fix php unit wrong error message when tests are failing.

Revision history for this message
Stevan Radaković (stevanr) wrote :
Download full text (21.3 KiB)

Nice work gesha.
I have one general proposal: The license text should be extracted from
the build info file and put in the separate file in the same directory
as the build info file.

Few comments on the code also:

>
> @@ -102,4 +102,5 @@
> RewriteCond %{REQUEST_URI} !^/licenses/.*$
> RewriteCond %{ENV:LP_DOWNLOAD_DIR}/EULA.txt !-f
> RewriteCond %{ENV:LP_DOWNLOAD_DIR}/OPEN-EULA.txt !-f
> +RewriteCond %{ENV:LP_DOWNLOAD_DIR}/BUILD-INFO.txt !-f
> RewriteRule .* - [R=403,L]

A comment above this block should be updated to match the new Build info
change.

> === added file 'licenses/BuildInfo.php'
> --- licenses/BuildInfo.php 1970-01-01 00:00:00 +0000
> +++ licenses/BuildInfo.php 2012-05-28 09:45:23 +0000
> @@ -0,0 +1,151 @@
> +<?php
> +
> +class BuildInfo
> +{
> + private $text_array = array();
> + private $fields_defined = array("Format-Version", "Files-Pattern",
> + "Build-Name", "Theme", "License-Type", "OpenID-Launchpad-Teams",
> + "Collect-User-Data", "License-Text");
> + private $multiline_vars = array("License-Text");
> + private $search_path = '';
> +

I like using __construct method and do all the class attribute setup in
there, that way is more readable.
Also, since your build file is something always unique to the build info
instance, you can make it an attribute of the class, and then just
assign it during class initialization. Something like:

$bi = BuildInfo("build_info.txt");
$bi->readFile();
...

> + public function readFile($fn)
> + {
> + $this->search_path = dirname($fn);
> + $field = '';
> + $fp_read = 0;
> + if (is_dir($fn) or !is_file($fn) or filesize($fn) == 0) return false; is
> + $file = fopen($fn, "r") or exit("Unable to open file $fn!");

There are exceptions in PHP as well, I started using them in the project
so I think it should be good idea that we stick with that.

> + // Get the 'Format-Version' field.
> + $line = fgets($file);
> + $fields = explode(":", $line, "2");
This is good, you ensure that second and any other ":" char is ignored.

...
> + // Get the rest fileds.
> + while(!feof($file)) {
> + if ($fp_read) {
> + print_r($fields);
Is this some leftover debugging? Please remove.

> + $this->text_array[$fields[0]] = trim($fields[1]);
> + $fp_read = 0;
> + }
> + $line = fgets($file);
> + if (trim($line) == "")
> + continue;
> + $fields = explode(":", $line, "2");
> + if ($fields[0] == "Files-Pattern") {
> + $tmp_arr = array();
> + $fp = trim($fields[1]);
> + while(!feof($file)) {
> + $line = fgets($file);
> + if (trim($line) == "")
> + continue;
> + $fields = explode(":", $line, "2");
> + if (in_array($fields[0], $this->multiline_vars)) {
> + $field = $fields[0];
> + if (isset($fields[1]))
> + $tmp_arr[$fields[0]] = trim($fields[1]);
> + while...

87. By Georgy Redkozubov

Fixed 'Files-Pattern' with multiple patterns

88. By Georgy Redkozubov

Added cunstructor and updated code to take into account it

89. By Georgy Redkozubov

Merged PHP unit tests into single test class

90. By Georgy Redkozubov

Added comments to code

91. By Georgy Redkozubov

Added tests for testing contents of BUILD-INFO array

92. By Georgy Redkozubov

Fixed indentation

Revision history for this message
Georgy Redkozubov (gesha) wrote :
Download full text (5.5 KiB)

> Nice work gesha.
> I have one general proposal: The license text should be extracted from
> the build info file and put in the separate file in the same directory
> as the build info file.

We've agreed to have a license text inside of the BUILD-INFO.txt when made discussed the format of that file.

>
> Few comments on the code also:
>
> > + public function readFile($fn)
> > + {
> > + $this->search_path = dirname($fn);
> > + $field = '';
> > + $fp_read = 0;
> > + if (is_dir($fn) or !is_file($fn) or filesize($fn) == 0) return
> false; is
> > + $file = fopen($fn, "r") or exit("Unable to open file $fn!");
>
> There are exceptions in PHP as well, I started using them in the project
> so I think it should be good idea that we stick with that.

Actually it is usual to open files such way. There is no suitable exception for that.

> > + $this->text_array[$fields[0]] = trim($fields[1]);
> > + $fp_read = 0;
> > + }
> > + $line = fgets($file);
> > + if (trim($line) == "")
> > + continue;
> > + $fields = explode(":", $line, "2");
> > + if ($fields[0] == "Files-Pattern") {
> > + $tmp_arr = array();
> > + $fp = trim($fields[1]);
> > + while(!feof($file)) {
> > + $line = fgets($file);
> > + if (trim($line) == "")
> > + continue;
> > + $fields = explode(":", $line, "2");
> > + if (in_array($fields[0], $this->multiline_vars)) {
> > + $field = $fields[0];
> > + if (isset($fields[1]))
> > + $tmp_arr[$fields[0]] = trim($fields[1]);
> > + while(!feof($file)) {
> > + $line = fgets($file);
> > + if (trim($line) == "")
> > + continue;
> > + $fields = explode(":", $line, "2");
> > + if(in_array($fields[0], $this->fields_defined))
> {
> > + if ($fields[0] == "Files-Pattern") {
> > + fseek($file, -(strlen($line)),
> SEEK_CUR);
> > + break 2;
> > + }
> > + break;
> > + }
> > + $tmp_arr[$field] = $tmp_arr[$field].
> > + "\n".rtrim($line);
> > + }
> > +
> > + }
> > + if (isset($fields[1])) {
> > + $tmp_arr[$fields[0]] = trim($fields[1]);
> > + }
> > + }
> > + $this->text_array[$fp] = $tmp_arr;
> > + unset($tmp_arr);
> > + }
> > + }
> > + fclose($file);
> > +
> > + return true;
> > + }
> > +
>
> First, the code above is not commented at all and was very hard to read.
> I think this will change anyway if you apply the license text ext...

Read more...

Revision history for this message
Georgy Redkozubov (gesha) wrote :

Refactored BUILD-INFO.txt parsing.
Updated tests.

93. By Georgy Redkozubov

[merge] Danilos TDD intro

94. By Georgy Redkozubov

Refactored parsing BUILD-INFO.txt

Revision history for this message
Stevan Radaković (stevanr) wrote :

Hi gesha,

Your additions look great!

Few small pointers tho:

92 === added file 'licenses/BuildInfo.php'
93 --- licenses/BuildInfo.php 1970-01-01 00:00:00 +0000
94 +++ licenses/BuildInfo.php 2012-06-05 14:32:19 +0000
95 @@ -0,0 +1,207 @@
96 +<?php
97 +
98 +class BuildInfo
99 +{
100 + private $text_array = array();
101 + private $fields_defined = array("Format-Version", "Files-Pattern",
102 + "Build-Name", "Theme", "License-Type", "OpenID-Launchpad-Teams",
103 + "Collect-User-Data", "License-Text");
104 + private $multiline_vars = array("License-Text");
105 + private $search_path = '';
106 + private $fname = '';

I would really like to see all the initialization inside the __construct class.
Furthermore, empty strings need not be initialized. "private $fname;" is enough.

There are very small amount of comments in the BuildInfo.php file.
Fields like text_array are very non-descriptive, we should rename those as well.

132 + private function getInfoForFile($fname)
133 + {
134 + /**
135 + * Get array of fields for corresponding file
136 + */
137 + foreach (array_keys($this->text_array) as $key)
138 + if ($key != 'Format-Version') {
139 + $files = glob($this->search_path."/".$key);
140 + foreach ($files as $file)
141 + if ($file == $this->search_path."/".$fname)
142 + return $this->text_array[$key];
143 + }
144 + return array();
145 + }

We can avoid this whole mumbo by putting $fname as the attribute of the class and then only hold the relevant build info data for that file in text_array attribute. That's all we need for each HTTP request anyway.

165 + public function getTheme($fname)
166 + {
167 + $info = $this->getInfoForFile($fname);
168 + if (array_key_exists('Theme', $info))
169 + return $info["Theme"];
170 + else
171 + return false;
172 + }

All getFieldX methods should be united in one method.
I.e. public function get($fieldName) - (if we remove $fname as suggested above)
We'll get less code, less tests, and if we would need to implement new fields, we wouldn't need to add separate method and additional tests.

801 === modified file 'tests/test_click_through_license.py'
802 --- tests/test_click_through_license.py 2012-05-17 18:44:59 +0000
803 +++ tests/test_click_through_license.py 2012-06-05 14:32:19 +0000
804 @@ -36,6 +36,9 @@

Tests fail for these 3 new tests added..

review: Needs Fixing (code)
95. By Georgy Redkozubov

Refactored 'getX' methods into single 'get' method. Updated code to use new approach.

Revision history for this message
Georgy Redkozubov (gesha) wrote :

Stevan, thanks for review. Your notes are good.

>
>
> I would really like to see all the initialization inside the __construct
> class.
> Furthermore, empty strings need not be initialized. "private $fname;" is
> enough.
>
> There are very small amount of comments in the BuildInfo.php file.
> Fields like text_array are very non-descriptive, we should rename those as
> well.

Moved inititalization to constructor.

>
> We can avoid this whole mumbo by putting $fname as the attribute of the class
> and then only hold the relevant build info data for that file in text_array
> attribute. That's all we need for each HTTP request anyway.

That's a good point.

>
>
> All getFieldX methods should be united in one method.
> I.e. public function get($fieldName) - (if we remove $fname as suggested
> above)
> We'll get less code, less tests, and if we would need to implement new fields,
> we wouldn't need to add separate method and additional tests.
>

I refactored code and did the reduction.

>
> 801 === modified file 'tests/test_click_through_license.py'
> 802 --- tests/test_click_through_license.py 2012-05-17 18:44:59 +0000
> 803 +++ tests/test_click_through_license.py 2012-06-05 14:32:19 +0000
> 804 @@ -36,6 +36,9 @@
>
> Tests fail for these 3 new tests added..

That was by the mistype. Fixed.

Revision history for this message
Stevan Radaković (stevanr) wrote :

Great work gesha. Approved.

> Stevan, thanks for review. Your notes are good.
>
> >
> >
> > I would really like to see all the initialization inside the __construct
> > class.
> > Furthermore, empty strings need not be initialized. "private $fname;" is
> > enough.
> >
> > There are very small amount of comments in the BuildInfo.php file.
> > Fields like text_array are very non-descriptive, we should rename those as
> > well.
>
> Moved inititalization to constructor.
>
> >
> > We can avoid this whole mumbo by putting $fname as the attribute of the
> class
> > and then only hold the relevant build info data for that file in text_array
> > attribute. That's all we need for each HTTP request anyway.
>
> That's a good point.
>
> >
> >
> > All getFieldX methods should be united in one method.
> > I.e. public function get($fieldName) - (if we remove $fname as suggested
> > above)
> > We'll get less code, less tests, and if we would need to implement new
> fields,
> > we wouldn't need to add separate method and additional tests.
> >
>
> I refactored code and did the reduction.
>
> >
> > 801 === modified file 'tests/test_click_through_license.py'
> > 802 --- tests/test_click_through_license.py 2012-05-17 18:44:59 +0000
> > 803 +++ tests/test_click_through_license.py 2012-06-05 14:32:19 +0000
> > 804 @@ -36,6 +36,9 @@
> >
> > Tests fail for these 3 new tests added..
>
> That was by the mistype. Fixed.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.htaccess'
2--- .htaccess 2012-05-11 12:03:32 +0000
3+++ .htaccess 2012-06-11 10:48:21 +0000
4@@ -1,4 +1,4 @@
5-IndexIgnore HEADER* licenses *EULA*
6+IndexIgnore HEADER* licenses *EULA* BUILD-INFO.txt
7 IndexOptions FancyIndexing HTMLTable
8
9 RewriteEngine On
10@@ -93,13 +93,14 @@
11 RewriteCond %{HTTP_COOKIE} redirectlicensephp=404
12 RewriteRule .* - [CO=redirectlicensephp:INVALID:.%{ENV:CO_DOMAIN}:-1,L]
13
14-## Redirect to the Samsung license file protected builds.
15+## Redirect to the license file protected builds.
16 RewriteCond %{REQUEST_URI} !^/$
17 RewriteRule .* /licenses/license.php [CO=downloadrequested:%{REQUEST_URI}:.%{ENV:CO_DOMAIN}:5:/,L,R]
18
19-## Return "Permission denied" if no EULA/OPEN-EULA exists
20+## Return "Permission denied" if no EULA/OPEN-EULA/BUILD-INFO exists
21 RewriteCond %{REQUEST_URI} !^/$
22 RewriteCond %{REQUEST_URI} !^/licenses/.*$
23 RewriteCond %{ENV:LP_DOWNLOAD_DIR}/EULA.txt !-f
24 RewriteCond %{ENV:LP_DOWNLOAD_DIR}/OPEN-EULA.txt !-f
25+RewriteCond %{ENV:LP_DOWNLOAD_DIR}/BUILD-INFO.txt !-f
26 RewriteRule .* - [R=403,L]
27
28=== added directory 'android/build-info'
29=== added file 'android/build-info/BUILD-INFO.txt'
30--- android/build-info/BUILD-INFO.txt 1970-01-01 00:00:00 +0000
31+++ android/build-info/BUILD-INFO.txt 2012-06-11 10:48:21 +0000
32@@ -0,0 +1,38 @@
33+Format-Version: 0.1
34+
35+Files-Pattern: *snowball*
36+Build-Name: landing-snowball
37+Theme: ste
38+License-Type: protected
39+License-Text: <p>IMPORTANT — PLEASE READ THE FOLLOWING AGREEMENT CAREFULLY.</p>
40+ <p>
41+ THIS IS A LEGALLY BINDING AGREEMENT BETWEEN YOU, an individual or a
42+ legal entity, (“LICENSEE”) AND SAMSUNG ELECTRONICS CO.,
43+ LTD. (“SAMSUNG”). BY CLICKING THE "ACCEPT" BUTTON, OR BY DOWNLOADING OR
44+ INSTALLING OR OTHERWISE USING THE SOFTWARE, YOU AGREE TO BE BOUND BY THE
45+ TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS
46+ AGREEMENT OR ARE NOT AUTHORISED TO ACCEPT AND AGREE TO THE TERMS OF THE
47+ AGREEMENT ON BEHALF OF YOUR LEGAL ENTITY, DO NOT DOWNLOAD, INSTALL OR
48+ OTHERWISE USE THE SOFTWARE.
49+ </p>
50+
51+Files-Pattern: *origen*
52+Build-Name: landing-origen
53+Theme: samsung
54+License-Type: protected
55+License-Text: <p>IMPORTANT — PLEASE READ THE FOLLOWING AGREEMENT CAREFULLY.</p>
56+ <p>
57+ THIS IS A LEGALLY BINDING AGREEMENT BETWEEN YOU, an individual or a
58+ legal entity, (“LICENSEE”) AND SAMSUNG ELECTRONICS CO.,
59+ LTD. (“SAMSUNG”). BY CLICKING THE "ACCEPT" BUTTON, OR BY DOWNLOADING OR
60+ INSTALLING OR OTHERWISE USING THE SOFTWARE, YOU AGREE TO BE BOUND BY THE
61+ TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS
62+ AGREEMENT OR ARE NOT AUTHORISED TO ACCEPT AND AGREE TO THE TERMS OF THE
63+ AGREEMENT ON BEHALF OF YOUR LEGAL ENTITY, DO NOT DOWNLOAD, INSTALL OR
64+ OTHERWISE USE THE SOFTWARE.
65+ </p>
66+
67+Files-Pattern: *panda*
68+Build-Name: landing-panda
69+License-Type: open
70+
71
72=== added file 'android/build-info/origen-blob.txt'
73--- android/build-info/origen-blob.txt 1970-01-01 00:00:00 +0000
74+++ android/build-info/origen-blob.txt 2012-06-11 10:48:21 +0000
75@@ -0,0 +1,1 @@
76+This is protected with click-through Samsung license.
77\ No newline at end of file
78
79=== added file 'android/build-info/panda-open.txt'
80--- android/build-info/panda-open.txt 1970-01-01 00:00:00 +0000
81+++ android/build-info/panda-open.txt 2012-06-11 10:48:21 +0000
82@@ -0,0 +1,1 @@
83+This is always available.
84
85=== added file 'android/build-info/snowball-blob.txt'
86--- android/build-info/snowball-blob.txt 1970-01-01 00:00:00 +0000
87+++ android/build-info/snowball-blob.txt 2012-06-11 10:48:21 +0000
88@@ -0,0 +1,1 @@
89+This is protected with click-through ST-E license.
90\ No newline at end of file
91
92=== added file 'licenses/BuildInfo.php'
93--- licenses/BuildInfo.php 1970-01-01 00:00:00 +0000
94+++ licenses/BuildInfo.php 2012-06-11 10:48:21 +0000
95@@ -0,0 +1,168 @@
96+<?php
97+
98+class BuildInfo
99+{
100+ private $build_info_array;
101+ private $fields_defined;
102+ private $multiline_vars;
103+ private $search_path;
104+ private $fname;
105+ private $file_info_array;
106+
107+ public function __construct($fn)
108+ {
109+ $this->build_info_array = array();
110+ $this->file_info_array = array();
111+ $this->fields_defined = array("Format-Version", "Files-Pattern",
112+ "Build-Name", "Theme", "License-Type", "OpenID-Launchpad-Teams",
113+ "Collect-User-Data", "License-Text");
114+ $this->multiline_vars = array("License-Text");
115+ $this->search_path = dirname($fn);
116+ $this->fname = basename($fn);
117+ $this->build_info_file = $this->search_path."/BUILD-INFO.txt";
118+ $data = $this->readFile();
119+ if (is_array($data)) {
120+ $this->build_info_array = $this->parseData($data);
121+ $this->file_info_array = $this->getInfoForFile($this->fname);
122+ }
123+ }
124+
125+ public function readFile()
126+ {
127+ $data = array();
128+ if (is_dir($this->build_info_file) or !is_file($this->build_info_file) or filesize($this->build_info_file) == 0) return false;
129+ $file = fopen($this->build_info_file, "r") or exit("Unable to open file $this->build_info_file!");
130+ while(!feof($file)) {
131+ $line = fgets($file);
132+ if (trim($line) == "")
133+ continue;
134+ $data[] = $line;
135+ }
136+ return $data;
137+ }
138+
139+ private function getInfoForFile($fname)
140+ {
141+ /**
142+ * Get array of fields for corresponding file
143+ */
144+ foreach (array_keys($this->build_info_array) as $key)
145+ if ($key != 'Format-Version') {
146+ $files = glob($this->search_path."/".$key);
147+ foreach ($files as $file)
148+ if ($file == $this->search_path."/".$fname)
149+ return $this->build_info_array[$key];
150+ }
151+ return array();
152+ }
153+
154+ public function getFormatVersion()
155+ {
156+ if (array_key_exists('Format-Version', $this->build_info_array))
157+ return $this->build_info_array["Format-Version"];
158+ else
159+ return false;
160+ }
161+
162+ // Get value of specified field for corresponding file
163+ public function get($field)
164+ {
165+ if (array_key_exists($field, $this->file_info_array))
166+ return $this->file_info_array[$field];
167+ else
168+ return false;
169+ }
170+
171+ public function parseLine($line) {
172+ $values = explode(":", $line, 2);
173+ if ($values === false || count($values) != 2) {
174+ throw new InvalidArgumentException("Line is not in the correct format.");
175+ } else {
176+ $field = trim($values[0]);
177+ $value = trim($values[1]);
178+ if (!$this->isValidField($field)) {
179+ throw new InvalidArgumentException("Field '$field' not allowed.");
180+ } else {
181+ return array($field => $value);
182+ }
183+ }
184+ }
185+
186+ public function isValidField($field_name) {
187+ if (in_array($field_name, $this->fields_defined)) {
188+ return true;
189+ } else {
190+ return false;
191+ }
192+ }
193+
194+ public function parseContinuation($lines, &$line_no) {
195+ $text = '';
196+ $total_lines = count($lines);
197+ while ($line_no < $total_lines &&
198+ strlen($lines[$line_no]) > 0) {
199+ if ($lines[$line_no][0] == ' ') {
200+ $text .= "\n" . substr($lines[$line_no], 1);
201+ $line_no++;
202+ } else {
203+ break;
204+ }
205+ }
206+ return $text;
207+ }
208+
209+ /**
210+ * `data` should be array of lines.
211+ */
212+ public function parseData($data) {
213+ if (!is_array($data)) {
214+ throw new InvalidArgumentException("No array provided.");
215+ }
216+ $format_line = array_shift($data);
217+ $values = $this->parseLine($format_line);
218+ if (!array_key_exists("Format-Version", $values)) {
219+ throw new InvalidArgumentException("Data in incorrect format.");
220+ }
221+ $result = array("Format-Version" => $values["Format-Version"]);
222+
223+ $line_no = 0;
224+ while ($line_no < count($data)) {
225+ $line = $data[$line_no];
226+ $values = $this->parseLine($line);
227+ if (array_key_exists("Files-Pattern", $values)) {
228+ $line_no++;
229+ $block = $this->parseBlock($data, $line_no);
230+ if (is_array($block)) {
231+ foreach (explode(",", $values["Files-Pattern"]) as $pattern) {
232+ $result[$pattern] = $block;
233+ }
234+ }
235+ }
236+ }
237+ return $result;
238+ }
239+
240+ public function parseBlock($data, &$line_no) {
241+ $result = array();
242+
243+ if (!is_array($data)) {
244+ throw new InvalidArgumentException("No array provided.");
245+ }
246+ while ($line_no < count($data)) {
247+ $line = $data[$line_no];
248+ $values = $this->parseLine($line);
249+ if (array_key_exists("License-Text", $values)) {
250+ $text = $values["License-Text"];
251+ $line_no++;
252+ $text .= $this->parseContinuation($data, $line_no);
253+ $result["License-Text"] = $text;
254+ } elseif (array_key_exists("Files-Pattern", $values)) {
255+ return $result;
256+ } else {
257+ $line_no++;
258+ $result = array_merge($result, $values);
259+ }
260+ }
261+ return $result;
262+ }
263+}
264
265=== modified file 'licenses/license.php'
266--- licenses/license.php 2012-05-11 08:23:42 +0000
267+++ licenses/license.php 2012-06-11 10:48:21 +0000
268@@ -1,6 +1,7 @@
269 <?php
270
271 require_once("LicenseHelper.php");
272+require_once("BuildInfo.php");
273
274 $down = $_COOKIE["downloadrequested"];
275 $host = $_SERVER["HTTP_HOST"];
276@@ -9,55 +10,78 @@
277 $fn = $doc.$down; // Filename on server
278 $flist = array();
279 $eula = '';
280+$bi_found = 0;
281
282 if (preg_match("/.*openid.*/", $fn) or preg_match("/.*restricted.*/", $fn) or preg_match("/.*private.*/", $fn)) {
283- LicenseHelper::redirect_with_status($down, $domain, 200);
284+ LicenseHelper::redirect_with_status($down, $domain, 200);
285 }
286
287 if (file_exists($fn) and LicenseHelper::checkFile($fn)) { // Requested download is file
288- $search_dir = dirname($fn);
289- $repl = dirname($down);
290- $name_only = array(basename($down), '');
291+ $search_dir = dirname($fn);
292+ $repl = dirname($down);
293+ $name_only = array(basename($down), '');
294 } elseif (is_dir($fn)) { // Requested download is directory
295- $search_dir = $fn;
296- $repl = $down;
297- $name_only = array();
298+ $search_dir = $fn;
299+ $repl = $down;
300+ $name_only = array();
301 } else { // Requested download not found on server
302- LicenseHelper::redirect_with_status($down, $domain, 404);
303+ LicenseHelper::redirect_with_status($down, $domain, 404);
304 }
305
306-$flist = LicenseHelper::getFilesList($search_dir);
307-
308-if (!empty($name_only)) {
309- $pattern = "/^".$name_only[0]."\.EULA\.txt.*/";
310- $eula = LicenseHelper::findFileByPattern($flist, $pattern);
311+if (file_exists($search_dir."/BUILD-INFO.txt")) {
312+ $bi_found = 1;
313+ $bi = new BuildInfo($search_dir."/".$name_only[0]);
314+ $theme = $bi->get("Theme");
315+ $lic_type = $bi->get("License-Type");
316+ $lic_text = $bi->get("License-Text");
317+} else {
318+ $flist = LicenseHelper::getFilesList($search_dir);
319+ if (!empty($name_only)) {
320+ $pattern = "/^".$name_only[0]."\.EULA\.txt.*/";
321+ $eula = LicenseHelper::findFileByPattern($flist, $pattern);
322+ }
323 }
324
325 if (LicenseHelper::checkFile($fn)) {
326- if (LicenseHelper::checkFile($doc."/".$repl."/".$eula)) { // Special EULA found
327- $theme = LicenseHelper::getTheme($eula, $down);
328- } elseif (LicenseHelper::checkFile($doc."/".$repl."/EULA.txt")) { // No special EULA found
329- $theme = LicenseHelper::getTheme("EULA.txt", $down);
330- } elseif (LicenseHelper::findFileByPattern($flist, "/.*EULA.txt.*/")) {
331- // If file is requested but no special EULA for it and no EULA.txt is present,
332- // look for any EULA and if found decide that current file is not protected.
333- LicenseHelper::redirect_with_status($down, $domain, 200);
334- } else {
335- LicenseHelper::redirect_with_status($down, $domain, 403);
336- }
337+ if ($bi_found) {
338+ if ($lic_type == 'open')
339+ LicenseHelper::redirect_with_status($down, $domain, 200);
340+ elseif (($theme != false) or ($lic_text != false))
341+ $template_content = file_get_contents($doc."/licenses/".$theme.".html");
342+ else
343+ LicenseHelper::redirect_with_status($down, $domain, 403);
344+ } else {
345+ if (LicenseHelper::checkFile($doc."/".$repl."/".$eula)) {
346+ // Special EULA found
347+ $theme = LicenseHelper::getTheme($eula, $down);
348+ } elseif (LicenseHelper::checkFile($doc."/".$repl."/EULA.txt")) {
349+ // No special EULA found
350+ $theme = LicenseHelper::getTheme("EULA.txt", $down);
351+ } elseif (LicenseHelper::findFileByPattern($flist, "/.*EULA.txt.*/")) {
352+ // If file is requested but no special EULA for it and no EULA.txt
353+ // is present, look for any EULA and if found decide that current
354+ // file is not protected.
355+ LicenseHelper::redirect_with_status($down, $domain, 200);
356+ } else {
357+ LicenseHelper::redirect_with_status($down, $domain, 403);
358+ }
359+ $template_content = file_get_contents($doc."/licenses/".$theme.".html");
360+ $lic_text = file_get_contents($doc."/licenses/".$theme.".txt");
361+ }
362 } elseif (is_dir($fn)) {
363- if (empty($flist) or LicenseHelper::findFileByPattern($flist, "/.*EULA.txt.*/")) { // Directory contains only subdirs or any EULA
364- LicenseHelper::redirect_with_status($down, $domain, 200);
365- } else { // No special EULA, no EULA.txt, no OPEN-EULA.txt found
366- LicenseHelper::redirect_with_status($down, $domain, 403);
367- }
368+ if (empty($flist)
369+ or LicenseHelper::findFileByPattern($flist, "/.*EULA.txt.*/")
370+ or $bi_found) {
371+ // Directory contains only subdirs or any EULA or BUILD-INFO.txt
372+ LicenseHelper::redirect_with_status($down, $domain, 200);
373+ } else {
374+ // No special EULA, no EULA.txt, no OPEN-EULA.txt found
375+ LicenseHelper::redirect_with_status($down, $domain, 403);
376+ }
377 } else {
378- LicenseHelper::redirect_with_status($down, $domain, 403);
379+ LicenseHelper::redirect_with_status($down, $domain, 403);
380 }
381
382-$template_content = file_get_contents($doc."/licenses/".$theme.".html");
383-$eula_content = file_get_contents($doc."/licenses/".$theme.".txt");
384-
385-$out = str_replace("EULA.txt", $eula_content, $template_content);
386+$out = str_replace("EULA.txt", $lic_text, $template_content);
387 echo $out;
388 ?>
389
390=== added file 'tests/BUILD-INFO.txt'
391--- tests/BUILD-INFO.txt 1970-01-01 00:00:00 +0000
392+++ tests/BUILD-INFO.txt 2012-06-11 10:48:21 +0000
393@@ -0,0 +1,18 @@
394+Format-Version: 0.1
395+Files-Pattern: *.txt
396+Build-Name: landing-snowball
397+Theme: stericsson
398+License-Type: open
399+OpenID-Launchpad-Teams: linaro,non-linaro
400+Collect-User-Data: yes
401+License-Text: <p>IMPORTANT — PLEASE READ THE FOLLOWING AGREEMENT CAREFULLY.</p>
402+ <p>
403+ THIS IS A LEGALLY BINDING AGREEMENT BETWEEN YOU, an individual or a
404+ legal entity, (“LICENSEE”) AND SAMSUNG ELECTRONICS CO.,
405+ LTD. (“SAMSUNG”). BY CLICKING THE "ACCEPT" BUTTON, OR BY DOWNLOADING OR
406+ INSTALLING OR OTHERWISE USING THE SOFTWARE, YOU AGREE TO BE BOUND BY THE
407+ TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS
408+ AGREEMENT OR ARE NOT AUTHORISED TO ACCEPT AND AGREE TO THE TERMS OF THE
409+ AGREEMENT ON BEHALF OF YOUR LEGAL ENTITY, DO NOT DOWNLOAD, INSTALL OR
410+ OTHERWISE USE THE SOFTWARE.
411+ </p>
412
413=== added file 'tests/BuildInfoTest.php'
414--- tests/BuildInfoTest.php 1970-01-01 00:00:00 +0000
415+++ tests/BuildInfoTest.php 2012-06-11 10:48:21 +0000
416@@ -0,0 +1,244 @@
417+<?php
418+
419+require_once("licenses/BuildInfo.php");
420+
421+class BuildInfoTest extends PHPUnit_Framework_TestCase
422+{
423+
424+ private $temp_filename;
425+ private $good_bi;
426+ private $empty_bi;
427+ private $fname;
428+
429+ public function setUp()
430+ {
431+ $this->good_bi = new BuildInfo("tests/BUILD-INFO.txt");
432+ $this->temp_filename = tempnam(sys_get_temp_dir(), "build-info");
433+ $this->empty_bi = new BuildInfo($this->temp_filename);
434+ $this->fname = "BUILD-INFO.txt";
435+ }
436+
437+ public function tearDown() {
438+ if (file_exists($this->temp_filename)) {
439+ unlink($this->temp_filename);
440+ }
441+ }
442+
443+ /**
444+ * @expectedException InvalidArgumentException
445+ */
446+ public function test_parseLine_fails() {
447+ $line = "no separator";
448+ $buildinfo = new BuildInfo("");
449+ $buildinfo->parseLine($line);
450+ }
451+
452+ public function test_parseLine_passes() {
453+ $line = "Build-Name:value";
454+ $buildinfo = new BuildInfo("");
455+ $this->assertEquals(array("Build-Name" => "value"),
456+ $buildinfo->parseLine($line));
457+ }
458+
459+ public function test_parseLine_trims() {
460+ $line = "Build-Name: value";
461+ $buildinfo = new BuildInfo("");
462+ $this->assertEquals(array("Build-Name" => "value"),
463+ $buildinfo->parseLine($line));
464+ }
465+
466+ /**
467+ * @expectedException InvalidArgumentException
468+ */
469+ public function test_parseLine_invalid_field() {
470+ $line = "field: value";
471+ $buildinfo = new BuildInfo("");
472+ $this->assertEquals(array("field" => "value"),
473+ $buildinfo->parseLine($line));
474+ }
475+
476+ public function test_isValidField_true() {
477+ $buildinfo = new BuildInfo("");
478+ $fields_allowed = array("Format-Version", "Files-Pattern",
479+ "Build-Name", "Theme", "License-Type", "OpenID-Launchpad-Teams",
480+ "Collect-User-Data", "License-Text");
481+ foreach ($fields_allowed as $field) {
482+ $this->assertTrue($buildinfo->isValidField($field));
483+ }
484+ }
485+
486+ public function test_isValidField_false() {
487+ $buildinfo = new BuildInfo("");
488+ $this->assertFalse($buildinfo->isValidField("Some random text"));
489+ }
490+
491+ /**
492+ * @expectedException InvalidArgumentException
493+ */
494+ public function test_parseData_fails() {
495+ $buildinfo = new BuildInfo("");
496+ $buildinfo->parseData(array("Arbitrary text"));
497+ }
498+
499+ /**
500+ * @expectedException InvalidArgumentException
501+ */
502+ public function test_parseData_array_expected() {
503+ $buildinfo = new BuildInfo("");
504+ $buildinfo->parseData("Arbitrary text");
505+ }
506+
507+ public function test_parseData_format_version() {
508+ $buildinfo = new BuildInfo("");
509+ $values = $buildinfo->parseData(array("Format-Version: 2.0"));
510+ $this->assertEquals(array("Format-Version" => "2.0"),
511+ $values);
512+ }
513+
514+ public function test_parseData_extra_fields() {
515+ $buildinfo = new BuildInfo("");
516+ $values = $buildinfo->parseData(array(
517+ "Format-Version: 2.0",
518+ "Files-Pattern: *.txt",
519+ "Build-Name: woohoo"));
520+ $this->assertEquals(array("Format-Version" => "2.0",
521+ "*.txt" => array("Build-Name" => "woohoo")),
522+ $values);
523+ }
524+
525+ public function test_parseBlock_license() {
526+ $buildinfo = new BuildInfo("");
527+ $lineno = 0;
528+ $values = $buildinfo->parseBlock(array(
529+ "Format-Version: 2.0",
530+ "License-Text: line1",
531+ " line2"), $lineno);
532+ $this->assertEquals(array("Format-Version" => "2.0",
533+ "License-Text" => "line1\nline2"),
534+ $values);
535+ }
536+
537+ public function test_parseContinuation_no_continuation() {
538+ $buildinfo = new BuildInfo("");
539+ $lineno = 0;
540+ $this->assertEquals(
541+ "",
542+ $buildinfo->parseContinuation(array("no-space"), $lineno));
543+ }
544+
545+ public function test_parseContinuation_indexed() {
546+ $buildinfo = new BuildInfo("");
547+ $lineno = 0;
548+ $this->assertEquals("",
549+ $buildinfo->parseContinuation(array("no-space", " space"), $lineno));
550+ }
551+
552+ public function test_parseContinuation() {
553+ $buildinfo = new BuildInfo("");
554+ $lineno = 1;
555+ $value = $buildinfo->parseContinuation(array("no-space", " line1", " line2"), $lineno);
556+ $this->assertEquals("\nline1\nline2", $value);
557+ }
558+
559+ /**
560+ * @expectedException InvalidArgumentException
561+ */
562+ public function test_parseData_no_format_version_fails() {
563+ $buildinfo = new BuildInfo("");
564+ $values = $buildinfo->parseData(array("Build-Name: blah"));
565+ }
566+
567+ public function test_parseData_blocks() {
568+ $buildinfo = new BuildInfo("");
569+ $lineno = 0;
570+ $values = $buildinfo->parseData(array("Format-Version: 2.0",
571+ "Files-Pattern: *.txt",
572+ "Build-Name: woohoo",
573+ "Files-Pattern: *.tgz",
574+ "Build-Name: weehee"));
575+ $this->assertEquals(array("Format-Version" => "2.0",
576+ "*.txt" => array("Build-Name" => "woohoo"),
577+ "*.tgz" => array("Build-Name" => "weehee")),
578+ $values);
579+ }
580+
581+ public function test_parseData_block_multiple_patterns() {
582+ $buildinfo = new BuildInfo("");
583+ $lineno = 0;
584+ $values = $buildinfo->parseData(array("Format-Version: 2.0",
585+ "Files-Pattern: *.txt,*.tgz",
586+ "Build-Name: weehee"));
587+ $this->assertEquals(array("Format-Version" => "2.0",
588+ "*.txt" => array("Build-Name" => "weehee"),
589+ "*.tgz" => array("Build-Name" => "weehee")),
590+ $values);
591+ }
592+
593+
594+ /**
595+ * Running readFile on a directory returns false.
596+ */
597+ public function test_readFile_nonFile()
598+ {
599+ $bi = new BuildInfo(dirname(__FILE__));
600+ $this->assertFalse($bi->readFile());
601+ }
602+
603+ /**
604+ * Running readFile on a nonexistent file returns false.
605+ */
606+ public function test_readFile_nonexistentFile()
607+ {
608+ $bi = new BuildInfo("nonexistent.file");
609+ $this->assertFalse($bi->readFile());
610+ }
611+
612+ /**
613+ * Running readFile on a regular file returns array of strings.
614+ */
615+ public function test_readFile_file()
616+ {
617+ $bi = new BuildInfo("tests/BUILD-INFO.txt");
618+ $this->assertInternalType('array', $bi->readFile());
619+ }
620+
621+ /**
622+ * Running 'get' functions on an empty fields returns false.
623+ */
624+ public function test_getFormatVersion_empty()
625+ {
626+ $this->assertFalse($this->empty_bi->getFormatVersion());
627+ }
628+
629+ /**
630+ * Running 'get' functions on non-empty fields returns string value.
631+ */
632+ public function test_getFormatVersion_type()
633+ {
634+ $this->assertInternalType(
635+ 'string', $this->good_bi->getFormatVersion());
636+ }
637+
638+ public function test_getFormatVersion()
639+ {
640+ $this->assertEquals('0.1', $this->good_bi->getFormatVersion());
641+ }
642+
643+ public function test_getBuildName_empty()
644+ {
645+ $this->assertFalse($this->empty_bi->get("Build-Name"));
646+ }
647+
648+ public function test_getBuildName_type()
649+ {
650+ $this->assertInternalType(
651+ 'string', $this->good_bi->get("Build-Name"));
652+ }
653+
654+ public function test_getBuildName()
655+ {
656+ $this->assertEquals(
657+ 'landing-snowball', $this->good_bi->get("Build-Name"));
658+ }
659+}
660+?>
661
662=== modified file 'tests/LicenseHelperTest.php'
663--- tests/LicenseHelperTest.php 2012-05-29 07:30:45 +0000
664+++ tests/LicenseHelperTest.php 2012-06-11 10:48:21 +0000
665@@ -174,4 +174,4 @@
666
667 }
668
669-?>
670\ No newline at end of file
671+?>
672
673=== modified file 'tests/test_click_through_license.py'
674--- tests/test_click_through_license.py 2012-05-17 18:44:59 +0000
675+++ tests/test_click_through_license.py 2012-06-11 10:48:21 +0000
676@@ -36,6 +36,9 @@
677 per_file_ste_test_file = '/android/images/snowball-blob.txt'
678 per_file_not_protected_test_file = '/android/images/MANIFEST'
679 dirs_only_dir = '/android/~linaro-android/'
680+build_info_samsung_test_file = '/android/build-info/origen-blob.txt'
681+build_info_ste_test_file = '/android/build-info/snowball-blob.txt'
682+build_info_not_protected_test_file = '/android/build-info/panda-open.txt'
683
684
685 class Contains(object):
686@@ -295,3 +298,25 @@
687 search = "Not Found"
688 testfile = fetcher.get(host + not_found_test_file)
689 self.assertThat(testfile, Contains(search))
690+
691+ def test_build_info_non_protected_file(self):
692+ search = "This is always available."
693+ testfile = fetcher.get(host + build_info_not_protected_test_file)
694+ self.assertThat(testfile, Contains(search))
695+
696+ def test_build_info_accept_license_samsung_file(self):
697+ search = "This is protected with click-through Samsung license."
698+ testfile = fetcher.get(host + build_info_samsung_test_file)
699+ fetcher.close()
700+ if os.path.exists("%s/cookies.txt" % docroot):
701+ os.rename("%s/cookies.txt" % docroot,
702+ "%s/cookies.samsung" % docroot)
703+ self.assertThat(testfile, Contains(search))
704+
705+ def test_build_info_accept_license_ste_file(self):
706+ search = "This is protected with click-through ST-E license."
707+ testfile = fetcher.get(host + build_info_ste_test_file)
708+ fetcher.close()
709+ if os.path.exists("%s/cookies.txt" % docroot):
710+ os.rename("%s/cookies.txt" % docroot, "%s/cookies.ste" % docroot)
711+ self.assertThat(testfile, Contains(search))
712
713=== modified file 'tests/test_php_unit.py'
714--- tests/test_php_unit.py 2012-05-28 09:35:50 +0000
715+++ tests/test_php_unit.py 2012-06-11 10:48:21 +0000
716@@ -17,7 +17,7 @@
717 super(PhpUnitTest, self).setUp()
718 self.xml_path = tempfile.mkstemp()[1]
719 returncode = subprocess.Popen(['phpunit', '--log-junit',
720- self.xml_path, 'tests/LicenseHelperTest'],
721+ self.xml_path, 'tests'],
722 stdout=open('/dev/null', 'w'),
723 stderr=subprocess.STDOUT).wait()
724 if returncode == -1:

Subscribers

People subscribed via source and target branches