File indexing completed on 2024-05-26 04:34:18
0001 # SPDX-FileCopyrightText: 2029 Rebecca Breu <rebecca@rbreu.de> 0002 0003 # This file is part of Krita. 0004 0005 # Krita is free software: you can redistribute it and/or modify 0006 # it under the terms of the GNU General Public License as published by 0007 # the Free Software Foundation, either version 3 of the License, or 0008 # (at your option) any later version. 0009 0010 # Krita is distributed in the hope that it will be useful, 0011 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 # GNU General Public License for more details. 0014 0015 # You should have received a copy of the GNU General Public License 0016 # along with Krita. If not, see <https://www.gnu.org/licenses/>. 0017 0018 import mimetypes 0019 import os 0020 import urllib 0021 import urllib.request 0022 0023 0024 class PluginDownloadError(Exception): 0025 """Base class for all exceptions of this module.""" 0026 pass 0027 0028 0029 def is_zip(url): 0030 """Check if the given URL is a direct link to a zip file""" 0031 0032 MTYPE = 'application/zip' 0033 0034 # This just goes by the ending of the url string: 0035 if mimetypes.guess_type(url)[0] == MTYPE: 0036 return True 0037 0038 # Could still be a zip, so check the HTTP headers: 0039 try: 0040 request = urllib.request.Request(url, method='HEAD') 0041 response = urllib.request.urlopen(request) 0042 except Exception as e: 0043 raise PluginDownloadError(str(e)) 0044 0045 return response.getheader('Content-Type') == MTYPE 0046 0047 0048 def get_zipurl_github(base_path): 0049 """Guess the zip location from a github url""" 0050 0051 url = None 0052 split = base_path.split('/') 0053 if len(split) > 2: 0054 url = (f'https://api.github.com/repos/{split[1]}/{split[2]}/' 0055 'zipball/master') 0056 return (url, {'Accept': 'application/vnd.github.v3+json'}) 0057 0058 0059 def get_zipurl(url): 0060 """Guess the zip location from a given URL.""" 0061 0062 if is_zip(url): 0063 return (url, {}) 0064 0065 parsed = urllib.parse.urlparse(url) 0066 if parsed.netloc == 'github.com': 0067 return get_zipurl_github(parsed.path) 0068 0069 raise PluginDownloadError( 0070 i18n('Could not determine download link from URL')) 0071 0072 0073 def download_plugin(url, dest_dir): 0074 """Download a plugin from a given URL into the given directory. 0075 0076 ``url`` may either point directly to a zip location (on any site), 0077 or to a github repository. 0078 0079 Returns full path of the downloaded zip file. 0080 """ 0081 0082 dest_path = os.path.join(dest_dir, 'plugin.zip') 0083 zip_url, headers = get_zipurl(url) 0084 headers['User-Agent'] = 'krita-plugin-importer' 0085 0086 try: 0087 request = urllib.request.Request(zip_url, headers=headers) 0088 with urllib.request.urlopen(request) as source: 0089 with open(dest_path, 'wb') as destination: 0090 destination.write(source.read()) 0091 except Exception as e: 0092 raise PluginDownloadError(str(e)) 0093 return dest_path