OLD | NEW |
1 # Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from buildutil import BuildObject | 5 from buildutil import BuildObject |
6 from xml.dom import minidom | 6 from xml.dom import minidom |
7 | 7 |
8 import os | 8 import os |
9 import shutil | 9 import shutil |
10 import time | 10 import time |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 def _GetSize(self, update_path): | 125 def _GetSize(self, update_path): |
126 """Returns the size of the file given.""" | 126 """Returns the size of the file given.""" |
127 return os.path.getsize(update_path) | 127 return os.path.getsize(update_path) |
128 | 128 |
129 def _GetHash(self, update_path): | 129 def _GetHash(self, update_path): |
130 """Returns the sha1 of the file given.""" | 130 """Returns the sha1 of the file given.""" |
131 cmd = ('cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';' | 131 cmd = ('cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';' |
132 % update_path) | 132 % update_path) |
133 return os.popen(cmd).read().rstrip() | 133 return os.popen(cmd).read().rstrip() |
134 | 134 |
135 def GetUpdatePayload(self, hash, size, url): | 135 # TODO(petkov): Consider optimizing getting both SHA-1 and SHA-256 so that |
| 136 # it takes advantage of reduced I/O and multiple processors. Something like: |
| 137 # % tee < FILE > /dev/null \ |
| 138 # >( openssl dgst -sha256 -binary | openssl base64 ) \ |
| 139 # >( openssl sha1 -binary | openssl base64 ) |
| 140 def _GetSHA256(self, update_path): |
| 141 """Returns the sha256 of the file given.""" |
| 142 cmd = ('cat %s | openssl dgst -sha256 -binary | openssl base64' % |
| 143 update_path) |
| 144 return os.popen(cmd).read().rstrip() |
| 145 |
| 146 def GetUpdatePayload(self, hash, sha256, size, url): |
136 """Returns a payload to the client corresponding to a new update. | 147 """Returns a payload to the client corresponding to a new update. |
137 | 148 |
138 Args: | 149 Args: |
139 hash: hash of update blob | 150 hash: hash of update blob |
| 151 sha256: SHA-256 hash of update blob |
140 size: size of update blob | 152 size: size of update blob |
141 url: where to find update blob | 153 url: where to find update blob |
142 Returns: | 154 Returns: |
143 Xml string to be passed back to client. | 155 Xml string to be passed back to client. |
144 """ | 156 """ |
145 payload = """<?xml version="1.0" encoding="UTF-8"?> | 157 payload = """<?xml version="1.0" encoding="UTF-8"?> |
146 <gupdate xmlns="http://www.google.com/update2/response" protocol="2.0"> | 158 <gupdate xmlns="http://www.google.com/update2/response" protocol="2.0"> |
147 <daystart elapsed_seconds="%s"/> | 159 <daystart elapsed_seconds="%s"/> |
148 <app appid="{%s}" status="ok"> | 160 <app appid="{%s}" status="ok"> |
149 <ping status="ok"/> | 161 <ping status="ok"/> |
150 <updatecheck | 162 <updatecheck |
151 codebase="%s" | 163 codebase="%s" |
152 hash="%s" | 164 hash="%s" |
| 165 sha256="%s" |
153 needsadmin="false" | 166 needsadmin="false" |
154 size="%s" | 167 size="%s" |
155 status="ok"/> | 168 status="ok"/> |
156 </app> | 169 </app> |
157 </gupdate> | 170 </gupdate> |
158 """ | 171 """ |
159 return payload % (self._GetSecondsSinceMidnight(), | 172 return payload % (self._GetSecondsSinceMidnight(), |
160 self.app_id, url, hash, size) | 173 self.app_id, url, hash, sha256, size) |
161 | 174 |
162 def GetNoUpdatePayload(self): | 175 def GetNoUpdatePayload(self): |
163 """Returns a payload to the client corresponding to no update.""" | 176 """Returns a payload to the client corresponding to no update.""" |
164 payload = """ < ?xml version = "1.0" encoding = "UTF-8"? > | 177 payload = """ < ?xml version = "1.0" encoding = "UTF-8"? > |
165 < gupdate xmlns = "http://www.google.com/update2/response" protocol = "2.0
" > | 178 < gupdate xmlns = "http://www.google.com/update2/response" protocol = "2.0
" > |
166 < daystart elapsed_seconds = "%s" /> | 179 < daystart elapsed_seconds = "%s" /> |
167 < app appid = "{%s}" status = "ok" > | 180 < app appid = "{%s}" status = "ok" > |
168 < ping status = "ok" /> | 181 < ping status = "ok" /> |
169 < updatecheck status = "noupdate" /> | 182 < updatecheck status = "noupdate" /> |
170 </ app > | 183 </ app > |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 stanza[kind + '_size']) | 416 stanza[kind + '_size']) |
404 return (None, None, None) | 417 return (None, None, None) |
405 | 418 |
406 def HandleFactoryRequest(self, hostname, board_id, channel): | 419 def HandleFactoryRequest(self, hostname, board_id, channel): |
407 (filename, checksum, size) = self.GetFactoryImage(board_id, channel) | 420 (filename, checksum, size) = self.GetFactoryImage(board_id, channel) |
408 if filename is None: | 421 if filename is None: |
409 web.debug('unable to find image for board %s' % board_id) | 422 web.debug('unable to find image for board %s' % board_id) |
410 return self.GetNoUpdatePayload() | 423 return self.GetNoUpdatePayload() |
411 url = 'http://%s/static/%s' % (hostname, filename) | 424 url = 'http://%s/static/%s' % (hostname, filename) |
412 web.debug('returning update payload ' + url) | 425 web.debug('returning update payload ' + url) |
413 return self.GetUpdatePayload(checksum, size, url) | 426 # Factory install is using memento updater which is using the sha-1 hash so |
| 427 # setting sha-256 to an empty string. |
| 428 return self.GetUpdatePayload(checksum, '', size, url) |
414 | 429 |
415 def HandleUpdatePing(self, data, label=None): | 430 def HandleUpdatePing(self, data, label=None): |
416 """Handles an update ping from an update client. | 431 """Handles an update ping from an update client. |
417 | 432 |
418 Args: | 433 Args: |
419 data: xml blob from client. | 434 data: xml blob from client. |
420 label: optional label for the update. | 435 label: optional label for the update. |
421 Returns: | 436 Returns: |
422 Update payload message for client. | 437 Update payload message for client. |
423 """ | 438 """ |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 self.forced_image = None | 482 self.forced_image = None |
468 elif self.serve_only: | 483 elif self.serve_only: |
469 has_built_image = self.GenerateImageFromZip(static_image_dir) | 484 has_built_image = self.GenerateImageFromZip(static_image_dir) |
470 else: | 485 else: |
471 has_built_image = self.GenerateLatestUpdateImage(board_id, | 486 has_built_image = self.GenerateLatestUpdateImage(board_id, |
472 client_version, | 487 client_version, |
473 static_image_dir) | 488 static_image_dir) |
474 | 489 |
475 if has_built_image: | 490 if has_built_image: |
476 hash = self._GetHash(os.path.join(static_image_dir, 'update.gz')) | 491 hash = self._GetHash(os.path.join(static_image_dir, 'update.gz')) |
| 492 sha256 = self._GetSHA256(os.path.join(static_image_dir, 'update.gz')) |
477 size = self._GetSize(os.path.join(static_image_dir, 'update.gz')) | 493 size = self._GetSize(os.path.join(static_image_dir, 'update.gz')) |
478 if self.static_urlbase and label: | 494 if self.static_urlbase and label: |
479 url = '%s/%s/update.gz' % (self.static_urlbase, label) | 495 url = '%s/%s/update.gz' % (self.static_urlbase, label) |
480 elif self.serve_only: | 496 elif self.serve_only: |
481 url = 'http://%s/static/archive/update.gz' % hostname | 497 url = 'http://%s/static/archive/update.gz' % hostname |
482 else: | 498 else: |
483 url = 'http://%s/static/update.gz' % hostname | 499 url = 'http://%s/static/update.gz' % hostname |
484 return self.GetUpdatePayload(hash, size, url) | 500 return self.GetUpdatePayload(hash, sha256, size, url) |
485 else: | 501 else: |
486 return self.GetNoUpdatePayload() | 502 return self.GetNoUpdatePayload() |
OLD | NEW |