Permalink
Browse files

Replace AdobeFlashURLProvider with new AdobeFlashDownloadDecoder

- now we just download a (hopefully) stable URL and decode it with `security`, thanks to
  tip from @MagerValp
- new AdobeFlashDownloadDecoder re-uses URLDownloader's 'pathname' output variable
  contain the scope of changes to only the .download recipe
  • Loading branch information...
1 parent 7362ba6 commit d3e9e717136fbd6041a4d2abc23633f7b32067a1 @timsutton timsutton committed Jan 26, 2015
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+#
+# Copyright 2015 Tim Sutton
+#
+# 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.
+"""See docstring for AdobeFlashDownloadDecoder class"""
+
+import os
+import subprocess
+
+from autopkglib import Processor, ProcessorError
+
+
+__all__ = ["AdobeFlashDownloadDecoder"]
+
+#pylint: disable=missing-docstring
+#pylint: disable=e1101
+
+class AdobeFlashDownloadDecoder(Processor):
+ '''Decodes an Adobe Flash Download using `security cms`. Thanks to Per
+ Olofsson for documenting the use of the `security` command to decode the
+ ASN-1 data from Adobe's Flash Player download.'''
+ description = __doc__
+ input_variables = {
+ "encoded_path": {
+ "required": True,
+ "description": ("Path to a downloaded, encoded DMG from Adobe's "
+ "auto-update url."),
+ },
+ }
+ output_variables = {
+ "pathname": {
+ "description": ("Path to the decoded DMG file. Note that this is "
+ "the same variable name as output by "
+ "URLDownloader, since we have ."),
@gregneagle
gregneagle Jan 26, 2015 Contributor

Got distracted mid-thought?
I'm confused as to what is happening here.

+ },
+ }
+
+ def main(self):
+ '''Decode the file specified at encoded_path to a new file stored
+ in the pathname variable.'''
+ inpath = self.env["encoded_path"]
+ outpath = os.path.join(self.env["RECIPE_CACHE_DIR"],
+ "flash_decoded.dmg")
+ sec_cmd = ["/usr/bin/security", "cms", "-D",
+ "-i", inpath,
+ "-o", outpath]
+ # wrap our call around a general exception in case of unexpected
+ # issues calling `security`
+ try:
+ proc = subprocess.Popen(sec_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ _, err = proc.communicate()
+ # we expect no output on success, so raise an error in case
+ # of any non-zero return code or stderr output
+ if proc.returncode or err:
+ raise ProcessorError("`security` error: %s, return code: %s"
+ % (err, proc.returncode))
+ except Exception as exp:
+ raise ProcessorError("Unexpected exception in running `security` "
+ "command: %s" % exp)
+ self.env["pathname"] = outpath
+
+
+if __name__ == '__main__':
+ PROCESSOR = AdobeFlashDownloadDecoder()
+ PROCESSOR.execute_shell()
@@ -17,15 +17,22 @@
<array>
<dict>
<key>Processor</key>
- <string>AdobeFlashURLProvider</string>
- </dict>
- <dict>
- <key>Processor</key>
<string>URLDownloader</string>
<key>Arguments</key>
<dict>
<key>filename</key>
<string>%NAME%.dmg</string>
@gregneagle
gregneagle Jan 26, 2015 Contributor

Why are we naming the download %NAME%.dmg ? It's not a valid dmg (yet). Why not just leave it "install_all_mac_pl_sgn.z"

+ <key>url</key>
+ <string>http://fpdownload2.macromedia.com/get/flashplayer/update/current/install/install_all_mac_pl_sgn.z</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Processor</key>
+ <string>AdobeFlashDownloadDecoder</string>
+ <key>Arguments</key>
+ <dict>
+ <key>encoded_path</key>
+ <string>%pathname%</string>
</dict>
</dict>
<dict>
@@ -1,100 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2010 Per Olofsson
-#
-# 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.
-"""See docstring for AdobeFlashURLProvider class"""
-
-
-import urllib2
-from xml.etree import ElementTree
-
-from autopkglib import Processor, ProcessorError
-
-
-__all__ = ["AdobeFlashURLProvider"]
-
-UPDATE_XML_URL = ("http://fpdownload2.macromedia.com/"
- "get/flashplayer/update/current/xml/version_en_mac_pl.xml")
-
-DOWNLOAD_TEMPLATE_URL = ("http://fpdownload.macromedia.com/"
- "get/flashplayer/pdc/%s/install_flash_player_osx.dmg")
-
-class AdobeFlashURLProvider(Processor):
- """Provides URL to the latest Adobe Flash Player release."""
- description = __doc__
- input_variables = {
- "url": {
- "required": False,
- "description": ("Override URL. If provided, this processor "
- "just returns without doing anything."),
- },
- "version": {
- "required": False,
- "description": ("Specific version to download. If not defined, "
- "defaults to latest version.")
- },
- }
- output_variables = {
- "url": {
- "description": "URL to the latest Adobe Flash Player release.",
- },
- }
-
- def get_adobeflash_dmg_url(self):
- '''Return the URL for the Adobe Flash DMG'''
- version = self.env.get("version")
- if not version:
- # Read update XML.
- try:
- fref = urllib2.urlopen(UPDATE_XML_URL)
- xml_data = fref.read()
- fref.close()
- except BaseException as err:
- raise ProcessorError(
- "Can't download %s: %s" % (UPDATE_XML_URL, err))
-
- # parse XML data
- try:
- root = ElementTree.fromstring(xml_data)
- except (OSError, IOError, ElementTree.ParseError), err:
- raise Exception("Can't read %s: %s" % (xml_data, err))
-
- # extract version number from the XML
- version = None
- if root.tag == "XML":
- update = root.find("update")
- if update is not None:
- version = update.attrib.get('version')
-
- if not version:
- raise ProcessorError("Update XML in unexpected format.")
- else:
- self.output("Using provided version %s" % version)
-
- # use version number to build a download URL
- version = version.replace(",", ".")
- return DOWNLOAD_TEMPLATE_URL % version
-
- def main(self):
- '''Return a download URL for latest Mac Flash Player'''
- if "url" in self.env:
- self.output("Using input URL %s" % self.env["url"])
- return
- self.env["url"] = self.get_adobeflash_dmg_url()
- self.output("Found URL %s" % self.env["url"])
-
-
-if __name__ == '__main__':
- PROCESSOR = AdobeFlashURLProvider()
- PROCESSOR.execute_shell()

0 comments on commit d3e9e71

Please sign in to comment.