feat(ST2.UtilPackages): bump up all packages

- Refresh PackageCache with latest versions of everything
This commit is contained in:
Iristyle
2013-09-16 22:35:46 -04:00
parent 7195197f0f
commit a000ce8acc
451 changed files with 14151 additions and 8317 deletions

View File

@@ -20,12 +20,19 @@ SETTINGS = [
"alias_path",
"alias_folder_index",
"debug",
"auto_refresh_sidebar"
"auto_refresh_sidebar",
"completion_type",
"complete_single_entry",
"use_folder_name",
"relative_from_current",
"default_extension"
]
VIEW_NAME = "AdvancedNewFileCreation"
WIN_ROOT_REGEX = r"[a-zA-Z]:(/|\\)"
NIX_ROOT_REGEX = r"^/"
HOME_REGEX = r"^~"
PLATFORM = sublime.platform().lower()
IS_ST3 = int(sublime.version()) > 3000
# Set up logger
logging.basicConfig(format='[AdvancedNewFile] %(levelname)s %(message)s')
@@ -33,8 +40,8 @@ logger = logging.getLogger()
class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
def run(self, is_python=False):
self.PLATFORM = sublime.platform().lower()
def run(self, is_python=False, initial_path=None):
PLATFORM = sublime.platform().lower()
self.root = None
self.alias_root = None
self.top_level_split_char = ":"
@@ -42,37 +49,34 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
self.view = self.window.active_view()
# Settings will be based on the view
settings = get_settings(self.view)
self.aliases = self.get_aliases(settings)
self.show_path = settings.get("show_path")
self.auto_refresh_sidebar = settings.get("auto_refresh_sidebar")
self.default_folder_index = settings.get("default_folder_index")
self.alias_folder_index = settings.get("alias_folder_index")
default_root = self.get_default_root(settings.get("default_root"))
self.settings = get_settings(self.view)
self.aliases = self.get_aliases()
self.show_path = self.settings.get("show_path")
self.default_folder_index = self.settings.get("default_folder_index")
self.alias_folder_index = self.settings.get("alias_folder_index")
default_root = self.get_default_root(self.settings.get("default_root"))
if default_root == "path":
self.root = os.path.expanduser(settings.get("default_path"))
self.root = os.path.expanduser(self.settings.get("default_path"))
default_root = ""
self.root, path = self.split_path(default_root)
# Set some default values for the auto complete
PathAutocomplete.set_show_files(settings.get("show_files"))
PathAutocomplete.set_aliases(self.aliases)
PathAutocomplete.set_ignore_case(settings.get("ignore_case"))
# Search for initial string
path = settings.get("default_initial", "")
if settings.get("use_cursor_text", False):
tmp = self.get_cursor_path()
if tmp != "":
path = tmp
if initial_path is not None:
path = initial_path
else:
path = self.settings.get("default_initial", "")
if self.settings.get("use_cursor_text", False):
tmp = self.get_cursor_path()
if tmp != "":
path = tmp
alias_root = self.get_default_root(settings.get("alias_root"), True)
alias_root = self.get_default_root(self.settings.get("alias_root"), True)
if alias_root == "path":
self.alias_root = os.path.expanduser(settings.get("alias_path"))
self.alias_root = os.path.expanduser(self.settings.get("alias_path"))
alias_root = ""
self.alias_root, tmp = self.split_path(alias_root, True)
debug = settings.get("debug") or False
debug = self.settings.get("debug") or False
if debug:
logger.setLevel(logging.DEBUG)
else:
@@ -80,12 +84,12 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
# Get user input
self.show_filename_input(path)
def get_aliases(self, settings):
aliases = settings.get("alias")
all_os_aliases = settings.get("os_specific_alias")
def get_aliases(self):
aliases = self.settings.get("alias")
all_os_aliases = self.settings.get("os_specific_alias")
for key in all_os_aliases:
if self.PLATFORM in all_os_aliases.get(key):
aliases[key] = all_os_aliases.get(key).get(self.PLATFORM)
if PLATFORM in all_os_aliases.get(key):
aliases[key] = all_os_aliases.get(key).get(PLATFORM)
return aliases
@@ -122,7 +126,7 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
root = None
try:
# Parse windows root
if self.PLATFORM == "windows":
if PLATFORM == "windows":
if re.match(WIN_ROOT_REGEX, path):
root = path[0:3]
path = path[3:]
@@ -137,10 +141,30 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
if parts[1] != "":
path_list.append(parts[1])
path = self.top_level_split_char.join(path_list)
elif re.match(r"^/", path):
path_offset = 1
if PLATFORM == "windows":
match = re.match(r"^/([a-zA-Z])/", path)
if match:
root = "%s:\\" % match.group(1)
path_offset = 3
else:
root, _ = os.path.splitdrive(self.view.file_name())
root += "\\"
else:
root = "/"
path = path[path_offset:]
# Parse if tilde used
elif re.match(HOME_REGEX, path) and root == None:
root = os.path.expanduser("~")
path = path[2:]
elif re.match(r"^\.{1,2}[/\\]", path) and self.settings.get("relative_from_current", False):
path_index = 2
root = os.path.dirname(self.view.file_name())
if re.match(r"^\.{2}[/\\]", path):
root = os.path.dirname(root)
path_index = 3
path = path[path_index:]
# Default
if root == None:
@@ -153,6 +177,8 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
root = root or self.window.folders()[folder_index]
except IndexError:
root = os.path.expanduser("~")
return root, path
def translate_alias(self, path):
@@ -169,9 +195,8 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
root_found = False
while join_index >= 0 and not root_found:
# Folder aliases
for folder in self.window.folders():
basename = os.path.basename(folder)
if basename == target:
for name, folder in get_project_folder_data(self.settings.get("use_folder_name")):
if name == target:
root = folder
root_found = True
break
@@ -180,7 +205,7 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
if alias == target:
alias_path = self.aliases.get(alias)
if re.search(HOME_REGEX, alias_path) is None:
if self.PLATFORM == "windows":
if PLATFORM == "windows":
if re.search(WIN_ROOT_REGEX, alias_path) is None:
root = os.path.join(self.alias_root, alias_path)
break
@@ -208,51 +233,218 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
caption = 'Enter a path for a new file'
if self.is_python:
caption = '%s (creates __init__.py in new dirs)' % caption
view = self.window.show_input_panel(
self.input_panel_view = self.window.show_input_panel(
caption, initial,
self.entered_filename, self.update_filename_input, self.clear
)
view.set_name(VIEW_NAME)
temp = view.settings().get("word_separators")
temp = temp.replace(".", "")
view.settings().set("word_separators", temp)
view.settings().set("auto_complete_commit_on_tab", True)
view.settings().set("tab_completion", True)
PathAutocomplete.set_view_id(view.id())
PathAutocomplete.set_root(self.root, True)
self.input_panel_view.set_name(VIEW_NAME)
self.input_panel_view.settings().set("auto_complete_commit_on_tab", False)
self.input_panel_view.settings().set("tab_completion", False)
self.input_panel_view.settings().set("translate_tabs_to_spaces", False)
self.input_panel_view.settings().set("anf_panel", True)
def update_filename_input(self, path_in):
base, path = self.split_path(path_in)
if self.top_level_split_char in path_in or re.match(r"^~[/\\]", path_in):
PathAutocomplete.set_root(base, False)
else:
PathAutocomplete.set_root(base, True)
if self.settings.get("completion_type") == "windows":
if "prev_text" in dir(self) and self.prev_text != path_in:
if self.view is not None:
self.view.erase_status("AdvancedNewFile2")
if path_in.endswith("\t"):
path_in = path_in.replace("\t", "")
if self.settings.get("completion_type") == "windows":
path_in = self.windows_completion(path_in)
elif self.settings.get("completion_type") == "nix":
path_in = self.nix_completion(path_in)
creation_path = self.generate_creation_path(base, path)
base, path = self.split_path(path_in)
creation_path = self.generate_creation_path(base, path, True)
if self.show_path:
if self.view != None:
self.view.set_status("AdvancedNewFile", "Creating file at %s " % \
creation_path)
else:
sublime.status_message("Creating file at %s " % creation_path)
sublime.status_message("Creating file at %s" % creation_path)
logger.debug("Creation path is '%s'" % creation_path)
PathAutocomplete.set_path(path)
def generate_creation_path(self, base, path):
if self.PLATFORM == "windows":
def generate_completion_list(self, path_in, each_list=False):
alias_list = []
dir_list = []
file_list = []
self.suggestion_entries = []
if self.top_level_split_char in path_in or re.match(r"^~[/\\]", path_in):
pass
else:
directory, filename = os.path.split(path_in)
if len(directory) == 0:
alias_list += self.generate_alias_auto_complete(filename)
alias_list += self.generate_project_auto_complete(filename)
base, path = self.split_path(path_in)
full_path = self.generate_creation_path(base, path)
directory, filename = os.path.split(full_path)
if os.path.isdir(directory):
for d in os.listdir(directory):
full_path = os.path.join(directory, d)
if os.path.isdir(full_path):
is_file = False
elif self.settings.get("show_files"):
is_file = True
else:
continue
if self.compare_entries(d, filename):
if is_file:
file_list.append(d)
else:
dir_list.append(d)
completion_list = alias_list + dir_list + file_list
return sorted(completion_list), alias_list, dir_list, file_list
def windows_completion(self, path_in):
pattern = r"(.*[/\\:])(.*)"
match = re.match(pattern, path_in)
if "prev_text" in dir(self) and self.prev_text == path_in:
self.offset = (self.offset + 1) % len(self.completion_list)
else:
# Generate new completion list
self.completion_list, self.alias_list, self.dir_list, self.file_list = self.generate_completion_list(path_in)
self.offset = 0
if len(self.completion_list) == 0:
if match:
self.completion_list = [match.group(2)]
else:
self.completion_list = [path_in]
match = re.match(pattern, path_in)
if match :
completion = self.completion_list[self.offset]
if self.settings.get("complete_single_entry"):
if len(self.completion_list) == 1:
if completion in self.alias_list:
completion += ":"
elif completion in self.dir_list:
completion += "/"
new_content = re.sub(pattern, r"\1" , path_in)
new_content += completion
first_token = False
else:
completion = self.completion_list[self.offset]
if self.settings.get("complete_single_entry"):
if len(self.completion_list) == 1:
if completion in self.alias_list:
completion += ":"
elif completion in self.dir_list:
completion += "/"
new_content = completion
first_token = True
if len(self.completion_list) > 1:
if first_token:
if self.view is not None:
if self.completion_list[self.offset] in self.alias_list:
self.view.set_status("AdvancedNewFile2", "Alias Completion")
elif self.completion_list[self.offset] in self.dir_list:
self.view.set_status("AdvancedNewFile2", "Directory Completion")
self.prev_text = new_content
else:
self.prev_text = None
self.input_panel_view.run_command("anf_replace", {"content": new_content})
return new_content
def nix_completion(self, path_in):
pattern = r"(.*[/\\:])(.*)"
completion_list, alias_list, dir_list, file_list = self.generate_completion_list(path_in)
new_content = path_in
if len(completion_list) > 0:
common = os.path.commonprefix(completion_list)
match = re.match(pattern, path_in)
if match :
new_content = re.sub(pattern, r"\1", path_in)
new_content += common
else:
new_content = common
if len(completion_list) > 1:
dir_list = map(lambda s: s + "/", dir_list)
alias_list = map(lambda s: s + ":", alias_list)
status_message_list = sorted(list(dir_list) + list(alias_list) + file_list)
sublime.status_message(", ".join(status_message_list))
else:
if completion_list[0] in alias_list:
new_content += ":"
elif completion_list[0] in dir_list:
new_content += "/"
self.input_panel_view.run_command("anf_replace", {"content": new_content})
return new_content
def generate_project_auto_complete(self, base):
folder_data = get_project_folder_data(self.settings.get("use_folder_name"))
if len(folder_data) > 1:
folders = [x[0] for x in folder_data]
return self.generate_auto_complete(base, folders)
return []
def generate_alias_auto_complete(self, base):
return self.generate_auto_complete(base, self.aliases)
def generate_auto_complete(self, base, iterable_var):
sugg = []
for entry in iterable_var:
if entry in self.suggestion_entries:
continue
self.suggestion_entries.append(entry)
compare_entry = entry
compare_base = base
if self.settings.get("ignore_case"):
compare_entry = compare_entry.lower()
compare_base = compare_base.lower()
if self.compare_entries(compare_entry, compare_base):
sugg.append(entry)
return sugg
def compare_entries(self, compare_entry, compare_base):
if self.settings.get("ignore_case"):
compare_entry = compare_entry.lower()
compare_base = compare_base.lower()
return compare_entry.startswith(compare_base)
def generate_creation_path(self, base, path, append_extension=False):
if PLATFORM == "windows":
if not re.match(WIN_ROOT_REGEX, base):
return base + self.top_level_split_char + path
else:
if not re.match(NIX_ROOT_REGEX, base):
return base + self.top_level_split_char + path
return os.path.abspath(os.path.join(base, path))
tokens = re.split(r"[/\\]", base) + re.split(r"[/\\]", path)
if tokens[0] == "":
tokens[0] = "/"
if PLATFORM == "windows":
tokens[0] = base[0:3]
full_path = os.path.abspath(os.path.join(*tokens))
if re.search(r"[/\\]$", path) or len(path) == 0:
full_path += os.path.sep
elif re.search(r"\.", tokens[-1]):
if re.search(r"\.$", tokens[-1]):
full_path += "."
elif append_extension:
filename = os.path.basename(full_path)
if not os.path.exists(full_path):
full_path += self.settings.get("default_extension", "")
return full_path
def entered_filename(self, filename):
# Check if valid root specified for windows.
if self.PLATFORM == "windows":
if PLATFORM == "windows":
if re.match(WIN_ROOT_REGEX, filename):
root = filename[0:3]
if not os.path.isdir(root):
@@ -261,11 +453,11 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
return
base, path = self.split_path(filename)
file_path = os.path.join(base, path)
file_path = self.generate_creation_path(base, path, True)
# Check for invalid alias specified.
if self.top_level_split_char in filename and \
not (self.PLATFORM == "windows" and re.match(WIN_ROOT_REGEX, base)) and \
not (self.PLATFORM != "windows" and re.match(NIX_ROOT_REGEX, base)):
not (PLATFORM == "windows" and re.match(WIN_ROOT_REGEX, base)) and \
not (PLATFORM != "windows" and re.match(NIX_ROOT_REGEX, base)):
if base == "":
error_message = "Current file cannot be resolved."
else:
@@ -291,17 +483,16 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
self.refresh_sidebar()
def refresh_sidebar(self):
if self.auto_refresh_sidebar:
if self.settings.get("auto_refresh_sidebar"):
try:
self.window.run_command("refresh_folder_list")
except:
pass
def clear(self):
if self.view != None:
self.view.erase_status("AdvancedNewFile")
PathAutocomplete.clear()
self.view.erase_status("AdvancedNewFile2")
def create(self, filename):
base, filename = os.path.split(filename)
@@ -310,13 +501,21 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
open(os.path.join(base, filename), "a").close()
def create_folder(self, path):
init_list = []
if self.is_python:
temp_path = path
while not os.path.exists(temp_path):
init_list.append(temp_path)
temp_path = os.path.dirname(temp_path)
try:
os.makedirs(path)
if not os.path.exists(path):
os.makedirs(path)
except OSError as ex:
if ex.errno != errno.EEXIST:
raise
if self.is_python:
open(os.path.join(base, '__init__.py'), 'a').close()
for entry in init_list:
open(os.path.join(entry, '__init__.py'), 'a').close()
def get_cursor_path(self):
if self.view == None:
@@ -325,7 +524,7 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
view = self.view
path = ""
for region in view.sel():
syntax = view.syntax_name(region.begin())
syntax = view.scope_name(region.begin())
if region.begin() != region.end():
path = view.substr(region)
break
@@ -337,226 +536,22 @@ class AdvancedNewFileCommand(sublime_plugin.WindowCommand):
return path
class PathAutocomplete(sublime_plugin.EventListener):
aliases = {}
show_files = False
ignore_case = False
class AnfReplaceCommand(sublime_plugin.TextCommand):
def run(self, edit, content):
self.view.replace(edit, sublime.Region(0, self.view.size()), content)
path = ""
root = ""
default_root = True
view_id = None
prev_suggestions = []
prev_base = ""
prev_directory = ""
path_empty = True
prev_root = ""
prev_prefix = ""
prev_locations = []
class AdvancedNewFileAtCommand(sublime_plugin.WindowCommand):
def run(self, dirs):
if len(dirs) != 1:
return
path = dirs[0]
self.window.run_command("advanced_new_file", {"initial_path": path + os.sep})
def on_query_context(self, view, key, operator, operand, match_all):
if key == "advanced_new_file_completion" and PathAutocomplete.view_id != None and view.id() == PathAutocomplete.view_id:
return True
return None
def continue_previous_autocomplete(self):
pac = PathAutocomplete
sep = os.sep
root_path = pac.root + sep
prev_base = pac.prev_base
prev_directory = pac.prev_directory
prev_root = pac.prev_root
base = os.path.basename(pac.path)
directory = os.path.dirname(pac.path)
# If base is empty, we may be cycling through directory options
if base == "":
return True
# Ensures the correct directory is used if the default root is specified
# using an alias.
if base == prev_base and \
directory == prev_directory and \
prev_root == root_path and \
pac.default_root:
return True
# Continue completions if file names are completed.
if os.path.isfile(os.path.join(root_path, pac.path)):
return True
return False
def on_query_completions(self, view, prefix, locations):
self.suggestion_entries = []
pac = PathAutocomplete
if pac.view_id == None or view.id() != pac.view_id:
return []
auto_complete_prefix = ""
if self.continue_previous_autocomplete() and prefix != "":
logger.debug("(Prev) Suggestions")
logger.debug(pac.prev_suggestions)
if len(pac.prev_suggestions) > 1:
return (pac.prev_suggestions, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
elif len(pac.prev_suggestions) == 1:
auto_complete_prefix = pac.prev_suggestions[0][1]
suggestions = []
suggestions_w_spaces = []
root_path = pac.root + os.sep
directory, base = os.path.split(pac.path)
if directory == "" and pac.default_root:
# Project folders
sugg, sugg_w_spaces = self.generate_project_auto_complete(base)
suggestions += sugg
suggestions_w_spaces += sugg_w_spaces
# Aliases
sugg, sugg_w_spaces = self.generate_alias_auto_complete(base)
suggestions += sugg
suggestions_w_spaces += sugg_w_spaces
# Directories
path = os.path.join(root_path, directory)
if os.path.exists(path):
sugg, sugg_w_spaces = self.generate_relative_auto_complete(path, base, auto_complete_prefix)
suggestions += sugg
suggestions_w_spaces += sugg_w_spaces
# If suggestions exist, use complete name
# else remove base prefix
if len(suggestions) > 0:
for name in suggestions_w_spaces:
suggestions.append((" " + name, name))
else:
for name in suggestions_w_spaces:
temp = name
name = name[len(base) - 1:]
suggestions.append((" " + temp, name))
if len(suggestions) == 0 and locations == pac.prev_locations:
return (pac.prev_suggestions, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
# Previous used to determine cycling through entries.
pac.prev_directory = directory
pac.prev_base = base
pac.prev_suggestions = suggestions
pac.prev_root = root_path
pac.prev_prefix = prefix
pac.prev_locations = locations
logger.debug("Suggestions:")
logger.debug(suggestions)
return (suggestions, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
def generate_project_auto_complete(self, base):
folders = sublime.active_window().folders()
if len(folders) > 1:
folders = map(lambda f: os.path.basename(f), folders)
return self.generate_auto_complete(base, folders)
return [], []
def generate_alias_auto_complete(self, base):
return self.generate_auto_complete(base, PathAutocomplete.aliases)
def generate_auto_complete(self, base, iterable_var):
sugg = []
sugg_w_spaces = []
for entry in iterable_var:
if entry in self.suggestion_entries:
continue
self.suggestion_entries.append(entry)
compare_entry = entry
compare_base = base
if PathAutocomplete.ignore_case:
compare_entry = compare_entry.lower()
compare_base = compare_base.lower()
if compare_entry.find(compare_base) == 0:
if " " in base:
sugg_w_spaces.append(entry + ":")
else:
sugg.append((entry + ":", entry + ":"))
return sugg, sugg_w_spaces
def generate_relative_auto_complete(self, path, base, auto_complete_prefix):
sep = os.sep
sugg = []
sugg_w_spaces = []
# Attempt to prevent searching the same path when a path has been specified
# Problems occur when using tab to complete entry with single completion
# followed by ctrl + space
if ":" in auto_complete_prefix:
compare_prefix = auto_complete_prefix.split(":", 1)[1]
else:
compare_prefix = auto_complete_prefix
if re.search(r"[/\\]$", auto_complete_prefix) and not path.endswith(compare_prefix[0:-1]):
path = os.path.join(path, compare_prefix)
for filename in os.listdir(path):
if PathAutocomplete.show_files or os.path.isdir(os.path.join(path, filename)):
compare_base = base
compare_filename = filename
if PathAutocomplete.ignore_case:
compare_base = compare_base.lower()
compare_filename = filename.lower()
if compare_filename.find(compare_base) == 0:
# Need to find a better way to do the auto complete.
if " " in compare_base:
if os.path.isdir(os.path.join(path, filename)):
sugg_w_spaces.append(auto_complete_prefix + filename + sep)
else:
sugg_w_spaces.append(auto_complete_prefix + filename)
else:
if os.path.isdir(os.path.join(path, filename)):
sugg.append((" " + auto_complete_prefix + filename + sep, auto_complete_prefix + filename + sep))
else:
sugg.append((" " + auto_complete_prefix + filename, auto_complete_prefix + filename))
return sugg, sugg_w_spaces
@staticmethod
def set_path(path_input):
PathAutocomplete.path = path_input
@staticmethod
def set_root(root_input, default_root):
PathAutocomplete.root = root_input
PathAutocomplete.default_root = default_root
@staticmethod
def clear():
PathAutocomplete.path = ""
PathAutocomplete.root = ""
PathAutocomplete.prev_suggestions = []
PathAutocomplete.prev_base = ""
PathAutocomplete.prev_directory = ""
PathAutocomplete.aliases = {}
PathAutocomplete.path_empty = True
PathAutocomplete.prev_root = ""
PathAutocomplete.default_root = True
PathAutocomplete.show_files = False
PathAutocomplete.prev_prefix = ""
PathAutocomplete.prev_locations = []
PathAutocomplete.view_id = None
@staticmethod
def set_aliases(aliases):
PathAutocomplete.aliases = aliases
@staticmethod
def set_show_files(show_files):
PathAutocomplete.show_files = show_files
@staticmethod
def set_ignore_case(ignore_case):
PathAutocomplete.ignore_case = ignore_case
@staticmethod
def set_view_id(view_id):
PathAutocomplete.view_id = view_id
def is_visible(self, dirs):
settings = sublime.load_settings("AdvancedNewFile.sublime-settings")
return settings.get("show_sidebar_menu", False) and len(dirs) == 1
def get_settings(view):
@@ -579,3 +574,31 @@ def get_settings(view):
logger.error("AdvancedNewFile[Warning]: Invalid key '%s' in project settings.", key)
return local_settings
def get_project_folder_data(use_folder_name):
folders = []
folder_entries = []
window = sublime.active_window()
project_folders = window.folders()
if IS_ST3:
project_data = window.project_data()
if project_data is not None:
if use_folder_name:
for folder in project_data.get("folders", []):
folder_entries.append({})
else:
folder_entries = project_data.get("folders", [])
else:
for folder in project_folders:
folder_entries.append({})
for index in range(len(folder_entries)):
folder_path = project_folders[index]
folder_entry = folder_entries[index]
if "name" in folder_entry:
folders.append((folder_entry["name"], folder_path))
else:
folders.append((os.path.basename(folder_path), folder_path))
return folders

View File

@@ -19,7 +19,7 @@
// A boolean defining if cursor text should be used. Text bound by single or
// double quotes or within a region will be used. If multiple cursors
// are used, the earliest selection containing a region or existing
// are used, the earliest selection containing a region or existing
// within quotes will be used.
// NOTE: A value read from cursor will override the default
// initial string setting.
@@ -55,7 +55,7 @@
// This value specifies the root that will be used when resolving relative paths
// defined in aliases. For more information about valid values, see "default_root".
// Note that if "default_path" or "default_folder_index" is used,
// Note that if "default_path" or "default_folder_index" is used,
// "alias_path" and "alias_folder_index" must be used for the respective entries.
"alias_root": "current",
@@ -76,5 +76,29 @@
// In some builds, the sidebar does not refresh when contents of project folder are updated.
// This setting is required to refresh the sidebar in these circumstances.
// false by default
"auto_refresh_sidebar": false
}
"auto_refresh_sidebar": false,
// A boolean specifying if an AdvancedNewFile option should be shown in the
// sidebar context menu.
"show_sidebar_menu": false,
// A string specifying the type of auto completion to use. Valid values are
// "windows" or "nix"
"completion_type": "windows",
// A boolean setting specifying if a separator should be inserted when
// there is only one completion and completion type is "windows"
"complete_single_entry": true,
// A boolean setting specifying if the folder name should be used
// or the name specified in the project. This setting only applies to ST3.
"use_folder_name": false,
// Boolean setting specifying if relative paths should be based on the
// current working directory.
"relative_from_current": true,
// String containing the default file extension. Note the extension is only applied
// if the specified path does not contain a dot (.) character.
"default_extension": ""
}

View File

@@ -1,6 +1,33 @@
# Changelog for AdvancedNewFile
- 9 September 2013
- Bug fix for folder creation.
- Bug fix for permission issue.
- Add default extension setting.
- 2 September 2013
- Add setting to begin all relative paths from current working directory if available.
- 14 August 2013
- Prompt completion type for first token when using Windows completion.
- Fix bug with path autocompletion.
- Fix bug for tab completion with no view.
- 27 July 2013
- Rewrite autocomplete functionality.
- Bug Fixes
- Snippets no longer appear when entering completions.
- 22 April 2013
- Add option to refresh sidebar after creating a file.
- Add side bar context menu.
- Bug Fixes
- Multiple autocomplete issues.
- Creation of __init__.py files.
- Filling text with cursor values.
- 2 February 2013
- Update to be compatible with Sublime Text 3.
- 14 January 2013
- Add `alias_root` setting, used with aliases with relative paths.
- Add setting to allow user to specify which folder from the project should be used.

View File

@@ -3,13 +3,10 @@
{ "keys": ["shift+super+alt+n"], "command": "advanced_new_file", "args": {"is_python": true}},
{
"keys": ["tab"],
"command": "insert_best_completion",
"args": {"default": "", "exact": false},
"context": [
{ "key": "advanced_new_file_completion"},
{ "key": "setting.tab_completion", "operator": "equal", "operand": true },
{ "key": "last_command", "operator": "not_equal", "operand": "insert_best_completion" },
{ "key": "auto_complete_visible" , "operator": "equal", "operand": false}
]
"command": "insert",
"args": {"characters": "\t"},
"context": [{
"key": "setting.anf_panel"
}]
}
]

View File

@@ -3,13 +3,10 @@
{ "keys": ["shift+super+alt+n"], "command": "advanced_new_file", "args": {"is_python": true}},
{
"keys": ["tab"],
"command": "insert_best_completion",
"args": {"default": "", "exact": false},
"context": [
{ "key": "advanced_new_file_completion"},
{ "key": "setting.tab_completion", "operator": "equal", "operand": true },
{ "key": "last_command", "operator": "not_equal", "operand": "insert_best_completion" },
{ "key": "auto_complete_visible" , "operator": "equal", "operand": false}
]
"command": "insert",
"args": {"characters": "\t"},
"context": [{
"key": "setting.anf_panel"
}]
}
]

View File

@@ -1,16 +1,12 @@
[
{ "keys": ["ctrl+alt+n"], "command": "advanced_new_file"},
{ "keys": ["shift+ctrl+alt+n"], "command": "advanced_new_file", "args": {"is_python": true}},
// Forces insert best autocomplete to run for advanced new file
{
"keys": ["tab"],
"command": "insert_best_completion",
"args": {"default": "", "exact": false},
"context": [
{ "key": "advanced_new_file_completion"},
{ "key": "setting.tab_completion", "operator": "equal", "operand": true },
{ "key": "last_command", "operator": "not_equal", "operand": "insert_best_completion" },
{ "key": "auto_complete_visible" , "operator": "equal", "operand": false}
]
"command": "insert",
"args": {"characters": "\t"},
"context": [{
"key": "setting.anf_panel"
}]
}
]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2012 AdvancedNewFile authors
Copyright (c) 2013 AdvancedNewFile authors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,

View File

@@ -22,6 +22,12 @@ Clone or copy this repository into the packages directory. By default, they are
* Windows: %APPDATA%/Roaming/Sublime Text 2/Packages/
* Linux: ~/.config/sublime-text-2/Packages/
or
* OS X: ~/Library/Application Support/Sublime Text 3/Packages/
* Windows: %APPDATA%/Roaming/Sublime Text 3/Packages/
* Linux: ~/.config/sublime-text-3/Packages/
## Usage
Simply bring up the AdvancedNewFile input through the appropriate [key binding](https://github.com/skuroda/Sublime-AdvancedNewFile). Then, enter the path, along with the file name into the input field. Upon pressing enter, the file will be created. In addition, if the directories specified do not yet exists, they will also be created. For more advanced usage of this plugin, be sure to look at [Advanced Path Usage](https://github.com/skuroda/Sublime-AdvancedNewFile#advanced-path-usage). By default, the path to the file being created will be filled shown in the status bar as you enter the path information.
@@ -107,13 +113,35 @@ A boolean specifying if case should be ignored when building auto complete list.
A boolean specifying if folders should automatically refresh and update the sidebar. In some builds, the sidebar does not refresh when contents of project folder are updated. This setting is required to refresh the sidebar in these circumstances. False by default.
`show_sidebar_menu`:
A boolean specifying if an AdvancedNewFile option should be shown in the sidebar context menu.
`completion_type`:
A string specifying the type of auto completion to use. Valid values are "windows" or "nix".
`complete_single_entry`
A boolean setting specifying if a separator should be inserted when there is only one completion and completion type is "windows"
`use_folder_name`:
A boolean setting specifying if the folder name should be used or the name specified in the project. This setting only applies to ST3.
`relative_from_current`:
Boolean setting specifying if relative paths should be based on the current working directory.
`default_extension`:
String containing the default file extension. Note the extension is only applied if the specified path does not contain a dot (.) character.
### Project Specific Settings
All of the above settings can also be specified as part of the project specific settings. These values override any previous values set by higher level settings, with aliases being an exception. Alias settings will be merged with higher level configurations for alias. In addition, if the same alias exist for both default/user settings and project settings, the project setting will take precedence.
"settings":
{
"AdvancedNewFile":
{
"settings": {
"AdvancedNewFile": {
"default_initial": "/project/specific/path"
}
}
@@ -154,7 +182,7 @@ Sample OS Specific Aliases:
{
"os_specific_alias": {
"subl_packages" {
"subl_packages": {
"windows": "~\\AppData\\Roaming\\Sublime Text 2\\Packages",
"linux": "~/.config/sublime-text-2/Packages",
"osx": "~/Library/Application Support/Sublime Text 2/Packages"

View File

@@ -0,0 +1,3 @@
[
{ "caption": "Advanced New File", "command": "advanced_new_file_at", "args": {"dirs": []} }
]

View File

@@ -3,5 +3,8 @@
"2012.11.08.20.00.00": "messages/1.txt",
"2012.11.12.11.00.00": "messages/2.txt",
"2012.11.26.11.00.00": "messages/3.txt",
"2012.12.17.11.00.00": "messages/4.txt"
}
"2012.12.17.11.00.00": "messages/4.txt",
"2013.07.29.11.00.00": "messages/5.txt",
"2013.08.05.11.00.00": "messages/6.txt",
"2013.09.03.11.00.00": "messages/7.txt"
}

View File

@@ -0,0 +1,4 @@
- Rewrite autocomplete functionality to support *nix or windows style completions. Please see the README for details about new settings.
Bug Fixes:
- Snippets no longer appear when entering completions.

View File

@@ -0,0 +1 @@
- Merge ST2 and ST3 into a single version.

View File

@@ -0,0 +1,6 @@
Enhancements:
- Setting to allow relative paths to be based on the current working directory. Enabled by default.
Bug Fixes:
- Various fixes for auto completion
- Prompt completion type when using Windows Completion

View File

@@ -2,7 +2,7 @@ Thank you for installing the AdvancedNewFile plugin.
For more information please visit https://github.com/skuroda/Sublime-AdvancedNewFile.
Note you may need to restart Sublime Text 2 after installing this plugin.
Note you may need to restart Sublime Text after installing this plugin.
If you have any questions, comments, or run into issues, please let me know! Hope you enjoy the plugin.

View File

@@ -1 +1 @@
{"url": "https://github.com/skuroda/Sublime-AdvancedNewFile", "version": "2013.04.02.21.22.36", "description": "File creation plugin for Sublime Text 2 and Sublime Text 3."}
{"url": "https://github.com/skuroda/Sublime-AdvancedNewFile", "version": "2013.09.09.06.50.47", "description": "File creation plugin for Sublime Text 2 and Sublime Text 3."}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -1,3 +1,5 @@
For Sublime Text 3 See: https://github.com/SublimeText/EncodingHelper/tree/st3
Description
------------------

View File

@@ -1 +1 @@
{"url": "https://github.com/welefen/KeymapManager", "version": "2012.08.19.23.05.38", "description": "KeymapManager for sublime text 2"}
{"url": "https://github.com/welefen/KeymapManager", "version": "2012.08.20.03.05.38", "description": "KeymapManager plugin for sublime text 2"}

View File

@@ -1,14 +1,15 @@
[
{
"keys": ["ctrl+shift+end"],
"command": "move_tab",
"args": { "position": "999" }
},
{
"keys": ["ctrl+shift+home"],
"command": "move_tab",
"args": { "position": "0" }
},
// Uncomment to enable.
// {
// "keys": ["ctrl+shift+end"],
// "command": "move_tab",
// "args": { "position": "999" }
// },
// {
// "keys": ["ctrl+shift+home"],
// "command": "move_tab",
// "args": { "position": "0" }
// },
{
"keys": ["ctrl+shift+pageup"],
"command": "move_tab",

View File

@@ -1,14 +1,15 @@
[
{
"keys": ["super+alt+shift+down"],
"command": "move_tab",
"args": { "position": "999" }
},
{
"keys": ["super+alt+shift+up"],
"command": "move_tab",
"args": { "position": "0" }
},
// Uncomment to enable.
// {
// "keys": ["super+alt+shift+down"],
// "command": "move_tab",
// "args": { "position": "999" }
// },
// {
// "keys": ["super+alt+shift+up"],
// "command": "move_tab",
// "args": { "position": "0" }
// },
{
"keys": ["super+alt+shift+left"],
"command": "move_tab",

View File

@@ -1,14 +1,15 @@
[
{
"keys": ["ctrl+shift+end"],
"command": "move_tab",
"args": { "position": "999" }
},
{
"keys": ["ctrl+shift+home"],
"command": "move_tab",
"args": { "position": "0" }
},
// Uncomment to enable.
// {
// "keys": ["ctrl+shift+end"],
// "command": "move_tab",
// "args": { "position": "999" }
// },
// {
// "keys": ["ctrl+shift+home"],
// "command": "move_tab",
// "args": { "position": "0" }
// },
{
"keys": ["ctrl+shift+pageup"],
"command": "move_tab",

View File

@@ -1,7 +1,7 @@
Move Tab
========
Plugin for Sublime Text 2 to move tabs around.
Plugin for Sublime Text to move tabs around.
Usage
-----
@@ -13,21 +13,30 @@ The following commands are accessible via the command palette:
- Move Tab: To first position
- Move Tab: To last position
The shortcuts are:
The default shortcuts are:
- Linux/Windows: CTRL + Shift + (Page up / Page down / Home / End)
- MacOS X: Command + Alt + Shift + (Left / Right / Up / Down)
- Linux/Windows: CTRL + Shift + (Page up / Page down)
- MacOS X: Command + Alt + Shift + (Left / Right)
*Shortcuts to move to first or last position are disabled by default.*
Requirements
------------
Sublime Text 2 or 3.
Installation
------------
Clone this repository into the Packages directory. If you don't know where it is, enter the following command in the console:
Use the Package Control.
print sublime.packages_path()
Command palette > Package Control: Install Package
_To access the console press CTRL + `_
Alternatively, simply clone this repository into the Packages directory.
Preferences > Browse Packages...
License
-------
Licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php)
Licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php)

View File

@@ -3,7 +3,7 @@
"""
Move Tab
Plugin for Sublime Text 2 to move tabs around
Plugin for Sublime Text to move tabs around
Copyright (c) 2012 Frédéric Massart - FMCorz.net

View File

@@ -1 +1 @@
{"url": "https://github.com/SublimeText/MoveTab", "version": "2012.08.24.06.11.17", "description": "Plugin for Sublime Text 2 to move tabs around"}
{"url": "https://github.com/SublimeText/MoveTab", "version": "2013.09.12.08.16.08", "description": "Plugin for Sublime Text to move tabs around"}

View File

@@ -1 +1 @@
{"url": "https://github.com/timjrobinson/SublimeNavigationHistory", "version": "2013.03.17.15.51.45", "description": "SublimeText 2/3 Navigation History - jump forward and back around your code. "}
{"url": "https://github.com/timjrobinson/SublimeNavigationHistory", "version": "2013.03.17.19.51.45", "description": "SublimeText 2/3 Navigation History - jump forward and back around your code. "}

View File

@@ -1 +1 @@
{"url": "https://github.com/spadgos/sublime-OpenRecentFiles", "version": "2011.10.03.10.20.08", "description": "A package which adds Ctrl+Shift+T to open the most recent files."}
{"url": "https://github.com/spadgos/sublime-OpenRecentFiles", "version": "2011.10.03.14.20.08", "description": "A package which adds Ctrl+Shift+T to open the most recent files."}

View File

@@ -1,5 +1,6 @@
{
"highlight_search_icon": "bookmark",
"highlight_search_scope": "entity.name.function",
"highlight_search_results": false
}
"highlight_search_results": false,
"open_search_result_everywhere": false
}

View File

@@ -3,5 +3,13 @@
"keys": ["g", "o"],
"command": "open_search_result",
"context": [{"key": "setting.command_mode"}]
},
{
"keys": ["ctrl+enter"],
"command": "open_search_result",
"context":
[
{ "key": "selector", "operator": "equal", "operand": "text.find-in-files" }
]
}
]
]

View File

@@ -24,3 +24,6 @@ openable paths or the icon. See your theme file for examples of colors.
- 'highlight_search_icon': If you want an icon to show up in the gutter next to
openable paths, include a valid icon name as a string (e.g., 'circle', 'dot' or
'bookmark')
- 'open_search_result_everywhere': Set to true to enable this plugin on all
files not just Find Results panes. You can use this for saving and reopening
your find results.

View File

@@ -1,31 +1,40 @@
import os
import sublime, sublime_plugin
import util
# Load with Python3, fallback to load with Python2
try:
from .util import parse_line_number, is_file_path
except ValueError:
from util import parse_line_number, is_file_path
class OpenSearchResultKeys:
HIGHLIGHT_ENABLED = 'highlight_search_results'
SCOPE_SETTINGS = 'highlight_search_scope'
ICON_SETTINGS = 'highlight_search_icon'
OPEN_EVERYWHERE = 'open_search_result_everywhere'
class HighlightFilePaths(sublime_plugin.EventListener):
HIGHLIGHT_REGION_NAME = 'HighlightFilePaths'
HIGHLIGHT_ENABLED_KEY = 'highlight_search_results'
SCOPE_SETTINGS_KEY = 'highlight_search_scope'
ICON_SETTINGS_KEY = 'highlight_search_icon'
DEFAULT_SCOPE = 'search_result_highlight'
DEFAULT_ICON = ''
def show_highlight(self, view):
valid_regions = []
show_highlight = view.settings().get(self.HIGHLIGHT_ENABLED_KEY, False)
scope = view.settings().get(self.SCOPE_SETTINGS_KEY, self.DEFAULT_SCOPE)
icon = view.settings().get(self.ICON_SETTINGS_KEY, self.DEFAULT_ICON)
show_highlight = view.settings().get(OpenSearchResultKeys.HIGHLIGHT_ENABLED, False)
scope = view.settings().get(OpenSearchResultKeys.SCOPE_SETTINGS, self.DEFAULT_SCOPE)
icon = view.settings().get(OpenSearchResultKeys.ICON_SETTINGS, self.DEFAULT_ICON)
open_everywhere = view.settings().get(OpenSearchResultKeys.OPEN_EVERYWHERE, False)
if view.name() != 'Find Results':
if open_everywhere == False and view.name() != 'Find Results':
return
for s in view.sel():
line = view.line(s)
line_str = view.substr(view.line(s))
line_num = util.parse_line_number(line_str)
line_num = parse_line_number(line_str)
if util.is_file_path(line_str) or line_num:
if is_file_path(line_str) or line_num:
valid_regions.append(line)
if valid_regions:
@@ -40,8 +49,8 @@ class HighlightFilePaths(sublime_plugin.EventListener):
view.erase_regions(self.HIGHLIGHT_REGION_NAME)
def on_selection_modified(self, view):
highlight_enabled = (view.settings().get(self.HIGHLIGHT_ENABLED_KEY)
or view.settings().get(self.ICON_SETTINGS_KEY))
highlight_enabled = (view.settings().get(OpenSearchResultKeys.HIGHLIGHT_ENABLED)
or view.settings().get(OpenSearchResultKeys.ICON_SETTINGS))
if view.settings().get('is_widget') \
or not view.settings().get('command_mode') \
@@ -108,19 +117,20 @@ class OpenSearchResultCommand(sublime_plugin.TextCommand):
break
line = self.view.substr(prev).strip()
if util.is_file_path(line):
if is_file_path(line):
return self.open_file_from_line(line, line_num)
def run(self, edit):
open_everywhere = self.view.settings().get(OpenSearchResultKeys.OPEN_EVERYWHERE, False)
for cursor in self.view.sel():
cur_line = self.view.line(cursor)
line_str = self.view.substr(cur_line).strip()
line_num = util.parse_line_number(line_str)
line_num = parse_line_number(line_str)
if self.view.name() != 'Find Results':
if open_everywhere == False and self.view.name() != 'Find Results':
return
if util.is_file_path(line_str):
if is_file_path(line_str):
self.open_file_path(line_str)
elif line_num:
self.open_file_at_line_num(cur_line, line_num)

View File

@@ -1 +1 @@
{"url": "https://github.com/abrookins/OpenSearchResult", "version": "2012.09.11.15.18.59", "description": "a Sublime Text 2 plugin that opens files listed in the Find in File output"}
{"url": "https://github.com/abrookins/OpenSearchResult", "version": "2013.07.25.03.39.55", "description": "a Sublime Text 2 plugin that opens files listed in the Find in File output"}

View File

@@ -27,7 +27,7 @@ def is_file_path(line_str):
>>> is_file_path('/Users/me/code/OpenSearchResult/open_search_result.py:')
True
>>> is_file_path('C:\Users\me\\test.txt:')
>>> is_file_path('C:\\Users\\me\\test.txt:')
True
>>> is_file_path('5: def parse_line_number(line_str):')
False

View File

@@ -5,7 +5,7 @@
},
{
"caption": "Package Control: Add Channel",
"command": "add_repository_channel"
"command": "add_channel"
},
{
"caption": "Package Control: Create Binary Package File",
@@ -27,6 +27,10 @@
"caption": "Package Control: Enable Package",
"command": "enable_package"
},
{
"caption": "Package Control: Grab CA Certs",
"command": "grab_certs"
},
{
"caption": "Package Control: Install Package",
"command": "install_package"

View File

@@ -0,0 +1,43 @@
----BEGIN CERTIFICATE-----
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----

View File

@@ -0,0 +1,4 @@
[
"221e907bdfff70d71cea42361ae209d5",
"7d0986b90061d60c8c02aa3b1cf23850"
]

View File

@@ -2,18 +2,19 @@
// A list of URLs that each contain a JSON file with a list of repositories.
// The repositories from these channels are placed in order after the
// repositories from the "repositories" setting
"repository_channels": [
"https://sublime.wbond.net/repositories.json"
"channels": [
"https://sublime.wbond.net/channel.json"
],
// A list of URLs that contain a packages JSON file. These repositories
// are placed in order before repositories from the "repository_channels"
// are placed in order before repositories from the "channels"
// setting
"repositories": [],
// A list of CA certs needed for domains. The default channel provides a
// list of domains and an identifier (the md5 hash) for the CA cert(s)
// necessary for each.
// necessary for each. Not used on Windows since the system CA cert list
// is automatically used via WinINet.
//
// If a custom cert is required for a proxy or for an alternate channel
// or repository domain name, it should be added in one of the two forms:
@@ -24,21 +25,29 @@
// In both cases the literal "*" means the cert will be checked to ensure
// it is present for accessing any URL. This is necessary for proxy
// connections, but also useful if you want to provide you own
// ca-bundle.crt file.
// Pckage Control.ca-bundle file.
//
// The "my_identifier" and "my_identifier_2" can be any unique string
// that Package Control can use as a filename, and ensures that it has
// merged the cert file with the ca-bundle.crt file in the certs/ directory
// since that is what is passed to the downloaders.
"certs": {
"api.bitbucket.org": ["d867a7b2aecc46f9c31afc4f2f50de05", ""],
"api.github.com": ["1c5282418e2cb4989cd6beddcdbab0b5", ""],
"bitbucket.org": ["897abe0b41fd2f64e9e2e351cbc36d76", ""],
"nodeload.github.com": ["1c5282418e2cb4989cd6beddcdbab0b5", ""],
"raw.github.com": ["1c5282418e2cb4989cd6beddcdbab0b5", ""],
"sublime.wbond.net": ["7f4f8622b4fd001c7f648e09aae7edaa", ""]
"api.bitbucket.org": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"api.github.com": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"bitbucket.org": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"codeload.github.com": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"downloads.sourceforge.net": ["221e907bdfff70d71cea42361ae209d5", "https://sublime.wbond.net/certs/221e907bdfff70d71cea42361ae209d5"],
"github.com": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"nodeload.github.com": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"raw.github.com": ["7d0986b90061d60c8c02aa3b1cf23850", "https://sublime.wbond.net/certs/7d0986b90061d60c8c02aa3b1cf23850"],
"sublime.wbond.net": ["221e907bdfff70d71cea42361ae209d5", "https://sublime.wbond.net/certs/221e907bdfff70d71cea42361ae209d5"]
},
// Install pre-release versions of packages. If this is false, versions
// under 1.0.0 will still be installed. Only packages using the SemVer
// -prerelease suffixes will be ignored.
"install_prereleases": false,
// If debugging information for HTTP/HTTPS connections should be printed
// to the Sublime Text console
"debug": false,
@@ -53,7 +62,7 @@
// the channel for aggregated statistics
"submit_usage": true,
// The URL to post install, upgrade and removal notices to
// The URL to post install, upgrade and removal notices to
"submit_url": "https://sublime.wbond.net/submit",
// If packages should be automatically upgraded when ST2 starts
@@ -69,25 +78,36 @@
// Packages to not auto upgrade
"auto_upgrade_ignore": [],
// Timeout for downloading channels, repositories and packages
// Timeout for downloading channels, repositories and packages. Doesn't
// have an effect on Windows due to a bug in WinINet.
"timeout": 30,
// The number of seconds to cache repository and package info for
"cache_length": 300,
// An HTTP proxy server to use for requests
// An HTTP proxy server to use for requests. Not used on Windows since the
// system proxy configuration is utilized via WinINet.
"http_proxy": "",
// An HTTPS proxy server to use for requests - this will inherit from
// http_proxy if it is set to "" or null and http_proxy has a value. You
// can set this to false to prevent inheriting from http_proxy.
// can set this to false to prevent inheriting from http_proxy. Not used on
// Windows since the system proxy configuration is utilized via WinINet.
"https_proxy": "",
// Username and password for both http_proxy and https_proxy
// Username and password for both http_proxy and https_proxy. May be used
// with WinINet to set credentials for system-level proxy config.
"proxy_username": "",
"proxy_password": "",
// User agent for HTTP requests
"user_agent": "Sublime Package Control",
// If HTTP responses should be cached to disk
"http_cache": true,
// Number of seconds to cache HTTP responses for, defaults to one week
"http_cache_length": 604800,
// User agent for HTTP requests. If "%s" is present, will be replaced
// with the current version.
"user_agent": "Sublime Package Control v%s",
// Setting this to true will cause Package Control to ignore all git
// and hg repositories - this may help if trying to list packages to install
@@ -97,12 +117,20 @@
// Custom paths to VCS binaries for when they can't be automatically
// found on the system and a package includes a VCS metadata directory
"git_binary": "",
"git_update_command": ["pull", "origin", "master", "--ff", "--commit"],
// This should NOT contain the name of the remote or branch - that will
// be automatically determined.
"git_update_command": ["pull", "--ff", "--commit"],
"hg_binary": "",
// Be sure to keep the remote name as the last argument
"hg_update_command": ["pull", "--update", "default"],
// For HG repositories, be sure to use "default" as the remote URL.
// This is the default behavior when cloning an HG repo.
"hg_update_command": ["pull", "--update"],
// Full path to the openssl binary, if not found on your machine. This is
// only used when running the Grab CA Certs command.
"openssl_binary": "",
// Directories to ignore when creating a package
"dirs_to_ignore": [
@@ -133,6 +161,6 @@
"__init__.py"
],
// When a package is created, copy it to this folder - defaults to Desktop
// When a package is created, copy it to this folder - defaults to Desktop
"package_destination": ""
}
}

View File

@@ -1,113 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0a:5f:11:4d:03:5b:17:91:17:d2:ef:d4:03:8c:3f:3b
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Validity
Not Before: Apr 2 12:00:00 2008 GMT
Not After : Apr 3 00:00:00 2022 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance CA-3
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:bf:61:0a:29:10:1f:5e:fe:34:37:51:08:f8:1e:
fb:22:ed:61:be:0b:0d:70:4c:50:63:26:75:15:b9:
41:88:97:b6:f0:a0:15:bb:08:60:e0:42:e8:05:29:
10:87:36:8a:28:65:a8:ef:31:07:74:6d:36:97:2f:
28:46:66:04:c7:2a:79:26:7a:99:d5:8e:c3:6d:4f:
a0:5e:ad:bc:3d:91:c2:59:7b:5e:36:6c:c0:53:cf:
00:08:32:3e:10:64:58:10:13:69:c7:0c:ee:9c:42:
51:00:f9:05:44:ee:24:ce:7a:1f:ed:8c:11:bd:12:
a8:f3:15:f4:1c:7a:31:69:01:1b:a7:e6:5d:c0:9a:
6c:7e:09:9e:e7:52:44:4a:10:3a:23:e4:9b:b6:03:
af:a8:9c:b4:5b:9f:d4:4b:ad:92:8c:ce:b5:11:2a:
aa:37:18:8d:b4:c2:b8:d8:5c:06:8c:f8:ff:23:bd:
35:5e:d4:7c:3e:7e:83:0e:91:96:05:98:c3:b2:1f:
e3:c8:65:eb:a9:7b:5d:a0:2c:cc:fc:3c:d9:6d:ed:
cc:fa:4b:43:8c:c9:d4:b8:a5:61:1c:b2:40:b6:28:
12:df:b9:f8:5f:fe:d3:b2:c9:ef:3d:b4:1e:4b:7c:
1c:4c:99:36:9e:3d:eb:ec:a7:68:5e:1d:df:67:6e:
5e:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.1.3.0.2
CPS: http://www.digicert.com/ssl-cps-repository.htm
User Notice:
Explicit Text:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl
Full Name:
URI:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl
X509v3 Authority Key Identifier:
keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Subject Key Identifier:
50:EA:73:89:DB:29:FB:10:8F:9E:E5:01:20:D4:DE:79:99:48:83:F7
Signature Algorithm: sha1WithRSAEncryption
1e:e2:a5:48:9e:6c:db:53:38:0f:ef:a6:1a:2a:ac:e2:03:43:
ed:9a:bc:3e:8e:75:1b:f0:fd:2e:22:59:ac:13:c0:61:e2:e7:
fa:e9:99:cd:87:09:75:54:28:bf:46:60:dc:be:51:2c:92:f3:
1b:91:7c:31:08:70:e2:37:b9:c1:5b:a8:bd:a3:0b:00:fb:1a:
15:fd:03:ad:58:6a:c5:c7:24:99:48:47:46:31:1e:92:ef:b4:
5f:4e:34:c7:90:bf:31:c1:f8:b1:84:86:d0:9c:01:aa:df:8a:
56:06:ce:3a:e9:0e:ae:97:74:5d:d7:71:9a:42:74:5f:de:8d:
43:7c:de:e9:55:ed:69:00:cb:05:e0:7a:61:61:33:d1:19:4d:
f9:08:ee:a0:39:c5:25:35:b7:2b:c4:0f:b2:dd:f1:a5:b7:0e:
24:c4:26:28:8d:79:77:f5:2f:f0:57:ba:7c:07:d4:e1:fc:cd:
5a:30:57:7e:86:10:47:dd:31:1f:d7:fc:a2:c2:bf:30:7c:5d:
24:aa:e8:f9:ae:5f:6a:74:c2:ce:6b:b3:46:d8:21:be:29:d4:
8e:5e:15:d6:42:4a:e7:32:6f:a4:b1:6b:51:83:58:be:3f:6d:
c7:fb:da:03:21:cb:6a:16:19:4e:0a:f0:ad:84:ca:5d:94:b3:
5a:76:f7:61
-----BEGIN CERTIFICATE-----
MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB
hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln
aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME
GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB
INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a
vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j
CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X
dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE
JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY
Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E=
-----END CERTIFICATE-----

View File

@@ -1,165 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 145105 (0x236d1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Validity
Not Before: Feb 19 22:45:05 2010 GMT
Not After : Feb 18 22:45:05 2020 GMT
Subject: C=US, O=GeoTrust, Inc., CN=RapidSSL CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c7:71:f8:56:c7:1e:d9:cc:b5:ad:f6:b4:97:a3:
fb:a1:e6:0b:50:5f:50:aa:3a:da:0f:fc:3d:29:24:
43:c6:10:29:c1:fc:55:40:72:ee:bd:ea:df:9f:b6:
41:f4:48:4b:c8:6e:fe:4f:57:12:8b:5b:fa:92:dd:
5e:e8:ad:f3:f0:1b:b1:7b:4d:fb:cf:fd:d1:e5:f8:
e3:dc:e7:f5:73:7f:df:01:49:cf:8c:56:c1:bd:37:
e3:5b:be:b5:4f:8b:8b:f0:da:4f:c7:e3:dd:55:47:
69:df:f2:5b:7b:07:4f:3d:e5:ac:21:c1:c8:1d:7a:
e8:e7:f6:0f:a1:aa:f5:6f:de:a8:65:4f:10:89:9c:
03:f3:89:7a:a5:5e:01:72:33:ed:a9:e9:5a:1e:79:
f3:87:c8:df:c8:c5:fc:37:c8:9a:9a:d7:b8:76:cc:
b0:3e:e7:fd:e6:54:ea:df:5f:52:41:78:59:57:ad:
f1:12:d6:7f:bc:d5:9f:70:d3:05:6c:fa:a3:7d:67:
58:dd:26:62:1d:31:92:0c:79:79:1c:8e:cf:ca:7b:
c1:66:af:a8:74:48:fb:8e:82:c2:9e:2c:99:5c:7b:
2d:5d:9b:bc:5b:57:9e:7c:3a:7a:13:ad:f2:a3:18:
5b:2b:59:0f:cd:5c:3a:eb:68:33:c6:28:1d:82:d1:
50:8b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
6B:69:3D:6A:18:42:4A:DD:8F:02:65:39:FD:35:24:86:78:91:16:30
X509v3 Authority Key Identifier:
keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 CRL Distribution Points:
URI:http://crl.geotrust.com/crls/gtglobal.crl
Authority Information Access:
OCSP - URI:http://ocsp.geotrust.com
Signature Algorithm: sha1WithRSAEncryption
ab:bc:bc:0a:5d:18:94:e3:c1:b1:c3:a8:4c:55:d6:be:b4:98:
f1:ee:3c:1c:cd:cf:f3:24:24:5c:96:03:27:58:fc:36:ae:a2:
2f:8f:f1:fe:da:2b:02:c3:33:bd:c8:dd:48:22:2b:60:0f:a5:
03:10:fd:77:f8:d0:ed:96:67:4f:fd:ea:47:20:70:54:dc:a9:
0c:55:7e:e1:96:25:8a:d9:b5:da:57:4a:be:8d:8e:49:43:63:
a5:6c:4e:27:87:25:eb:5b:6d:fe:a2:7f:38:28:e0:36:ab:ad:
39:a5:a5:62:c4:b7:5c:58:2c:aa:5d:01:60:a6:62:67:a3:c0:
c7:62:23:f4:e7:6c:46:ee:b5:d3:80:6a:22:13:d2:2d:3f:74:
4f:ea:af:8c:5f:b4:38:9c:db:ae:ce:af:84:1e:a6:f6:34:51:
59:79:d3:e3:75:dc:bc:d7:f3:73:df:92:ec:d2:20:59:6f:9c:
fb:95:f8:92:76:18:0a:7c:0f:2c:a6:ca:de:8a:62:7b:d8:f3:
ce:5f:68:bd:8f:3e:c1:74:bb:15:72:3a:16:83:a9:0b:e6:4d:
99:9c:d8:57:ec:a8:01:51:c7:6f:57:34:5e:ab:4a:2c:42:f6:
4f:1c:89:78:de:26:4e:f5:6f:93:4c:15:6b:27:56:4d:00:54:
6c:7a:b7:b7
-----BEGIN CERTIFICATE-----
MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMTAwMjE5MjI0NTA1WhcNMjAwMjE4MjI0NTA1WjA8MQswCQYDVQQG
EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xFDASBgNVBAMTC1JhcGlkU1NM
IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3H4Vsce2cy1rfa0
l6P7oeYLUF9QqjraD/w9KSRDxhApwfxVQHLuverfn7ZB9EhLyG7+T1cSi1v6kt1e
6K3z8Buxe037z/3R5fjj3Of1c3/fAUnPjFbBvTfjW761T4uL8NpPx+PdVUdp3/Jb
ewdPPeWsIcHIHXro5/YPoar1b96oZU8QiZwD84l6pV4BcjPtqelaHnnzh8jfyMX8
N8iamte4dsywPuf95lTq319SQXhZV63xEtZ/vNWfcNMFbPqjfWdY3SZiHTGSDHl5
HI7PynvBZq+odEj7joLCniyZXHstXZu8W1eefDp6E63yoxhbK1kPzVw662gzxigd
gtFQiwIDAQABo4HZMIHWMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUa2k9ahhC
St2PAmU5/TUkhniRFjAwHwYDVR0jBBgwFoAUwHqYaI2J+6sFZAwRfap9ZbjKzE4w
EgYDVR0TAQH/BAgwBgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3Js
Lmdlb3RydXN0LmNvbS9jcmxzL2d0Z2xvYmFsLmNybDA0BggrBgEFBQcBAQQoMCYw
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdlb3RydXN0LmNvbTANBgkqhkiG9w0B
AQUFAAOCAQEAq7y8Cl0YlOPBscOoTFXWvrSY8e48HM3P8yQkXJYDJ1j8Nq6iL4/x
/torAsMzvcjdSCIrYA+lAxD9d/jQ7ZZnT/3qRyBwVNypDFV+4ZYlitm12ldKvo2O
SUNjpWxOJ4cl61tt/qJ/OCjgNqutOaWlYsS3XFgsql0BYKZiZ6PAx2Ij9OdsRu61
04BqIhPSLT90T+qvjF+0OJzbrs6vhB6m9jRRWXnT43XcvNfzc9+S7NIgWW+c+5X4
knYYCnwPLKbK3opie9jzzl9ovY8+wXS7FXI6FoOpC+ZNmZzYV+yoAVHHb1c0XqtK
LEL2TxyJeN4mTvVvk0wVaydWTQBUbHq3tw==
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 144470 (0x23456)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Validity
Not Before: May 21 04:00:00 2002 GMT
Not After : May 21 04:00:00 2022 GMT
Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:da:cc:18:63:30:fd:f4:17:23:1a:56:7e:5b:df:
3c:6c:38:e4:71:b7:78:91:d4:bc:a1:d8:4c:f8:a8:
43:b6:03:e9:4d:21:07:08:88:da:58:2f:66:39:29:
bd:05:78:8b:9d:38:e8:05:b7:6a:7e:71:a4:e6:c4:
60:a6:b0:ef:80:e4:89:28:0f:9e:25:d6:ed:83:f3:
ad:a6:91:c7:98:c9:42:18:35:14:9d:ad:98:46:92:
2e:4f:ca:f1:87:43:c1:16:95:57:2d:50:ef:89:2d:
80:7a:57:ad:f2:ee:5f:6b:d2:00:8d:b9:14:f8:14:
15:35:d9:c0:46:a3:7b:72:c8:91:bf:c9:55:2b:cd:
d0:97:3e:9c:26:64:cc:df:ce:83:19:71:ca:4e:e6:
d4:d5:7b:a9:19:cd:55:de:c8:ec:d2:5e:38:53:e5:
5c:4f:8c:2d:fe:50:23:36:fc:66:e6:cb:8e:a4:39:
19:00:b7:95:02:39:91:0b:0e:fe:38:2e:d1:1d:05:
9a:f6:4d:3e:6f:0f:07:1d:af:2c:1e:8f:60:39:e2:
fa:36:53:13:39:d4:5e:26:2b:db:3d:a8:14:bd:32:
eb:18:03:28:52:04:71:e5:ab:33:3d:e1:38:bb:07:
36:84:62:9c:79:ea:16:30:f4:5f:c0:2b:e8:71:6b:
e4:f9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
X509v3 Authority Key Identifier:
keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
Signature Algorithm: sha1WithRSAEncryption
35:e3:29:6a:e5:2f:5d:54:8e:29:50:94:9f:99:1a:14:e4:8f:
78:2a:62:94:a2:27:67:9e:d0:cf:1a:5e:47:e9:c1:b2:a4:cf:
dd:41:1a:05:4e:9b:4b:ee:4a:6f:55:52:b3:24:a1:37:0a:eb:
64:76:2a:2e:2c:f3:fd:3b:75:90:bf:fa:71:d8:c7:3d:37:d2:
b5:05:95:62:b9:a6:de:89:3d:36:7b:38:77:48:97:ac:a6:20:
8f:2e:a6:c9:0c:c2:b2:99:45:00:c7:ce:11:51:22:22:e0:a5:
ea:b6:15:48:09:64:ea:5e:4f:74:f7:05:3e:c7:8a:52:0c:db:
15:b4:bd:6d:9b:e5:c6:b1:54:68:a9:e3:69:90:b6:9a:a5:0f:
b8:b9:3f:20:7d:ae:4a:b5:b8:9c:e4:1d:b6:ab:e6:94:a5:c1:
c7:83:ad:db:f5:27:87:0e:04:6c:d5:ff:dd:a0:5d:ed:87:52:
b7:2b:15:02:ae:39:a6:6a:74:e9:da:c4:e7:bc:4d:34:1e:a9:
5c:4d:33:5f:92:09:2f:88:66:5d:77:97:c7:1d:76:13:a9:d5:
e5:f1:16:09:11:35:d5:ac:db:24:71:70:2c:98:56:0b:d9:17:
b4:d1:e3:51:2b:5e:75:e8:d5:d0:dc:4f:34:ed:c2:05:66:80:
a1:cb:e6:33
-----BEGIN CERTIFICATE-----
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
-----END CERTIFICATE-----

View File

@@ -1,285 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:37:b9:28:34:7c:60:a6:ae:c5:ad:b1:21:7f:38:60
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Validity
Not Before: Nov 9 12:00:00 2007 GMT
Not After : Nov 10 00:00:00 2021 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV CA-1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:f3:96:62:d8:75:6e:19:ff:3f:34:7c:49:4f:31:
7e:0d:04:4e:99:81:e2:b3:85:55:91:30:b1:c0:af:
70:bb:2c:a8:e7:18:aa:3f:78:f7:90:68:52:86:01:
88:97:e2:3b:06:65:90:aa:bd:65:76:c2:ec:be:10:
5b:37:78:83:60:75:45:c6:bd:74:aa:b6:9f:a4:3a:
01:50:17:c4:39:69:b9:f1:4f:ef:82:c1:ca:f3:4a:
db:cc:9e:50:4f:4d:40:a3:3a:90:e7:86:66:bc:f0:
3e:76:28:4c:d1:75:80:9e:6a:35:14:35:03:9e:db:
0c:8c:c2:28:ad:50:b2:ce:f6:91:a3:c3:a5:0a:58:
49:f6:75:44:6c:ba:f9:ce:e9:ab:3a:02:e0:4d:f3:
ac:e2:7a:e0:60:22:05:3c:82:d3:52:e2:f3:9c:47:
f8:3b:d8:b2:4b:93:56:4a:bf:70:ab:3e:e9:68:c8:
1d:8f:58:1d:2a:4d:5e:27:3d:ad:0a:59:2f:5a:11:
20:40:d9:68:04:68:2d:f4:c0:84:0b:0a:1b:78:df:
ed:1a:58:dc:fb:41:5a:6d:6b:f2:ed:1c:ee:5c:32:
b6:5c:ec:d7:a6:03:32:a6:e8:de:b7:28:27:59:88:
80:ff:7b:ad:89:58:d5:1e:14:a4:f2:b0:70:d4:a0:
3e:a7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.2.1
CPS: http://www.digicert.com/ssl-cps-repository.htm
User Notice:
Explicit Text:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
CA Issuers - URI:http://www.digicert.com/CACerts/DigiCertHighAssuranceEVRootCA.crt
X509v3 CRL Distribution Points:
URI:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl
URI:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl
X509v3 Subject Key Identifier:
4C:58:CB:25:F0:41:4F:52:F4:28:C8:81:43:9B:A6:A8:A0:E6:92:E5
X509v3 Authority Key Identifier:
keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
Signature Algorithm: sha1WithRSAEncryption
4c:7a:17:87:28:5d:17:bc:b2:32:73:bf:cd:2e:f5:58:31:1d:
f0:b1:71:54:9c:d6:9b:67:93:db:2f:03:3e:16:6f:1e:03:c9:
53:84:a3:56:60:1e:78:94:1b:a2:a8:6f:a3:a4:8b:52:91:d7:
dd:5c:95:bb:ef:b5:16:49:e9:a5:42:4f:34:f2:47:ff:ae:81:
7f:13:54:b7:20:c4:70:15:cb:81:0a:81:cb:74:57:dc:9c:df:
24:a4:29:0c:18:f0:1c:e4:ae:07:33:ec:f1:49:3e:55:cf:6e:
4f:0d:54:7b:d3:c9:e8:15:48:d4:c5:bb:dc:35:1c:77:45:07:
48:45:85:bd:d7:7e:53:b8:c0:16:d9:95:cd:8b:8d:7d:c9:60:
4f:d1:a2:9b:e3:d0:30:d6:b4:73:36:e6:d2:f9:03:b2:e3:a4:
f5:e5:b8:3e:04:49:00:ba:2e:a6:4a:72:83:72:9d:f7:0b:8c:
a9:89:e7:b3:d7:64:1f:d6:e3:60:cb:03:c4:dc:88:e9:9d:25:
01:00:71:cb:03:b4:29:60:25:8f:f9:46:d1:7b:71:ae:cd:53:
12:5b:84:8e:c2:0f:c7:ed:93:19:d9:c9:fa:8f:58:34:76:32:
2f:ae:e1:50:14:61:d4:a8:58:a3:c8:30:13:23:ef:c6:25:8c:
36:8f:1c:80
-----BEGIN CERTIFICATE-----
MIIG5jCCBc6gAwIBAgIQAze5KDR8YKauxa2xIX84YDANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA3MTEwOTEyMDAwMFoXDTIxMTExMDAwMDAwMFowaTEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTEoMCYGA1UEAxMfRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPOWYth1bhn/
PzR8SU8xfg0ETpmB4rOFVZEwscCvcLssqOcYqj9495BoUoYBiJfiOwZlkKq9ZXbC
7L4QWzd4g2B1Rca9dKq2n6Q6AVAXxDlpufFP74LByvNK28yeUE9NQKM6kOeGZrzw
PnYoTNF1gJ5qNRQ1A57bDIzCKK1Qss72kaPDpQpYSfZ1RGy6+c7pqzoC4E3zrOJ6
4GAiBTyC01Li85xH+DvYskuTVkq/cKs+6WjIHY9YHSpNXic9rQpZL1oRIEDZaARo
LfTAhAsKG3jf7RpY3PtBWm1r8u0c7lwytlzs16YDMqbo3rcoJ1mIgP97rYlY1R4U
pPKwcNSgPqcCAwEAAaOCA4UwggOBMA4GA1UdDwEB/wQEAwIBhjA7BgNVHSUENDAy
BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUH
AwgwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwCATCCAaQwOgYIKwYBBQUH
AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
AGcAaQBDAGUAcgB0ACAARQBWACAAQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wEgYDVR0TAQH/BAgwBgEB/wIBADCB
gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NBQ2Vy
dHMvRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcw
gYQwQKA+oDyGOmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hB
c3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwHQYDVR0OBBYE
FExYyyXwQU9S9CjIgUObpqig5pLlMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoI
Au9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQBMeheHKF0XvLIyc7/NLvVYMR3wsXFU
nNabZ5PbLwM+Fm8eA8lThKNWYB54lBuiqG+jpItSkdfdXJW777UWSemlQk808kf/
roF/E1S3IMRwFcuBCoHLdFfcnN8kpCkMGPAc5K4HM+zxST5Vz25PDVR708noFUjU
xbvcNRx3RQdIRYW9135TuMAW2ZXNi419yWBP0aKb49Aw1rRzNubS+QOy46T15bg+
BEkAui6mSnKDcp33C4ypieez12Qf1uNgywPE3IjpnSUBAHHLA7QpYCWP+UbRe3Gu
zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1116160165 (0x428740a5)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Validity
Not Before: Oct 1 05:00:00 2006 GMT
Not After : Jul 26 18:15:15 2014 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c6:cc:e5:73:e6:fb:d4:bb:e5:2d:2d:32:a6:df:
e5:81:3f:c9:cd:25:49:b6:71:2a:c3:d5:94:34:67:
a2:0a:1c:b0:5f:69:a6:40:b1:c4:b7:b2:8f:d0:98:
a4:a9:41:59:3a:d3:dc:94:d6:3c:db:74:38:a4:4a:
cc:4d:25:82:f7:4a:a5:53:12:38:ee:f3:49:6d:71:
91:7e:63:b6:ab:a6:5f:c3:a4:84:f8:4f:62:51:be:
f8:c5:ec:db:38:92:e3:06:e5:08:91:0c:c4:28:41:
55:fb:cb:5a:89:15:7e:71:e8:35:bf:4d:72:09:3d:
be:3a:38:50:5b:77:31:1b:8d:b3:c7:24:45:9a:a7:
ac:6d:00:14:5a:04:b7:ba:13:eb:51:0a:98:41:41:
22:4e:65:61:87:81:41:50:a6:79:5c:89:de:19:4a:
57:d5:2e:e6:5d:1c:53:2c:7e:98:cd:1a:06:16:a4:
68:73:d0:34:04:13:5c:a1:71:d3:5a:7c:55:db:5e:
64:e1:37:87:30:56:04:e5:11:b4:29:80:12:f1:79:
39:88:a2:02:11:7c:27:66:b7:88:b7:78:f2:ca:0a:
a8:38:ab:0a:64:c2:bf:66:5d:95:84:c1:a1:25:1e:
87:5d:1a:50:0b:20:12:cc:41:bb:6e:0b:51:38:b8:
4b:cb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
Authority Information Access:
OCSP - URI:http://ocsp.entrust.net
X509v3 CRL Distribution Points:
URI:http://crl.entrust.net/server1.crl
X509v3 Subject Key Identifier:
B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Key Usage:
Certificate Sign, CRL Sign
X509v3 Authority Key Identifier:
keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
1.2.840.113533.7.65.0:
0
..V7.1....
Signature Algorithm: sha1WithRSAEncryption
48:0e:2b:6f:20:62:4c:28:93:a3:24:3d:58:ab:21:cf:80:f8:
9a:97:90:6a:22:ed:5a:7c:47:36:99:e7:79:84:75:ab:24:8f:
92:0a:d5:61:04:ae:c3:6a:5c:b2:cc:d9:e4:44:87:6f:db:8f:
38:62:f7:44:36:9d:ba:bc:6e:07:c4:d4:8d:e8:1f:d1:0b:60:
a3:b5:9c:ce:63:be:ed:67:dc:f8:ba:de:6e:c9:25:cb:5b:b5:
9d:76:70:0b:df:42:72:f8:4f:41:11:64:a5:d2:ea:fc:d5:af:
11:f4:15:38:67:9c:20:a8:4b:77:5a:91:32:42:32:e7:85:b3:
df:36
-----BEGIN CERTIFICATE-----
MIIEQjCCA6ugAwIBAgIEQodApTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEw
MDEwNTAwMDBaFw0xNDA3MjYxODE1MTVaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
BQADgYEASA4rbyBiTCiToyQ9WKshz4D4mpeQaiLtWnxHNpnneYR1qySPkgrVYQSu
w2pcsszZ5ESHb9uPOGL3RDadurxuB8TUjegf0Qtgo7WczmO+7Wfc+Lrebskly1u1
nXZwC99CcvhPQRFkpdLq/NWvEfQVOGecIKhLd1qRMkIy54Wz3zY=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 927650371 (0x374ad243)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Validity
Not Before: May 25 16:09:40 1999 GMT
Not After : May 25 16:39:40 2019 GMT
Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff:
af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1:
0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81:
26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71:
d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24:
da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29:
92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8:
ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81:
b1:16:19:61:b9:54:b6:e6:43
Exponent: 3 (0x3)
X509v3 extensions:
Netscape Cert Type:
SSL CA, S/MIME CA, Object Signing CA
X509v3 CRL Distribution Points:
DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1
URI:http://www.entrust.net/CRL/net1.crl
X509v3 Private Key Usage Period:
Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT
X509v3 Key Usage:
Certificate Sign, CRL Sign
X509v3 Authority Key Identifier:
keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
X509v3 Subject Key Identifier:
F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
X509v3 Basic Constraints:
CA:TRUE
1.2.840.113533.7.65.0:
0
..V4.0....
Signature Algorithm: sha1WithRSAEncryption
90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb:
47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d:
f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31:
c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb:
a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58:
0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54:
73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06:
f9:b2
-----BEGIN CERTIFICATE-----
MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
-----END CERTIFICATE-----

View File

@@ -1,563 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 145105 (0x236d1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Validity
Not Before: Feb 19 22:45:05 2010 GMT
Not After : Feb 18 22:45:05 2020 GMT
Subject: C=US, O=GeoTrust, Inc., CN=RapidSSL CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c7:71:f8:56:c7:1e:d9:cc:b5:ad:f6:b4:97:a3:
fb:a1:e6:0b:50:5f:50:aa:3a:da:0f:fc:3d:29:24:
43:c6:10:29:c1:fc:55:40:72:ee:bd:ea:df:9f:b6:
41:f4:48:4b:c8:6e:fe:4f:57:12:8b:5b:fa:92:dd:
5e:e8:ad:f3:f0:1b:b1:7b:4d:fb:cf:fd:d1:e5:f8:
e3:dc:e7:f5:73:7f:df:01:49:cf:8c:56:c1:bd:37:
e3:5b:be:b5:4f:8b:8b:f0:da:4f:c7:e3:dd:55:47:
69:df:f2:5b:7b:07:4f:3d:e5:ac:21:c1:c8:1d:7a:
e8:e7:f6:0f:a1:aa:f5:6f:de:a8:65:4f:10:89:9c:
03:f3:89:7a:a5:5e:01:72:33:ed:a9:e9:5a:1e:79:
f3:87:c8:df:c8:c5:fc:37:c8:9a:9a:d7:b8:76:cc:
b0:3e:e7:fd:e6:54:ea:df:5f:52:41:78:59:57:ad:
f1:12:d6:7f:bc:d5:9f:70:d3:05:6c:fa:a3:7d:67:
58:dd:26:62:1d:31:92:0c:79:79:1c:8e:cf:ca:7b:
c1:66:af:a8:74:48:fb:8e:82:c2:9e:2c:99:5c:7b:
2d:5d:9b:bc:5b:57:9e:7c:3a:7a:13:ad:f2:a3:18:
5b:2b:59:0f:cd:5c:3a:eb:68:33:c6:28:1d:82:d1:
50:8b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
6B:69:3D:6A:18:42:4A:DD:8F:02:65:39:FD:35:24:86:78:91:16:30
X509v3 Authority Key Identifier:
keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 CRL Distribution Points:
URI:http://crl.geotrust.com/crls/gtglobal.crl
Authority Information Access:
OCSP - URI:http://ocsp.geotrust.com
Signature Algorithm: sha1WithRSAEncryption
ab:bc:bc:0a:5d:18:94:e3:c1:b1:c3:a8:4c:55:d6:be:b4:98:
f1:ee:3c:1c:cd:cf:f3:24:24:5c:96:03:27:58:fc:36:ae:a2:
2f:8f:f1:fe:da:2b:02:c3:33:bd:c8:dd:48:22:2b:60:0f:a5:
03:10:fd:77:f8:d0:ed:96:67:4f:fd:ea:47:20:70:54:dc:a9:
0c:55:7e:e1:96:25:8a:d9:b5:da:57:4a:be:8d:8e:49:43:63:
a5:6c:4e:27:87:25:eb:5b:6d:fe:a2:7f:38:28:e0:36:ab:ad:
39:a5:a5:62:c4:b7:5c:58:2c:aa:5d:01:60:a6:62:67:a3:c0:
c7:62:23:f4:e7:6c:46:ee:b5:d3:80:6a:22:13:d2:2d:3f:74:
4f:ea:af:8c:5f:b4:38:9c:db:ae:ce:af:84:1e:a6:f6:34:51:
59:79:d3:e3:75:dc:bc:d7:f3:73:df:92:ec:d2:20:59:6f:9c:
fb:95:f8:92:76:18:0a:7c:0f:2c:a6:ca:de:8a:62:7b:d8:f3:
ce:5f:68:bd:8f:3e:c1:74:bb:15:72:3a:16:83:a9:0b:e6:4d:
99:9c:d8:57:ec:a8:01:51:c7:6f:57:34:5e:ab:4a:2c:42:f6:
4f:1c:89:78:de:26:4e:f5:6f:93:4c:15:6b:27:56:4d:00:54:
6c:7a:b7:b7
-----BEGIN CERTIFICATE-----
MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMTAwMjE5MjI0NTA1WhcNMjAwMjE4MjI0NTA1WjA8MQswCQYDVQQG
EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xFDASBgNVBAMTC1JhcGlkU1NM
IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3H4Vsce2cy1rfa0
l6P7oeYLUF9QqjraD/w9KSRDxhApwfxVQHLuverfn7ZB9EhLyG7+T1cSi1v6kt1e
6K3z8Buxe037z/3R5fjj3Of1c3/fAUnPjFbBvTfjW761T4uL8NpPx+PdVUdp3/Jb
ewdPPeWsIcHIHXro5/YPoar1b96oZU8QiZwD84l6pV4BcjPtqelaHnnzh8jfyMX8
N8iamte4dsywPuf95lTq319SQXhZV63xEtZ/vNWfcNMFbPqjfWdY3SZiHTGSDHl5
HI7PynvBZq+odEj7joLCniyZXHstXZu8W1eefDp6E63yoxhbK1kPzVw662gzxigd
gtFQiwIDAQABo4HZMIHWMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUa2k9ahhC
St2PAmU5/TUkhniRFjAwHwYDVR0jBBgwFoAUwHqYaI2J+6sFZAwRfap9ZbjKzE4w
EgYDVR0TAQH/BAgwBgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3Js
Lmdlb3RydXN0LmNvbS9jcmxzL2d0Z2xvYmFsLmNybDA0BggrBgEFBQcBAQQoMCYw
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdlb3RydXN0LmNvbTANBgkqhkiG9w0B
AQUFAAOCAQEAq7y8Cl0YlOPBscOoTFXWvrSY8e48HM3P8yQkXJYDJ1j8Nq6iL4/x
/torAsMzvcjdSCIrYA+lAxD9d/jQ7ZZnT/3qRyBwVNypDFV+4ZYlitm12ldKvo2O
SUNjpWxOJ4cl61tt/qJ/OCjgNqutOaWlYsS3XFgsql0BYKZiZ6PAx2Ij9OdsRu61
04BqIhPSLT90T+qvjF+0OJzbrs6vhB6m9jRRWXnT43XcvNfzc9+S7NIgWW+c+5X4
knYYCnwPLKbK3opie9jzzl9ovY8+wXS7FXI6FoOpC+ZNmZzYV+yoAVHHb1c0XqtK
LEL2TxyJeN4mTvVvk0wVaydWTQBUbHq3tw==
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 144470 (0x23456)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Validity
Not Before: May 21 04:00:00 2002 GMT
Not After : May 21 04:00:00 2022 GMT
Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:da:cc:18:63:30:fd:f4:17:23:1a:56:7e:5b:df:
3c:6c:38:e4:71:b7:78:91:d4:bc:a1:d8:4c:f8:a8:
43:b6:03:e9:4d:21:07:08:88:da:58:2f:66:39:29:
bd:05:78:8b:9d:38:e8:05:b7:6a:7e:71:a4:e6:c4:
60:a6:b0:ef:80:e4:89:28:0f:9e:25:d6:ed:83:f3:
ad:a6:91:c7:98:c9:42:18:35:14:9d:ad:98:46:92:
2e:4f:ca:f1:87:43:c1:16:95:57:2d:50:ef:89:2d:
80:7a:57:ad:f2:ee:5f:6b:d2:00:8d:b9:14:f8:14:
15:35:d9:c0:46:a3:7b:72:c8:91:bf:c9:55:2b:cd:
d0:97:3e:9c:26:64:cc:df:ce:83:19:71:ca:4e:e6:
d4:d5:7b:a9:19:cd:55:de:c8:ec:d2:5e:38:53:e5:
5c:4f:8c:2d:fe:50:23:36:fc:66:e6:cb:8e:a4:39:
19:00:b7:95:02:39:91:0b:0e:fe:38:2e:d1:1d:05:
9a:f6:4d:3e:6f:0f:07:1d:af:2c:1e:8f:60:39:e2:
fa:36:53:13:39:d4:5e:26:2b:db:3d:a8:14:bd:32:
eb:18:03:28:52:04:71:e5:ab:33:3d:e1:38:bb:07:
36:84:62:9c:79:ea:16:30:f4:5f:c0:2b:e8:71:6b:
e4:f9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
X509v3 Authority Key Identifier:
keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
Signature Algorithm: sha1WithRSAEncryption
35:e3:29:6a:e5:2f:5d:54:8e:29:50:94:9f:99:1a:14:e4:8f:
78:2a:62:94:a2:27:67:9e:d0:cf:1a:5e:47:e9:c1:b2:a4:cf:
dd:41:1a:05:4e:9b:4b:ee:4a:6f:55:52:b3:24:a1:37:0a:eb:
64:76:2a:2e:2c:f3:fd:3b:75:90:bf:fa:71:d8:c7:3d:37:d2:
b5:05:95:62:b9:a6:de:89:3d:36:7b:38:77:48:97:ac:a6:20:
8f:2e:a6:c9:0c:c2:b2:99:45:00:c7:ce:11:51:22:22:e0:a5:
ea:b6:15:48:09:64:ea:5e:4f:74:f7:05:3e:c7:8a:52:0c:db:
15:b4:bd:6d:9b:e5:c6:b1:54:68:a9:e3:69:90:b6:9a:a5:0f:
b8:b9:3f:20:7d:ae:4a:b5:b8:9c:e4:1d:b6:ab:e6:94:a5:c1:
c7:83:ad:db:f5:27:87:0e:04:6c:d5:ff:dd:a0:5d:ed:87:52:
b7:2b:15:02:ae:39:a6:6a:74:e9:da:c4:e7:bc:4d:34:1e:a9:
5c:4d:33:5f:92:09:2f:88:66:5d:77:97:c7:1d:76:13:a9:d5:
e5:f1:16:09:11:35:d5:ac:db:24:71:70:2c:98:56:0b:d9:17:
b4:d1:e3:51:2b:5e:75:e8:d5:d0:dc:4f:34:ed:c2:05:66:80:
a1:cb:e6:33
-----BEGIN CERTIFICATE-----
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:37:b9:28:34:7c:60:a6:ae:c5:ad:b1:21:7f:38:60
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Validity
Not Before: Nov 9 12:00:00 2007 GMT
Not After : Nov 10 00:00:00 2021 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV CA-1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:f3:96:62:d8:75:6e:19:ff:3f:34:7c:49:4f:31:
7e:0d:04:4e:99:81:e2:b3:85:55:91:30:b1:c0:af:
70:bb:2c:a8:e7:18:aa:3f:78:f7:90:68:52:86:01:
88:97:e2:3b:06:65:90:aa:bd:65:76:c2:ec:be:10:
5b:37:78:83:60:75:45:c6:bd:74:aa:b6:9f:a4:3a:
01:50:17:c4:39:69:b9:f1:4f:ef:82:c1:ca:f3:4a:
db:cc:9e:50:4f:4d:40:a3:3a:90:e7:86:66:bc:f0:
3e:76:28:4c:d1:75:80:9e:6a:35:14:35:03:9e:db:
0c:8c:c2:28:ad:50:b2:ce:f6:91:a3:c3:a5:0a:58:
49:f6:75:44:6c:ba:f9:ce:e9:ab:3a:02:e0:4d:f3:
ac:e2:7a:e0:60:22:05:3c:82:d3:52:e2:f3:9c:47:
f8:3b:d8:b2:4b:93:56:4a:bf:70:ab:3e:e9:68:c8:
1d:8f:58:1d:2a:4d:5e:27:3d:ad:0a:59:2f:5a:11:
20:40:d9:68:04:68:2d:f4:c0:84:0b:0a:1b:78:df:
ed:1a:58:dc:fb:41:5a:6d:6b:f2:ed:1c:ee:5c:32:
b6:5c:ec:d7:a6:03:32:a6:e8:de:b7:28:27:59:88:
80:ff:7b:ad:89:58:d5:1e:14:a4:f2:b0:70:d4:a0:
3e:a7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.2.1
CPS: http://www.digicert.com/ssl-cps-repository.htm
User Notice:
Explicit Text:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
CA Issuers - URI:http://www.digicert.com/CACerts/DigiCertHighAssuranceEVRootCA.crt
X509v3 CRL Distribution Points:
URI:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl
URI:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl
X509v3 Subject Key Identifier:
4C:58:CB:25:F0:41:4F:52:F4:28:C8:81:43:9B:A6:A8:A0:E6:92:E5
X509v3 Authority Key Identifier:
keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
Signature Algorithm: sha1WithRSAEncryption
4c:7a:17:87:28:5d:17:bc:b2:32:73:bf:cd:2e:f5:58:31:1d:
f0:b1:71:54:9c:d6:9b:67:93:db:2f:03:3e:16:6f:1e:03:c9:
53:84:a3:56:60:1e:78:94:1b:a2:a8:6f:a3:a4:8b:52:91:d7:
dd:5c:95:bb:ef:b5:16:49:e9:a5:42:4f:34:f2:47:ff:ae:81:
7f:13:54:b7:20:c4:70:15:cb:81:0a:81:cb:74:57:dc:9c:df:
24:a4:29:0c:18:f0:1c:e4:ae:07:33:ec:f1:49:3e:55:cf:6e:
4f:0d:54:7b:d3:c9:e8:15:48:d4:c5:bb:dc:35:1c:77:45:07:
48:45:85:bd:d7:7e:53:b8:c0:16:d9:95:cd:8b:8d:7d:c9:60:
4f:d1:a2:9b:e3:d0:30:d6:b4:73:36:e6:d2:f9:03:b2:e3:a4:
f5:e5:b8:3e:04:49:00:ba:2e:a6:4a:72:83:72:9d:f7:0b:8c:
a9:89:e7:b3:d7:64:1f:d6:e3:60:cb:03:c4:dc:88:e9:9d:25:
01:00:71:cb:03:b4:29:60:25:8f:f9:46:d1:7b:71:ae:cd:53:
12:5b:84:8e:c2:0f:c7:ed:93:19:d9:c9:fa:8f:58:34:76:32:
2f:ae:e1:50:14:61:d4:a8:58:a3:c8:30:13:23:ef:c6:25:8c:
36:8f:1c:80
-----BEGIN CERTIFICATE-----
MIIG5jCCBc6gAwIBAgIQAze5KDR8YKauxa2xIX84YDANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA3MTEwOTEyMDAwMFoXDTIxMTExMDAwMDAwMFowaTEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTEoMCYGA1UEAxMfRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPOWYth1bhn/
PzR8SU8xfg0ETpmB4rOFVZEwscCvcLssqOcYqj9495BoUoYBiJfiOwZlkKq9ZXbC
7L4QWzd4g2B1Rca9dKq2n6Q6AVAXxDlpufFP74LByvNK28yeUE9NQKM6kOeGZrzw
PnYoTNF1gJ5qNRQ1A57bDIzCKK1Qss72kaPDpQpYSfZ1RGy6+c7pqzoC4E3zrOJ6
4GAiBTyC01Li85xH+DvYskuTVkq/cKs+6WjIHY9YHSpNXic9rQpZL1oRIEDZaARo
LfTAhAsKG3jf7RpY3PtBWm1r8u0c7lwytlzs16YDMqbo3rcoJ1mIgP97rYlY1R4U
pPKwcNSgPqcCAwEAAaOCA4UwggOBMA4GA1UdDwEB/wQEAwIBhjA7BgNVHSUENDAy
BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUH
AwgwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwCATCCAaQwOgYIKwYBBQUH
AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
AGcAaQBDAGUAcgB0ACAARQBWACAAQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wEgYDVR0TAQH/BAgwBgEB/wIBADCB
gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NBQ2Vy
dHMvRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcw
gYQwQKA+oDyGOmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hB
c3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwHQYDVR0OBBYE
FExYyyXwQU9S9CjIgUObpqig5pLlMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoI
Au9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQBMeheHKF0XvLIyc7/NLvVYMR3wsXFU
nNabZ5PbLwM+Fm8eA8lThKNWYB54lBuiqG+jpItSkdfdXJW777UWSemlQk808kf/
roF/E1S3IMRwFcuBCoHLdFfcnN8kpCkMGPAc5K4HM+zxST5Vz25PDVR708noFUjU
xbvcNRx3RQdIRYW9135TuMAW2ZXNi419yWBP0aKb49Aw1rRzNubS+QOy46T15bg+
BEkAui6mSnKDcp33C4ypieez12Qf1uNgywPE3IjpnSUBAHHLA7QpYCWP+UbRe3Gu
zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1116160165 (0x428740a5)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Validity
Not Before: Oct 1 05:00:00 2006 GMT
Not After : Jul 26 18:15:15 2014 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c6:cc:e5:73:e6:fb:d4:bb:e5:2d:2d:32:a6:df:
e5:81:3f:c9:cd:25:49:b6:71:2a:c3:d5:94:34:67:
a2:0a:1c:b0:5f:69:a6:40:b1:c4:b7:b2:8f:d0:98:
a4:a9:41:59:3a:d3:dc:94:d6:3c:db:74:38:a4:4a:
cc:4d:25:82:f7:4a:a5:53:12:38:ee:f3:49:6d:71:
91:7e:63:b6:ab:a6:5f:c3:a4:84:f8:4f:62:51:be:
f8:c5:ec:db:38:92:e3:06:e5:08:91:0c:c4:28:41:
55:fb:cb:5a:89:15:7e:71:e8:35:bf:4d:72:09:3d:
be:3a:38:50:5b:77:31:1b:8d:b3:c7:24:45:9a:a7:
ac:6d:00:14:5a:04:b7:ba:13:eb:51:0a:98:41:41:
22:4e:65:61:87:81:41:50:a6:79:5c:89:de:19:4a:
57:d5:2e:e6:5d:1c:53:2c:7e:98:cd:1a:06:16:a4:
68:73:d0:34:04:13:5c:a1:71:d3:5a:7c:55:db:5e:
64:e1:37:87:30:56:04:e5:11:b4:29:80:12:f1:79:
39:88:a2:02:11:7c:27:66:b7:88:b7:78:f2:ca:0a:
a8:38:ab:0a:64:c2:bf:66:5d:95:84:c1:a1:25:1e:
87:5d:1a:50:0b:20:12:cc:41:bb:6e:0b:51:38:b8:
4b:cb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
Authority Information Access:
OCSP - URI:http://ocsp.entrust.net
X509v3 CRL Distribution Points:
URI:http://crl.entrust.net/server1.crl
X509v3 Subject Key Identifier:
B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Key Usage:
Certificate Sign, CRL Sign
X509v3 Authority Key Identifier:
keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
1.2.840.113533.7.65.0:
0
..V7.1....
Signature Algorithm: sha1WithRSAEncryption
48:0e:2b:6f:20:62:4c:28:93:a3:24:3d:58:ab:21:cf:80:f8:
9a:97:90:6a:22:ed:5a:7c:47:36:99:e7:79:84:75:ab:24:8f:
92:0a:d5:61:04:ae:c3:6a:5c:b2:cc:d9:e4:44:87:6f:db:8f:
38:62:f7:44:36:9d:ba:bc:6e:07:c4:d4:8d:e8:1f:d1:0b:60:
a3:b5:9c:ce:63:be:ed:67:dc:f8:ba:de:6e:c9:25:cb:5b:b5:
9d:76:70:0b:df:42:72:f8:4f:41:11:64:a5:d2:ea:fc:d5:af:
11:f4:15:38:67:9c:20:a8:4b:77:5a:91:32:42:32:e7:85:b3:
df:36
-----BEGIN CERTIFICATE-----
MIIEQjCCA6ugAwIBAgIEQodApTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEw
MDEwNTAwMDBaFw0xNDA3MjYxODE1MTVaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
BQADgYEASA4rbyBiTCiToyQ9WKshz4D4mpeQaiLtWnxHNpnneYR1qySPkgrVYQSu
w2pcsszZ5ESHb9uPOGL3RDadurxuB8TUjegf0Qtgo7WczmO+7Wfc+Lrebskly1u1
nXZwC99CcvhPQRFkpdLq/NWvEfQVOGecIKhLd1qRMkIy54Wz3zY=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 927650371 (0x374ad243)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Validity
Not Before: May 25 16:09:40 1999 GMT
Not After : May 25 16:39:40 2019 GMT
Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff:
af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1:
0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81:
26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71:
d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24:
da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29:
92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8:
ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81:
b1:16:19:61:b9:54:b6:e6:43
Exponent: 3 (0x3)
X509v3 extensions:
Netscape Cert Type:
SSL CA, S/MIME CA, Object Signing CA
X509v3 CRL Distribution Points:
DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1
URI:http://www.entrust.net/CRL/net1.crl
X509v3 Private Key Usage Period:
Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT
X509v3 Key Usage:
Certificate Sign, CRL Sign
X509v3 Authority Key Identifier:
keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
X509v3 Subject Key Identifier:
F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
X509v3 Basic Constraints:
CA:TRUE
1.2.840.113533.7.65.0:
0
..V4.0....
Signature Algorithm: sha1WithRSAEncryption
90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb:
47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d:
f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31:
c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb:
a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58:
0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54:
73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06:
f9:b2
-----BEGIN CERTIFICATE-----
MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0a:5f:11:4d:03:5b:17:91:17:d2:ef:d4:03:8c:3f:3b
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Validity
Not Before: Apr 2 12:00:00 2008 GMT
Not After : Apr 3 00:00:00 2022 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance CA-3
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:bf:61:0a:29:10:1f:5e:fe:34:37:51:08:f8:1e:
fb:22:ed:61:be:0b:0d:70:4c:50:63:26:75:15:b9:
41:88:97:b6:f0:a0:15:bb:08:60:e0:42:e8:05:29:
10:87:36:8a:28:65:a8:ef:31:07:74:6d:36:97:2f:
28:46:66:04:c7:2a:79:26:7a:99:d5:8e:c3:6d:4f:
a0:5e:ad:bc:3d:91:c2:59:7b:5e:36:6c:c0:53:cf:
00:08:32:3e:10:64:58:10:13:69:c7:0c:ee:9c:42:
51:00:f9:05:44:ee:24:ce:7a:1f:ed:8c:11:bd:12:
a8:f3:15:f4:1c:7a:31:69:01:1b:a7:e6:5d:c0:9a:
6c:7e:09:9e:e7:52:44:4a:10:3a:23:e4:9b:b6:03:
af:a8:9c:b4:5b:9f:d4:4b:ad:92:8c:ce:b5:11:2a:
aa:37:18:8d:b4:c2:b8:d8:5c:06:8c:f8:ff:23:bd:
35:5e:d4:7c:3e:7e:83:0e:91:96:05:98:c3:b2:1f:
e3:c8:65:eb:a9:7b:5d:a0:2c:cc:fc:3c:d9:6d:ed:
cc:fa:4b:43:8c:c9:d4:b8:a5:61:1c:b2:40:b6:28:
12:df:b9:f8:5f:fe:d3:b2:c9:ef:3d:b4:1e:4b:7c:
1c:4c:99:36:9e:3d:eb:ec:a7:68:5e:1d:df:67:6e:
5e:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.1.3.0.2
CPS: http://www.digicert.com/ssl-cps-repository.htm
User Notice:
Explicit Text:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl
Full Name:
URI:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl
X509v3 Authority Key Identifier:
keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Subject Key Identifier:
50:EA:73:89:DB:29:FB:10:8F:9E:E5:01:20:D4:DE:79:99:48:83:F7
Signature Algorithm: sha1WithRSAEncryption
1e:e2:a5:48:9e:6c:db:53:38:0f:ef:a6:1a:2a:ac:e2:03:43:
ed:9a:bc:3e:8e:75:1b:f0:fd:2e:22:59:ac:13:c0:61:e2:e7:
fa:e9:99:cd:87:09:75:54:28:bf:46:60:dc:be:51:2c:92:f3:
1b:91:7c:31:08:70:e2:37:b9:c1:5b:a8:bd:a3:0b:00:fb:1a:
15:fd:03:ad:58:6a:c5:c7:24:99:48:47:46:31:1e:92:ef:b4:
5f:4e:34:c7:90:bf:31:c1:f8:b1:84:86:d0:9c:01:aa:df:8a:
56:06:ce:3a:e9:0e:ae:97:74:5d:d7:71:9a:42:74:5f:de:8d:
43:7c:de:e9:55:ed:69:00:cb:05:e0:7a:61:61:33:d1:19:4d:
f9:08:ee:a0:39:c5:25:35:b7:2b:c4:0f:b2:dd:f1:a5:b7:0e:
24:c4:26:28:8d:79:77:f5:2f:f0:57:ba:7c:07:d4:e1:fc:cd:
5a:30:57:7e:86:10:47:dd:31:1f:d7:fc:a2:c2:bf:30:7c:5d:
24:aa:e8:f9:ae:5f:6a:74:c2:ce:6b:b3:46:d8:21:be:29:d4:
8e:5e:15:d6:42:4a:e7:32:6f:a4:b1:6b:51:83:58:be:3f:6d:
c7:fb:da:03:21:cb:6a:16:19:4e:0a:f0:ad:84:ca:5d:94:b3:
5a:76:f7:61
-----BEGIN CERTIFICATE-----
MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB
hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln
aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME
GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB
INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a
vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j
CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X
dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE
JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY
Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E=
-----END CERTIFICATE-----

View File

@@ -1,197 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0a:5f:11:4d:03:5b:17:91:17:d2:ef:d4:03:8c:3f:3b
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Validity
Not Before: Apr 2 12:00:00 2008 GMT
Not After : Apr 3 00:00:00 2022 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance CA-3
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:bf:61:0a:29:10:1f:5e:fe:34:37:51:08:f8:1e:
fb:22:ed:61:be:0b:0d:70:4c:50:63:26:75:15:b9:
41:88:97:b6:f0:a0:15:bb:08:60:e0:42:e8:05:29:
10:87:36:8a:28:65:a8:ef:31:07:74:6d:36:97:2f:
28:46:66:04:c7:2a:79:26:7a:99:d5:8e:c3:6d:4f:
a0:5e:ad:bc:3d:91:c2:59:7b:5e:36:6c:c0:53:cf:
00:08:32:3e:10:64:58:10:13:69:c7:0c:ee:9c:42:
51:00:f9:05:44:ee:24:ce:7a:1f:ed:8c:11:bd:12:
a8:f3:15:f4:1c:7a:31:69:01:1b:a7:e6:5d:c0:9a:
6c:7e:09:9e:e7:52:44:4a:10:3a:23:e4:9b:b6:03:
af:a8:9c:b4:5b:9f:d4:4b:ad:92:8c:ce:b5:11:2a:
aa:37:18:8d:b4:c2:b8:d8:5c:06:8c:f8:ff:23:bd:
35:5e:d4:7c:3e:7e:83:0e:91:96:05:98:c3:b2:1f:
e3:c8:65:eb:a9:7b:5d:a0:2c:cc:fc:3c:d9:6d:ed:
cc:fa:4b:43:8c:c9:d4:b8:a5:61:1c:b2:40:b6:28:
12:df:b9:f8:5f:fe:d3:b2:c9:ef:3d:b4:1e:4b:7c:
1c:4c:99:36:9e:3d:eb:ec:a7:68:5e:1d:df:67:6e:
5e:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.1.3.0.2
CPS: http://www.digicert.com/ssl-cps-repository.htm
User Notice:
Explicit Text:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
X509v3 CRL Distribution Points:
URI:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl
URI:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl
X509v3 Authority Key Identifier:
keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Subject Key Identifier:
50:EA:73:89:DB:29:FB:10:8F:9E:E5:01:20:D4:DE:79:99:48:83:F7
Signature Algorithm: sha1WithRSAEncryption
1e:e2:a5:48:9e:6c:db:53:38:0f:ef:a6:1a:2a:ac:e2:03:43:
ed:9a:bc:3e:8e:75:1b:f0:fd:2e:22:59:ac:13:c0:61:e2:e7:
fa:e9:99:cd:87:09:75:54:28:bf:46:60:dc:be:51:2c:92:f3:
1b:91:7c:31:08:70:e2:37:b9:c1:5b:a8:bd:a3:0b:00:fb:1a:
15:fd:03:ad:58:6a:c5:c7:24:99:48:47:46:31:1e:92:ef:b4:
5f:4e:34:c7:90:bf:31:c1:f8:b1:84:86:d0:9c:01:aa:df:8a:
56:06:ce:3a:e9:0e:ae:97:74:5d:d7:71:9a:42:74:5f:de:8d:
43:7c:de:e9:55:ed:69:00:cb:05:e0:7a:61:61:33:d1:19:4d:
f9:08:ee:a0:39:c5:25:35:b7:2b:c4:0f:b2:dd:f1:a5:b7:0e:
24:c4:26:28:8d:79:77:f5:2f:f0:57:ba:7c:07:d4:e1:fc:cd:
5a:30:57:7e:86:10:47:dd:31:1f:d7:fc:a2:c2:bf:30:7c:5d:
24:aa:e8:f9:ae:5f:6a:74:c2:ce:6b:b3:46:d8:21:be:29:d4:
8e:5e:15:d6:42:4a:e7:32:6f:a4:b1:6b:51:83:58:be:3f:6d:
c7:fb:da:03:21:cb:6a:16:19:4e:0a:f0:ad:84:ca:5d:94:b3:
5a:76:f7:61
-----BEGIN CERTIFICATE-----
MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB
hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln
aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME
GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB
INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a
vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j
CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X
dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE
JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY
Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1116160165 (0x428740a5)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
Validity
Not Before: Oct 1 05:00:00 2006 GMT
Not After : Jul 26 18:15:15 2014 GMT
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c6:cc:e5:73:e6:fb:d4:bb:e5:2d:2d:32:a6:df:
e5:81:3f:c9:cd:25:49:b6:71:2a:c3:d5:94:34:67:
a2:0a:1c:b0:5f:69:a6:40:b1:c4:b7:b2:8f:d0:98:
a4:a9:41:59:3a:d3:dc:94:d6:3c:db:74:38:a4:4a:
cc:4d:25:82:f7:4a:a5:53:12:38:ee:f3:49:6d:71:
91:7e:63:b6:ab:a6:5f:c3:a4:84:f8:4f:62:51:be:
f8:c5:ec:db:38:92:e3:06:e5:08:91:0c:c4:28:41:
55:fb:cb:5a:89:15:7e:71:e8:35:bf:4d:72:09:3d:
be:3a:38:50:5b:77:31:1b:8d:b3:c7:24:45:9a:a7:
ac:6d:00:14:5a:04:b7:ba:13:eb:51:0a:98:41:41:
22:4e:65:61:87:81:41:50:a6:79:5c:89:de:19:4a:
57:d5:2e:e6:5d:1c:53:2c:7e:98:cd:1a:06:16:a4:
68:73:d0:34:04:13:5c:a1:71:d3:5a:7c:55:db:5e:
64:e1:37:87:30:56:04:e5:11:b4:29:80:12:f1:79:
39:88:a2:02:11:7c:27:66:b7:88:b7:78:f2:ca:0a:
a8:38:ab:0a:64:c2:bf:66:5d:95:84:c1:a1:25:1e:
87:5d:1a:50:0b:20:12:cc:41:bb:6e:0b:51:38:b8:
4b:cb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
Authority Information Access:
OCSP - URI:http://ocsp.entrust.net
X509v3 CRL Distribution Points:
URI:http://crl.entrust.net/server1.crl
X509v3 Subject Key Identifier:
B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
X509v3 Key Usage:
Certificate Sign, CRL Sign
X509v3 Authority Key Identifier:
keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
1.2.840.113533.7.65.0:
0
..V7.1....
Signature Algorithm: sha1WithRSAEncryption
48:0e:2b:6f:20:62:4c:28:93:a3:24:3d:58:ab:21:cf:80:f8:
9a:97:90:6a:22:ed:5a:7c:47:36:99:e7:79:84:75:ab:24:8f:
92:0a:d5:61:04:ae:c3:6a:5c:b2:cc:d9:e4:44:87:6f:db:8f:
38:62:f7:44:36:9d:ba:bc:6e:07:c4:d4:8d:e8:1f:d1:0b:60:
a3:b5:9c:ce:63:be:ed:67:dc:f8:ba:de:6e:c9:25:cb:5b:b5:
9d:76:70:0b:df:42:72:f8:4f:41:11:64:a5:d2:ea:fc:d5:af:
11:f4:15:38:67:9c:20:a8:4b:77:5a:91:32:42:32:e7:85:b3:
df:36
-----BEGIN CERTIFICATE-----
MIIEQjCCA6ugAwIBAgIEQodApTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEw
MDEwNTAwMDBaFw0xNDA3MjYxODE1MTVaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
BQADgYEASA4rbyBiTCiToyQ9WKshz4D4mpeQaiLtWnxHNpnneYR1qySPkgrVYQSu
w2pcsszZ5ESHb9uPOGL3RDadurxuB8TUjegf0Qtgo7WczmO+7Wfc+Lrebskly1u1
nXZwC99CcvhPQRFkpdLq/NWvEfQVOGecIKhLd1qRMkIy54Wz3zY=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,64 @@
{
"schema_version": "2.0",
// All repositories must be an HTTP or HTTPS URL. HTTPS is vastly superior
// since verification of the source server is performed on SSL certificates.
"repositories": [
"http://sublime.wbond.net/packages.json",
"https://github.com/buymeasoda/soda-theme",
"https://github.com/SublimeText"
],
// The "packages_cache" is completely optional, but allows the
// channel to cache and deliver package data from multiple
// repositories in a single HTTP request, allowing for significantly
// improved performance.
"packages_cache": {
// The first level keys are the repository URLs
"http://sublime.wbond.net/packages.json": [
// Each repository has an array of packages with their fully
// expanded info. This means that the "details" key must be expanded
// into the various keys it provides.
{
"name": "Alignment",
"description": "Multi-line and multiple selection alignment plugin",
"author": "wbond",
"homepage": "http://wbond.net/sublime_packages/alignment",
"releases": [
{
"version": "2.0.0",
"url": "https://sublime.wbond.net/Alignment.sublime-package",
"date": "2011-09-18 20:12:41"
}
]
}
]
},
// Package Control ships with the SSL Certificate Authority (CA) cert for the
// SSL certificate that secures and identifies sublime.wbond.net. After this
// initial connection is made, the channel server provides a list of CA certs
// for the various URLs that Package Control need to connect to. This way the
// default channel (https://sublime.wbond.net/channel.json) can provide
// real-time updates to CA certs in the case that a CA is compromised. The
// CA certs are extracted from openssl, and the server runs on an LTS version
// of Ubuntu, which automatically applies security patches from the official
// Ubuntu repositories. This architecture helps to ensure that the packages
// being downloaded are from the source listed and that users are very
// unlikely to be the subject of the man-in-the-middle attack.
"certs": {
// All certs have the domain they apply to as the key
"sublime.wbond.net": [
// The value is an array of two elements, the first being an md5
// hash of the contents of the certificate. This helps in detecting
// CA cert changes. The second element is the URL where the cert
// can be downloaded, if it is not already installed on the users
// copy of Sublime Text.
"7f4f8622b4fd001c7f648e09aae7edaa",
"https://sublime.wbond.net/certs/7f4f8622b4fd001c7f648e09aae7edaa"
]
}
}

View File

@@ -1,54 +0,0 @@
{
"schema_version": "1.2",
"packages": [
{
"name": "GitHub Example",
"description": "An example from GitHub, be sure to use the zipball URL",
"author": "John Smith",
"homepage": "http://example.com",
"last_modified": "2011-12-12 05:04:31",
"platforms": {
"*": [
{
"version": "1.1",
"url": "http://nodeload.github.com/john_smith/github_example/zipball/master"
}
]
}
},
{
"name": "BitBucket Example",
"description": "An example from BitBucket, be sure to use the zip URL",
"author": "John Smith",
"homepage": "http://example.com",
"last_modified": "2011-08-12 12:21:09",
"platforms": {
"*": [
{
"version": "1.0",
"url": "https://bitbucket.org/john_smith/bitbucket_example/get/tip.zip"
}
]
}
},
{
"name": "Tortoise",
"description": "Keyboard shortcuts and menu entries to execute TortoiseSVN, TortoiseHg and TortoiseGit commands",
"author": "Will Bond",
"homepage": "http://sublime.wbond.net",
"last_modified": "2011-11-30 22:55:52",
"platforms": {
"windows": [
{
"version": "1.0",
"url": "http://sublime.wbond.net/Tortoise.sublime-package"
}
]
}
}
],
"renamed_packages": {
"sublime-old-package": "NewPackage",
"OldPackage": "NewName"
}
}

View File

@@ -1,60 +0,0 @@
{
"schema_version": "1.2",
"repositories": [
"http://sublime.wbond.net/packages.json",
"https://github.com/buymeasoda/soda-theme",
"https://github.com/SublimeText"
],
"package_name_map": {
"soda-theme": "Theme - Soda"
},
"renamed_packages": {
"old-name": "New Name"
},
"packages": {
"http://sublime.wbond.net/packages.json": [
{
"name": "GitHub Example",
"description": "An example from GitHub, be sure to use the zipball URL",
"author": "John Smith",
"homepage": "http://example.com",
"platforms": {
"*": [
{
"version": "1.1",
"url": "http://nodeload.github.com/john_smith/github_example/zipball/master"
}
]
}
},
{
"name": "BitBucket Example",
"description": "An example from BitBucket, be sure to use the zip URL",
"author": "John Smith",
"homepage": "http://example.com",
"platforms": {
"*": [
{
"version": "1.0",
"url": "https://bitbucket.org/john_smith/bitbucket_example/get/tip.zip"
}
]
}
},
{
"name": "Tortoise",
"description": "Keyboard shortcuts and menu entries to execute TortoiseSVN, TortoiseHg and TortoiseGit commands",
"author": "Will Bond",
"homepage": "http://sublime.wbond.net",
"platforms": {
"windows": [
{
"version": "1.0",
"url": "http://sublime.wbond.net/Tortoise.sublime-package"
}
]
}
}
]
}
}

View File

@@ -0,0 +1,275 @@
{
"schema_version": "2.0",
// Packages can be specified with a simple URL to a GitHub or BitBucket
// repository, but details can be overridden for every field. It is
// also possible not utilize GitHub or BitBucket at all, but just to
// host your packages on any server with an SSL certificate.
"packages": [
// This is what most packages should aim to model.
//
// The majority of the information about a package ("name",
// "description", "author") are all pulled from the GitHub (or
// BitBucket) repository info.
//
// If the word "sublime" exists in the repository name, the name
// can be overridden by the "name" key.
//
// A release is created from the the tag that is the highest semantic
// versioning version number in the list of tags.
{
"name": "Alignment",
"details": "https://github.com/wbond/sublime_alignment",
"releases": [
{
"details": "https://github.com/wbond/sublime_alignment/tags"
}
]
},
// Here is an equivalent package being pulled from BitBucket
{
"name": "Alignment",
"details": "https://bitbucket.org/wbond/sublime_alignment",
"releases": [
{
"details": "https://bitbucket.org/wbond/sublime_alignment#tags"
}
]
},
// Pull most details from GitHub, releases from master branch.
// This form is discouraged because users will upgrade to every single
// commit you make to master.
{
"details": "https://github.com/wbond/sublime_alignment"
},
// Pull most details from a BitBucket repository and releases from
// the branch "default" or "master", depending on how your repository
// is configured.
// Similar to the above example, this form is discouraged because users
// will upgrade to every single commit you make to master.
{
"details": "https://bitbucket.org/wbond/sublime_alignment"
},
// Use a custom name instead of just the URL slug
{
"name": "Alignment",
"details": "https://github.com/wbond/sublime_alignment"
},
// You can also override the homepage and author
{
"name": "Alignment",
"details": "https://github.com/wbond/sublime_alignment",
"homepage": "http://wbond.net/sublime_packages/alignment",
"author": "wbond"
},
// It is possible to provide the URL to a readme file. This URL
// should be to the raw source of the file, not rendered HTML.
// GitHub and BitBucket repositories will automatically provide
// these.
//
// The following extensions will be rendered:
//
// .markdown, .mdown, .mkd, .md
// .texttile
// .creole
// .rst
//
// All others are treated as plaintext.
{
"details": "https://github.com/wbond/sublime_alignment",
"readme": "https://raw.github.com/wbond/sublime_alignment/master/readme.creole"
},
// If a package has a public bug tracker, the URL should be
// included via the "issues" key. Both GitHub and BitBucket
// repositories will automatically provide this if they have
// issues enabled.
{
"details": "https://github.com/wbond/sublime_alignment",
"issues": "https://github.com/wbond/sublime_alignment/issues"
},
// The URL to donate to support the development of a package.
// GitHub and BitBucket repositories will default to:
//
// https://www.gittip.com/{username}/
//
// Other URLs with special integration include:
//
// https://flattr.com/profile/{username}
// https://www.dwolla.com/hub/{username}
//
// This may also contain a URL to another other donation-type site
// where users may support the author for their development of the
// package.
{
"details": "https://github.com/wbond/sublime_alignment",
"donate": "https://www.gittip.com/wbond/"
},
// The URL to purchase a license to the package
{
"details": "https://github.com/wbond/sublime_alignment",
"buy": "https://wbond.net/sublime_packages/alignment/buy"
},
// If you rename a package, you can provide the previous name(s)
// so that users with the old package name can be automatically
// upgraded to the new one.
{
"name": "Alignment",
"details": "https://github.com/wbond/sublime_alignment",
"previous_names": ["sublime_alignment"]
},
// Packages can be labelled for the purpose of creating a
// folksonomy so users may more easily find relevant packages.
// Labels should be all lower case and should use spaces instead
// of _ or - to separate words.
//
// Some suggested labels are listed below, however, anything can
// be used as a label:
//
// auto-complete
// browser integration
// build system
// code navigation
// code sharing
// color scheme
// deprecated
// diff/merge
// editor emulation
// file creation
// file navigation
// formatting
// ftp
// language syntax
// linting
// minification
// search
// snippets
// terminal/shell/repl
// testing
// text manipulation
// text navigation
// theme
// todo
// vcs
{
"details": "https://github.com/wbond/sublime_alignment",
"labels": ["text manipulation", "formatting"]
},
// In addition to the recommendation above of pulling releases
// from tags that are semantic version numbers, releases can also
// comefrom a custom branch.
{
"details": "https://github.com/wbond/sublime_alignment",
"releases": [
{
"details": "https://github.com/wbond/sublime_alignment/tree/custom_branch"
}
]
},
// An equivalent package being pulled from BitBucket.
{
"details": "https://bitbucket.org/wbond/sublime_alignment",
"releases": [
{
"details": "https://bitbucket.org/wbond/sublime_alignment/src/custom_branch"
}
]
},
// If your package is only compatible with specific builds of
// Sublime Text, this will cause the package to be hidden from
// users with incompatible versions.
{
"details": "https://github.com/wbond/sublime_alignment",
"releases": [
{
// Could also be >2999 for ST3. Leaving this out indicates
// the package works with both ST2 and ST3.
"sublime_text": "<3000",
"details": "https://github.com/wbond/sublime_alignment"
}
]
},
// The "platforms" key allows specifying what platform(s) the release
// is valid for. As shown, there can be multiple releases of a package
// at any given time. However, only the latest version for any given
// platform/arch will be shown to the user.
//
// The "platforms" key allows specifying a single platform, or a list
// of platforms. Valid platform indentifiers include:
//
// "*"
// "windows", "windows-x64", "windows-x32"
// "osx", "osx-x64"
// "linux", "linux-x32", "linux-x64"
{
"details": "https://github.com/wbond/sublime_alignment",
"releases": [
{
// Defaults to "*", or all platforms.
"platforms": ["osx", "linux"],
"details": "https://github.com/wbond/sublime_alignment/tree/posix"
},
{
"platforms": "windows",
"details": "https://github.com/wbond/sublime_alignment/tree/win32"
}
]
},
// If you don't use a "details" key for a "releases" entry, you need to
// specify the "version", "url" and "date" manually.
{
"details": "https://github.com/wbond/sublime_alignment",
"releases": [
{
// The version number needs to be a semantic version number per
// http://semver.org 2.x.x
"version": "2.0.0",
// The URL needs to be a zip file containing the package. It is permissible
// for the zip file to contain a single root folder with any name. All
// file will be extracted out of this single root folder. This allows
// zip files from GitHub and BitBucket to be used a sources.
"url": "https://codeload.github.com/wbond/sublime_alignment/zip/v2.0.0",
// The date MUST be in the form "YYYY-MM-DD HH:MM:SS" and SHOULD be UTC
"date": "2011-09-18 20:12:41"
}
]
}
],
// If you need/want to split your repository up into multiple smaller files
// for the sake of organization, the "includes" key allows you to enter
// URL paths that will be combined together and dynamically inserted
// into the "packages" key. These URLs these can be relative or absolute.
"includes": [
// Here is an example of how relative paths work for URLs. If this file
// was loaded from:
// "https://sublime.wbond.net/example-repository.json"
// then the following files would be loaded from:
// "https://sublime.wbond.net/repository/0-9.json"
// "https://sublime.wbond.net/repository/a.json"
"./repository/0-9.json",
"./repository/a.json",
// An example of an absolute URL
"https://sublime.wbond.net/repository/b.json"
]
}

View File

@@ -1,86 +0,0 @@
# -*- coding: utf-8 -*-
# This code is copyright Konstantine Rybnikov <k-bx@k-bx.com>, and is
# available at https://github.com/k-bx/python-semver and is licensed under the
# BSD License
import re
_REGEX = re.compile('^(?P<major>[0-9]+)'
'\.(?P<minor>[0-9]+)'
'\.(?P<patch>[0-9]+)'
'(\-(?P<prerelease>[0-9A-Za-z]+(\.[0-9A-Za-z]+)*))?'
'(\+(?P<build>[0-9A-Za-z]+(\.[0-9A-Za-z]+)*))?$')
if 'cmp' not in __builtins__:
cmp = lambda a,b: (a > b) - (a < b)
def parse(version):
"""
Parse version to major, minor, patch, pre-release, build parts.
"""
match = _REGEX.match(version)
if match is None:
raise ValueError('%s is not valid SemVer string' % version)
verinfo = match.groupdict()
verinfo['major'] = int(verinfo['major'])
verinfo['minor'] = int(verinfo['minor'])
verinfo['patch'] = int(verinfo['patch'])
return verinfo
def compare(ver1, ver2):
def nat_cmp(a, b):
a, b = a or '', b or ''
convert = lambda text: text.isdigit() and int(text) or text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return cmp(alphanum_key(a), alphanum_key(b))
def compare_by_keys(d1, d2):
for key in ['major', 'minor', 'patch']:
v = cmp(d1.get(key), d2.get(key))
if v:
return v
rc1, rc2 = d1.get('prerelease'), d2.get('prerelease')
build1, build2 = d1.get('build'), d2.get('build')
rccmp = nat_cmp(rc1, rc2)
buildcmp = nat_cmp(build1, build2)
if not (rc1 or rc2):
return buildcmp
elif not rc1:
return 1
elif not rc2:
return -1
return rccmp or buildcmp or 0
v1, v2 = parse(ver1), parse(ver2)
return compare_by_keys(v1, v2)
def match(version, match_expr):
prefix = match_expr[:2]
if prefix in ('>=', '<=', '=='):
match_version = match_expr[2:]
elif prefix and prefix[0] in ('>', '<', '='):
prefix = prefix[0]
match_version = match_expr[1:]
else:
raise ValueError("match_expr parameter should be in format <op><ver>, "
"where <op> is one of ['<', '>', '==', '<=', '>=']. "
"You provided: %r" % match_expr)
possibilities_dict = {
'>': (1,),
'<': (-1,),
'==': (0,),
'>=': (0, 1),
'<=': (-1, 0)
}
possibilities = possibilities_dict[prefix]
cmp_res = compare(version, match_version)
return cmp_res in possibilities

View File

@@ -1,113 +0,0 @@
# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/
# Copyright 2001 Dmitry A. Rozmanov <dima@xenon.spb.ru>
#
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
C = 0x1000000000L
def norm(n):
return n & 0xFFFFFFFFL
class U32:
v = 0L
def __init__(self, value = 0):
self.v = C + norm(abs(long(value)))
def set(self, value = 0):
self.v = C + norm(abs(long(value)))
def __repr__(self):
return hex(norm(self.v))
def __long__(self): return long(norm(self.v))
def __int__(self): return int(norm(self.v))
def __chr__(self): return chr(norm(self.v))
def __add__(self, b):
r = U32()
r.v = C + norm(self.v + b.v)
return r
def __sub__(self, b):
r = U32()
if self.v < b.v:
r.v = C + norm(0x100000000L - (b.v - self.v))
else: r.v = C + norm(self.v - b.v)
return r
def __mul__(self, b):
r = U32()
r.v = C + norm(self.v * b.v)
return r
def __div__(self, b):
r = U32()
r.v = C + (norm(self.v) / norm(b.v))
return r
def __mod__(self, b):
r = U32()
r.v = C + (norm(self.v) % norm(b.v))
return r
def __neg__(self): return U32(self.v)
def __pos__(self): return U32(self.v)
def __abs__(self): return U32(self.v)
def __invert__(self):
r = U32()
r.v = C + norm(~self.v)
return r
def __lshift__(self, b):
r = U32()
r.v = C + norm(self.v << b)
return r
def __rshift__(self, b):
r = U32()
r.v = C + (norm(self.v) >> b)
return r
def __and__(self, b):
r = U32()
r.v = C + norm(self.v & b.v)
return r
def __or__(self, b):
r = U32()
r.v = C + norm(self.v | b.v)
return r
def __xor__(self, b):
r = U32()
r.v = C + norm(self.v ^ b.v)
return r
def __not__(self):
return U32(not norm(self.v))
def truth(self):
return norm(self.v)
def __cmp__(self, b):
if norm(self.v) > norm(b.v): return 1
elif norm(self.v) < norm(b.v): return -1
else: return 0
def __nonzero__(self):
return norm(self.v)

View File

@@ -1,92 +0,0 @@
# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/
# Copyright 2001 Dmitry A. Rozmanov <dima@xenon.spb.ru>
#
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
import des_c
#---------------------------------------------------------------------
class DES:
des_c_obj = None
#-----------------------------------------------------------------
def __init__(self, key_str):
""
k = str_to_key56(key_str)
k = key56_to_key64(k)
key_str = ''
for i in k:
key_str += chr(i & 0xFF)
self.des_c_obj = des_c.DES(key_str)
#-----------------------------------------------------------------
def encrypt(self, plain_text):
""
return self.des_c_obj.encrypt(plain_text)
#-----------------------------------------------------------------
def decrypt(self, crypted_text):
""
return self.des_c_obj.decrypt(crypted_text)
#---------------------------------------------------------------------
#Some Helpers
#---------------------------------------------------------------------
DESException = 'DESException'
#---------------------------------------------------------------------
def str_to_key56(key_str):
""
if type(key_str) != type(''):
#rise DESException, 'ERROR. Wrong key type.'
pass
if len(key_str) < 7:
key_str = key_str + '\000\000\000\000\000\000\000'[:(7 - len(key_str))]
key_56 = []
for i in key_str[:7]: key_56.append(ord(i))
return key_56
#---------------------------------------------------------------------
def key56_to_key64(key_56):
""
key = []
for i in range(8): key.append(0)
key[0] = key_56[0];
key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
key[7] = (key_56[6] << 1) & 0xFF;
key = set_key_odd_parity(key)
return key
#---------------------------------------------------------------------
def set_key_odd_parity(key):
""
for i in range(len(key)):
for k in range(7):
bit = 0
t = key[i] >> k
bit = (t ^ bit) & 0x1
key[i] = (key[i] & 0xFE) | bit
return key

View File

@@ -1,328 +0,0 @@
# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/
# Copyright 2001 Dmitry A. Rozmanov <dima@xenon.spb.ru>
#
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
from U32 import U32
# --NON ASCII COMMENT ELIDED--
#typedef unsigned char des_cblock[8];
#define HDRSIZE 4
def c2l(c):
"char[4] to unsigned long"
l = U32(c[0])
l = l | (U32(c[1]) << 8)
l = l | (U32(c[2]) << 16)
l = l | (U32(c[3]) << 24)
return l
def c2ln(c,l1,l2,n):
"char[n] to two unsigned long???"
c = c + n
l1, l2 = U32(0), U32(0)
f = 0
if n == 8:
l2 = l2 | (U32(c[7]) << 24)
f = 1
if f or (n == 7):
l2 = l2 | (U32(c[6]) << 16)
f = 1
if f or (n == 6):
l2 = l2 | (U32(c[5]) << 8)
f = 1
if f or (n == 5):
l2 = l2 | U32(c[4])
f = 1
if f or (n == 4):
l1 = l1 | (U32(c[3]) << 24)
f = 1
if f or (n == 3):
l1 = l1 | (U32(c[2]) << 16)
f = 1
if f or (n == 2):
l1 = l1 | (U32(c[1]) << 8)
f = 1
if f or (n == 1):
l1 = l1 | U32(c[0])
return (l1, l2)
def l2c(l):
"unsigned long to char[4]"
c = []
c.append(int(l & U32(0xFF)))
c.append(int((l >> 8) & U32(0xFF)))
c.append(int((l >> 16) & U32(0xFF)))
c.append(int((l >> 24) & U32(0xFF)))
return c
def n2l(c, l):
"network to host long"
l = U32(c[0] << 24)
l = l | (U32(c[1]) << 16)
l = l | (U32(c[2]) << 8)
l = l | (U32(c[3]))
return l
def l2n(l, c):
"host to network long"
c = []
c.append(int((l >> 24) & U32(0xFF)))
c.append(int((l >> 16) & U32(0xFF)))
c.append(int((l >> 8) & U32(0xFF)))
c.append(int((l ) & U32(0xFF)))
return c
def l2cn(l1, l2, c, n):
""
for i in range(n): c.append(0x00)
f = 0
if f or (n == 8):
c[7] = int((l2 >> 24) & U32(0xFF))
f = 1
if f or (n == 7):
c[6] = int((l2 >> 16) & U32(0xFF))
f = 1
if f or (n == 6):
c[5] = int((l2 >> 8) & U32(0xFF))
f = 1
if f or (n == 5):
c[4] = int((l2 ) & U32(0xFF))
f = 1
if f or (n == 4):
c[3] = int((l1 >> 24) & U32(0xFF))
f = 1
if f or (n == 3):
c[2] = int((l1 >> 16) & U32(0xFF))
f = 1
if f or (n == 2):
c[1] = int((l1 >> 8) & U32(0xFF))
f = 1
if f or (n == 1):
c[0] = int((l1 ) & U32(0xFF))
f = 1
return c[:n]
# array of data
# static unsigned long des_SPtrans[8][64]={
# static unsigned long des_skb[8][64]={
from des_data import des_SPtrans, des_skb
def D_ENCRYPT(tup, u, t, s):
L, R, S = tup
#print 'LRS1', L, R, S, u, t, '-->',
u = (R ^ s[S])
t = R ^ s[S + 1]
t = ((t >> 4) + (t << 28))
L = L ^ (des_SPtrans[1][int((t ) & U32(0x3f))] | \
des_SPtrans[3][int((t >> 8) & U32(0x3f))] | \
des_SPtrans[5][int((t >> 16) & U32(0x3f))] | \
des_SPtrans[7][int((t >> 24) & U32(0x3f))] | \
des_SPtrans[0][int((u ) & U32(0x3f))] | \
des_SPtrans[2][int((u >> 8) & U32(0x3f))] | \
des_SPtrans[4][int((u >> 16) & U32(0x3f))] | \
des_SPtrans[6][int((u >> 24) & U32(0x3f))])
#print 'LRS:', L, R, S, u, t
return ((L, R, S), u, t, s)
def PERM_OP (tup, n, m):
"tup - (a, b, t)"
a, b, t = tup
t = ((a >> n) ^ b) & m
b = b ^ t
a = a ^ (t << n)
return (a, b, t)
def HPERM_OP (tup, n, m):
"tup - (a, t)"
a, t = tup
t = ((a << (16 - n)) ^ a) & m
a = a ^ t ^ (t >> (16 - n))
return (a, t)
shifts2 = [0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0]
class DES:
KeySched = None # des_key_schedule
def __init__(self, key_str):
# key - UChar[8]
key = []
for i in key_str: key.append(ord(i))
#print 'key:', key
self.KeySched = des_set_key(key)
#print 'schedule:', self.KeySched, len(self.KeySched)
def decrypt(self, str):
# block - UChar[]
block = []
for i in str: block.append(ord(i))
#print block
block = des_ecb_encrypt(block, self.KeySched, 0)
res = ''
for i in block: res = res + (chr(i))
return res
def encrypt(self, str):
# block - UChar[]
block = []
for i in str: block.append(ord(i))
block = des_ecb_encrypt(block, self.KeySched, 1)
res = ''
for i in block: res = res + (chr(i))
return res
#------------------------
def des_encript(input, ks, encrypt):
# input - U32[]
# output - U32[]
# ks - des_key_shedule - U32[2][16]
# encrypt - int
# l, r, t, u - U32
# i - int
# s - U32[]
l = input[0]
r = input[1]
t = U32(0)
u = U32(0)
r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0fL))
l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffffL))
r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333L))
l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ffL))
r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555L))
t = (r << 1)|(r >> 31)
r = (l << 1)|(l >> 31)
l = t
s = ks # ???????????????
#print l, r
if(encrypt):
for i in range(0, 32, 4):
rtup, u, t, s = D_ENCRYPT((l, r, i + 0), u, t, s)
l = rtup[0]
r = rtup[1]
rtup, u, t, s = D_ENCRYPT((r, l, i + 2), u, t, s)
r = rtup[0]
l = rtup[1]
else:
for i in range(30, 0, -4):
rtup, u, t, s = D_ENCRYPT((l, r, i - 0), u, t, s)
l = rtup[0]
r = rtup[1]
rtup, u, t, s = D_ENCRYPT((r, l, i - 2), u, t, s)
r = rtup[0]
l = rtup[1]
#print l, r
l = (l >> 1)|(l << 31)
r = (r >> 1)|(r << 31)
r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555L))
l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ffL))
r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333L))
l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffffL))
r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0fL))
output = [l]
output.append(r)
l, r, t, u = U32(0), U32(0), U32(0), U32(0)
return output
def des_ecb_encrypt(input, ks, encrypt):
# input - des_cblock - UChar[8]
# output - des_cblock - UChar[8]
# ks - des_key_shedule - U32[2][16]
# encrypt - int
#print input
l0 = c2l(input[0:4])
l1 = c2l(input[4:8])
ll = [l0]
ll.append(l1)
#print ll
ll = des_encript(ll, ks, encrypt)
#print ll
l0 = ll[0]
l1 = ll[1]
output = l2c(l0)
output = output + l2c(l1)
#print output
l0, l1, ll[0], ll[1] = U32(0), U32(0), U32(0), U32(0)
return output
def des_set_key(key):
# key - des_cblock - UChar[8]
# schedule - des_key_schedule
# register unsigned long c,d,t,s;
# register unsigned char *in;
# register unsigned long *k;
# register int i;
#k = schedule
# in = key
k = []
c = c2l(key[0:4])
d = c2l(key[4:8])
t = U32(0)
d, c, t = PERM_OP((d, c, t), 4, U32(0x0f0f0f0fL))
c, t = HPERM_OP((c, t), -2, U32(0xcccc0000L))
d, t = HPERM_OP((d, t), -2, U32(0xcccc0000L))
d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555L))
c, d, t = PERM_OP((c, d, t), 8, U32(0x00ff00ffL))
d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555L))
d = (((d & U32(0x000000ffL)) << 16)|(d & U32(0x0000ff00L))|((d & U32(0x00ff0000L)) >> 16)|((c & U32(0xf0000000L)) >> 4))
c = c & U32(0x0fffffffL)
for i in range(16):
if (shifts2[i]):
c = ((c >> 2)|(c << 26))
d = ((d >> 2)|(d << 26))
else:
c = ((c >> 1)|(c << 27))
d = ((d >> 1)|(d << 27))
c = c & U32(0x0fffffffL)
d = d & U32(0x0fffffffL)
s= des_skb[0][int((c ) & U32(0x3f))]|\
des_skb[1][int(((c>> 6) & U32(0x03))|((c>> 7) & U32(0x3c)))]|\
des_skb[2][int(((c>>13) & U32(0x0f))|((c>>14) & U32(0x30)))]|\
des_skb[3][int(((c>>20) & U32(0x01))|((c>>21) & U32(0x06)) | ((c>>22) & U32(0x38)))]
t= des_skb[4][int((d ) & U32(0x3f) )]|\
des_skb[5][int(((d>> 7) & U32(0x03))|((d>> 8) & U32(0x3c)))]|\
des_skb[6][int((d>>15) & U32(0x3f) )]|\
des_skb[7][int(((d>>21) & U32(0x0f))|((d>>22) & U32(0x30)))]
#print s, t
k.append(((t << 16)|(s & U32(0x0000ffffL))) & U32(0xffffffffL))
s = ((s >> 16)|(t & U32(0xffff0000L)))
s = (s << 4)|(s >> 28)
k.append(s & U32(0xffffffffL))
schedule = k
return schedule

View File

@@ -1,348 +0,0 @@
# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/
# Copyright 2001 Dmitry A. Rozmanov <dima@xenon.spb.ru>
#
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
from U32 import U32
# static unsigned long des_SPtrans[8][64]={
des_SPtrans =\
[
#nibble 0
[
U32(0x00820200L), U32(0x00020000L), U32(0x80800000L), U32(0x80820200L),
U32(0x00800000L), U32(0x80020200L), U32(0x80020000L), U32(0x80800000L),
U32(0x80020200L), U32(0x00820200L), U32(0x00820000L), U32(0x80000200L),
U32(0x80800200L), U32(0x00800000L), U32(0x00000000L), U32(0x80020000L),
U32(0x00020000L), U32(0x80000000L), U32(0x00800200L), U32(0x00020200L),
U32(0x80820200L), U32(0x00820000L), U32(0x80000200L), U32(0x00800200L),
U32(0x80000000L), U32(0x00000200L), U32(0x00020200L), U32(0x80820000L),
U32(0x00000200L), U32(0x80800200L), U32(0x80820000L), U32(0x00000000L),
U32(0x00000000L), U32(0x80820200L), U32(0x00800200L), U32(0x80020000L),
U32(0x00820200L), U32(0x00020000L), U32(0x80000200L), U32(0x00800200L),
U32(0x80820000L), U32(0x00000200L), U32(0x00020200L), U32(0x80800000L),
U32(0x80020200L), U32(0x80000000L), U32(0x80800000L), U32(0x00820000L),
U32(0x80820200L), U32(0x00020200L), U32(0x00820000L), U32(0x80800200L),
U32(0x00800000L), U32(0x80000200L), U32(0x80020000L), U32(0x00000000L),
U32(0x00020000L), U32(0x00800000L), U32(0x80800200L), U32(0x00820200L),
U32(0x80000000L), U32(0x80820000L), U32(0x00000200L), U32(0x80020200L),
],
#nibble 1
[
U32(0x10042004L), U32(0x00000000L), U32(0x00042000L), U32(0x10040000L),
U32(0x10000004L), U32(0x00002004L), U32(0x10002000L), U32(0x00042000L),
U32(0x00002000L), U32(0x10040004L), U32(0x00000004L), U32(0x10002000L),
U32(0x00040004L), U32(0x10042000L), U32(0x10040000L), U32(0x00000004L),
U32(0x00040000L), U32(0x10002004L), U32(0x10040004L), U32(0x00002000L),
U32(0x00042004L), U32(0x10000000L), U32(0x00000000L), U32(0x00040004L),
U32(0x10002004L), U32(0x00042004L), U32(0x10042000L), U32(0x10000004L),
U32(0x10000000L), U32(0x00040000L), U32(0x00002004L), U32(0x10042004L),
U32(0x00040004L), U32(0x10042000L), U32(0x10002000L), U32(0x00042004L),
U32(0x10042004L), U32(0x00040004L), U32(0x10000004L), U32(0x00000000L),
U32(0x10000000L), U32(0x00002004L), U32(0x00040000L), U32(0x10040004L),
U32(0x00002000L), U32(0x10000000L), U32(0x00042004L), U32(0x10002004L),
U32(0x10042000L), U32(0x00002000L), U32(0x00000000L), U32(0x10000004L),
U32(0x00000004L), U32(0x10042004L), U32(0x00042000L), U32(0x10040000L),
U32(0x10040004L), U32(0x00040000L), U32(0x00002004L), U32(0x10002000L),
U32(0x10002004L), U32(0x00000004L), U32(0x10040000L), U32(0x00042000L),
],
#nibble 2
[
U32(0x41000000L), U32(0x01010040L), U32(0x00000040L), U32(0x41000040L),
U32(0x40010000L), U32(0x01000000L), U32(0x41000040L), U32(0x00010040L),
U32(0x01000040L), U32(0x00010000L), U32(0x01010000L), U32(0x40000000L),
U32(0x41010040L), U32(0x40000040L), U32(0x40000000L), U32(0x41010000L),
U32(0x00000000L), U32(0x40010000L), U32(0x01010040L), U32(0x00000040L),
U32(0x40000040L), U32(0x41010040L), U32(0x00010000L), U32(0x41000000L),
U32(0x41010000L), U32(0x01000040L), U32(0x40010040L), U32(0x01010000L),
U32(0x00010040L), U32(0x00000000L), U32(0x01000000L), U32(0x40010040L),
U32(0x01010040L), U32(0x00000040L), U32(0x40000000L), U32(0x00010000L),
U32(0x40000040L), U32(0x40010000L), U32(0x01010000L), U32(0x41000040L),
U32(0x00000000L), U32(0x01010040L), U32(0x00010040L), U32(0x41010000L),
U32(0x40010000L), U32(0x01000000L), U32(0x41010040L), U32(0x40000000L),
U32(0x40010040L), U32(0x41000000L), U32(0x01000000L), U32(0x41010040L),
U32(0x00010000L), U32(0x01000040L), U32(0x41000040L), U32(0x00010040L),
U32(0x01000040L), U32(0x00000000L), U32(0x41010000L), U32(0x40000040L),
U32(0x41000000L), U32(0x40010040L), U32(0x00000040L), U32(0x01010000L),
],
#nibble 3
[
U32(0x00100402L), U32(0x04000400L), U32(0x00000002L), U32(0x04100402L),
U32(0x00000000L), U32(0x04100000L), U32(0x04000402L), U32(0x00100002L),
U32(0x04100400L), U32(0x04000002L), U32(0x04000000L), U32(0x00000402L),
U32(0x04000002L), U32(0x00100402L), U32(0x00100000L), U32(0x04000000L),
U32(0x04100002L), U32(0x00100400L), U32(0x00000400L), U32(0x00000002L),
U32(0x00100400L), U32(0x04000402L), U32(0x04100000L), U32(0x00000400L),
U32(0x00000402L), U32(0x00000000L), U32(0x00100002L), U32(0x04100400L),
U32(0x04000400L), U32(0x04100002L), U32(0x04100402L), U32(0x00100000L),
U32(0x04100002L), U32(0x00000402L), U32(0x00100000L), U32(0x04000002L),
U32(0x00100400L), U32(0x04000400L), U32(0x00000002L), U32(0x04100000L),
U32(0x04000402L), U32(0x00000000L), U32(0x00000400L), U32(0x00100002L),
U32(0x00000000L), U32(0x04100002L), U32(0x04100400L), U32(0x00000400L),
U32(0x04000000L), U32(0x04100402L), U32(0x00100402L), U32(0x00100000L),
U32(0x04100402L), U32(0x00000002L), U32(0x04000400L), U32(0x00100402L),
U32(0x00100002L), U32(0x00100400L), U32(0x04100000L), U32(0x04000402L),
U32(0x00000402L), U32(0x04000000L), U32(0x04000002L), U32(0x04100400L),
],
#nibble 4
[
U32(0x02000000L), U32(0x00004000L), U32(0x00000100L), U32(0x02004108L),
U32(0x02004008L), U32(0x02000100L), U32(0x00004108L), U32(0x02004000L),
U32(0x00004000L), U32(0x00000008L), U32(0x02000008L), U32(0x00004100L),
U32(0x02000108L), U32(0x02004008L), U32(0x02004100L), U32(0x00000000L),
U32(0x00004100L), U32(0x02000000L), U32(0x00004008L), U32(0x00000108L),
U32(0x02000100L), U32(0x00004108L), U32(0x00000000L), U32(0x02000008L),
U32(0x00000008L), U32(0x02000108L), U32(0x02004108L), U32(0x00004008L),
U32(0x02004000L), U32(0x00000100L), U32(0x00000108L), U32(0x02004100L),
U32(0x02004100L), U32(0x02000108L), U32(0x00004008L), U32(0x02004000L),
U32(0x00004000L), U32(0x00000008L), U32(0x02000008L), U32(0x02000100L),
U32(0x02000000L), U32(0x00004100L), U32(0x02004108L), U32(0x00000000L),
U32(0x00004108L), U32(0x02000000L), U32(0x00000100L), U32(0x00004008L),
U32(0x02000108L), U32(0x00000100L), U32(0x00000000L), U32(0x02004108L),
U32(0x02004008L), U32(0x02004100L), U32(0x00000108L), U32(0x00004000L),
U32(0x00004100L), U32(0x02004008L), U32(0x02000100L), U32(0x00000108L),
U32(0x00000008L), U32(0x00004108L), U32(0x02004000L), U32(0x02000008L),
],
#nibble 5
[
U32(0x20000010L), U32(0x00080010L), U32(0x00000000L), U32(0x20080800L),
U32(0x00080010L), U32(0x00000800L), U32(0x20000810L), U32(0x00080000L),
U32(0x00000810L), U32(0x20080810L), U32(0x00080800L), U32(0x20000000L),
U32(0x20000800L), U32(0x20000010L), U32(0x20080000L), U32(0x00080810L),
U32(0x00080000L), U32(0x20000810L), U32(0x20080010L), U32(0x00000000L),
U32(0x00000800L), U32(0x00000010L), U32(0x20080800L), U32(0x20080010L),
U32(0x20080810L), U32(0x20080000L), U32(0x20000000L), U32(0x00000810L),
U32(0x00000010L), U32(0x00080800L), U32(0x00080810L), U32(0x20000800L),
U32(0x00000810L), U32(0x20000000L), U32(0x20000800L), U32(0x00080810L),
U32(0x20080800L), U32(0x00080010L), U32(0x00000000L), U32(0x20000800L),
U32(0x20000000L), U32(0x00000800L), U32(0x20080010L), U32(0x00080000L),
U32(0x00080010L), U32(0x20080810L), U32(0x00080800L), U32(0x00000010L),
U32(0x20080810L), U32(0x00080800L), U32(0x00080000L), U32(0x20000810L),
U32(0x20000010L), U32(0x20080000L), U32(0x00080810L), U32(0x00000000L),
U32(0x00000800L), U32(0x20000010L), U32(0x20000810L), U32(0x20080800L),
U32(0x20080000L), U32(0x00000810L), U32(0x00000010L), U32(0x20080010L),
],
#nibble 6
[
U32(0x00001000L), U32(0x00000080L), U32(0x00400080L), U32(0x00400001L),
U32(0x00401081L), U32(0x00001001L), U32(0x00001080L), U32(0x00000000L),
U32(0x00400000L), U32(0x00400081L), U32(0x00000081L), U32(0x00401000L),
U32(0x00000001L), U32(0x00401080L), U32(0x00401000L), U32(0x00000081L),
U32(0x00400081L), U32(0x00001000L), U32(0x00001001L), U32(0x00401081L),
U32(0x00000000L), U32(0x00400080L), U32(0x00400001L), U32(0x00001080L),
U32(0x00401001L), U32(0x00001081L), U32(0x00401080L), U32(0x00000001L),
U32(0x00001081L), U32(0x00401001L), U32(0x00000080L), U32(0x00400000L),
U32(0x00001081L), U32(0x00401000L), U32(0x00401001L), U32(0x00000081L),
U32(0x00001000L), U32(0x00000080L), U32(0x00400000L), U32(0x00401001L),
U32(0x00400081L), U32(0x00001081L), U32(0x00001080L), U32(0x00000000L),
U32(0x00000080L), U32(0x00400001L), U32(0x00000001L), U32(0x00400080L),
U32(0x00000000L), U32(0x00400081L), U32(0x00400080L), U32(0x00001080L),
U32(0x00000081L), U32(0x00001000L), U32(0x00401081L), U32(0x00400000L),
U32(0x00401080L), U32(0x00000001L), U32(0x00001001L), U32(0x00401081L),
U32(0x00400001L), U32(0x00401080L), U32(0x00401000L), U32(0x00001001L),
],
#nibble 7
[
U32(0x08200020L), U32(0x08208000L), U32(0x00008020L), U32(0x00000000L),
U32(0x08008000L), U32(0x00200020L), U32(0x08200000L), U32(0x08208020L),
U32(0x00000020L), U32(0x08000000L), U32(0x00208000L), U32(0x00008020L),
U32(0x00208020L), U32(0x08008020L), U32(0x08000020L), U32(0x08200000L),
U32(0x00008000L), U32(0x00208020L), U32(0x00200020L), U32(0x08008000L),
U32(0x08208020L), U32(0x08000020L), U32(0x00000000L), U32(0x00208000L),
U32(0x08000000L), U32(0x00200000L), U32(0x08008020L), U32(0x08200020L),
U32(0x00200000L), U32(0x00008000L), U32(0x08208000L), U32(0x00000020L),
U32(0x00200000L), U32(0x00008000L), U32(0x08000020L), U32(0x08208020L),
U32(0x00008020L), U32(0x08000000L), U32(0x00000000L), U32(0x00208000L),
U32(0x08200020L), U32(0x08008020L), U32(0x08008000L), U32(0x00200020L),
U32(0x08208000L), U32(0x00000020L), U32(0x00200020L), U32(0x08008000L),
U32(0x08208020L), U32(0x00200000L), U32(0x08200000L), U32(0x08000020L),
U32(0x00208000L), U32(0x00008020L), U32(0x08008020L), U32(0x08200000L),
U32(0x00000020L), U32(0x08208000L), U32(0x00208020L), U32(0x00000000L),
U32(0x08000000L), U32(0x08200020L), U32(0x00008000L), U32(0x00208020L),
],
]
#static unsigned long des_skb[8][64]={
des_skb = \
[
#for C bits (numbered as per FIPS 46) 1 2 3 4 5 6
[
U32(0x00000000L),U32(0x00000010L),U32(0x20000000L),U32(0x20000010L),
U32(0x00010000L),U32(0x00010010L),U32(0x20010000L),U32(0x20010010L),
U32(0x00000800L),U32(0x00000810L),U32(0x20000800L),U32(0x20000810L),
U32(0x00010800L),U32(0x00010810L),U32(0x20010800L),U32(0x20010810L),
U32(0x00000020L),U32(0x00000030L),U32(0x20000020L),U32(0x20000030L),
U32(0x00010020L),U32(0x00010030L),U32(0x20010020L),U32(0x20010030L),
U32(0x00000820L),U32(0x00000830L),U32(0x20000820L),U32(0x20000830L),
U32(0x00010820L),U32(0x00010830L),U32(0x20010820L),U32(0x20010830L),
U32(0x00080000L),U32(0x00080010L),U32(0x20080000L),U32(0x20080010L),
U32(0x00090000L),U32(0x00090010L),U32(0x20090000L),U32(0x20090010L),
U32(0x00080800L),U32(0x00080810L),U32(0x20080800L),U32(0x20080810L),
U32(0x00090800L),U32(0x00090810L),U32(0x20090800L),U32(0x20090810L),
U32(0x00080020L),U32(0x00080030L),U32(0x20080020L),U32(0x20080030L),
U32(0x00090020L),U32(0x00090030L),U32(0x20090020L),U32(0x20090030L),
U32(0x00080820L),U32(0x00080830L),U32(0x20080820L),U32(0x20080830L),
U32(0x00090820L),U32(0x00090830L),U32(0x20090820L),U32(0x20090830L),
],
#for C bits (numbered as per FIPS 46) 7 8 10 11 12 13
[
U32(0x00000000L),U32(0x02000000L),U32(0x00002000L),U32(0x02002000L),
U32(0x00200000L),U32(0x02200000L),U32(0x00202000L),U32(0x02202000L),
U32(0x00000004L),U32(0x02000004L),U32(0x00002004L),U32(0x02002004L),
U32(0x00200004L),U32(0x02200004L),U32(0x00202004L),U32(0x02202004L),
U32(0x00000400L),U32(0x02000400L),U32(0x00002400L),U32(0x02002400L),
U32(0x00200400L),U32(0x02200400L),U32(0x00202400L),U32(0x02202400L),
U32(0x00000404L),U32(0x02000404L),U32(0x00002404L),U32(0x02002404L),
U32(0x00200404L),U32(0x02200404L),U32(0x00202404L),U32(0x02202404L),
U32(0x10000000L),U32(0x12000000L),U32(0x10002000L),U32(0x12002000L),
U32(0x10200000L),U32(0x12200000L),U32(0x10202000L),U32(0x12202000L),
U32(0x10000004L),U32(0x12000004L),U32(0x10002004L),U32(0x12002004L),
U32(0x10200004L),U32(0x12200004L),U32(0x10202004L),U32(0x12202004L),
U32(0x10000400L),U32(0x12000400L),U32(0x10002400L),U32(0x12002400L),
U32(0x10200400L),U32(0x12200400L),U32(0x10202400L),U32(0x12202400L),
U32(0x10000404L),U32(0x12000404L),U32(0x10002404L),U32(0x12002404L),
U32(0x10200404L),U32(0x12200404L),U32(0x10202404L),U32(0x12202404L),
],
#for C bits (numbered as per FIPS 46) 14 15 16 17 19 20
[
U32(0x00000000L),U32(0x00000001L),U32(0x00040000L),U32(0x00040001L),
U32(0x01000000L),U32(0x01000001L),U32(0x01040000L),U32(0x01040001L),
U32(0x00000002L),U32(0x00000003L),U32(0x00040002L),U32(0x00040003L),
U32(0x01000002L),U32(0x01000003L),U32(0x01040002L),U32(0x01040003L),
U32(0x00000200L),U32(0x00000201L),U32(0x00040200L),U32(0x00040201L),
U32(0x01000200L),U32(0x01000201L),U32(0x01040200L),U32(0x01040201L),
U32(0x00000202L),U32(0x00000203L),U32(0x00040202L),U32(0x00040203L),
U32(0x01000202L),U32(0x01000203L),U32(0x01040202L),U32(0x01040203L),
U32(0x08000000L),U32(0x08000001L),U32(0x08040000L),U32(0x08040001L),
U32(0x09000000L),U32(0x09000001L),U32(0x09040000L),U32(0x09040001L),
U32(0x08000002L),U32(0x08000003L),U32(0x08040002L),U32(0x08040003L),
U32(0x09000002L),U32(0x09000003L),U32(0x09040002L),U32(0x09040003L),
U32(0x08000200L),U32(0x08000201L),U32(0x08040200L),U32(0x08040201L),
U32(0x09000200L),U32(0x09000201L),U32(0x09040200L),U32(0x09040201L),
U32(0x08000202L),U32(0x08000203L),U32(0x08040202L),U32(0x08040203L),
U32(0x09000202L),U32(0x09000203L),U32(0x09040202L),U32(0x09040203L),
],
#for C bits (numbered as per FIPS 46) 21 23 24 26 27 28
[
U32(0x00000000L),U32(0x00100000L),U32(0x00000100L),U32(0x00100100L),
U32(0x00000008L),U32(0x00100008L),U32(0x00000108L),U32(0x00100108L),
U32(0x00001000L),U32(0x00101000L),U32(0x00001100L),U32(0x00101100L),
U32(0x00001008L),U32(0x00101008L),U32(0x00001108L),U32(0x00101108L),
U32(0x04000000L),U32(0x04100000L),U32(0x04000100L),U32(0x04100100L),
U32(0x04000008L),U32(0x04100008L),U32(0x04000108L),U32(0x04100108L),
U32(0x04001000L),U32(0x04101000L),U32(0x04001100L),U32(0x04101100L),
U32(0x04001008L),U32(0x04101008L),U32(0x04001108L),U32(0x04101108L),
U32(0x00020000L),U32(0x00120000L),U32(0x00020100L),U32(0x00120100L),
U32(0x00020008L),U32(0x00120008L),U32(0x00020108L),U32(0x00120108L),
U32(0x00021000L),U32(0x00121000L),U32(0x00021100L),U32(0x00121100L),
U32(0x00021008L),U32(0x00121008L),U32(0x00021108L),U32(0x00121108L),
U32(0x04020000L),U32(0x04120000L),U32(0x04020100L),U32(0x04120100L),
U32(0x04020008L),U32(0x04120008L),U32(0x04020108L),U32(0x04120108L),
U32(0x04021000L),U32(0x04121000L),U32(0x04021100L),U32(0x04121100L),
U32(0x04021008L),U32(0x04121008L),U32(0x04021108L),U32(0x04121108L),
],
#for D bits (numbered as per FIPS 46) 1 2 3 4 5 6
[
U32(0x00000000L),U32(0x10000000L),U32(0x00010000L),U32(0x10010000L),
U32(0x00000004L),U32(0x10000004L),U32(0x00010004L),U32(0x10010004L),
U32(0x20000000L),U32(0x30000000L),U32(0x20010000L),U32(0x30010000L),
U32(0x20000004L),U32(0x30000004L),U32(0x20010004L),U32(0x30010004L),
U32(0x00100000L),U32(0x10100000L),U32(0x00110000L),U32(0x10110000L),
U32(0x00100004L),U32(0x10100004L),U32(0x00110004L),U32(0x10110004L),
U32(0x20100000L),U32(0x30100000L),U32(0x20110000L),U32(0x30110000L),
U32(0x20100004L),U32(0x30100004L),U32(0x20110004L),U32(0x30110004L),
U32(0x00001000L),U32(0x10001000L),U32(0x00011000L),U32(0x10011000L),
U32(0x00001004L),U32(0x10001004L),U32(0x00011004L),U32(0x10011004L),
U32(0x20001000L),U32(0x30001000L),U32(0x20011000L),U32(0x30011000L),
U32(0x20001004L),U32(0x30001004L),U32(0x20011004L),U32(0x30011004L),
U32(0x00101000L),U32(0x10101000L),U32(0x00111000L),U32(0x10111000L),
U32(0x00101004L),U32(0x10101004L),U32(0x00111004L),U32(0x10111004L),
U32(0x20101000L),U32(0x30101000L),U32(0x20111000L),U32(0x30111000L),
U32(0x20101004L),U32(0x30101004L),U32(0x20111004L),U32(0x30111004L),
],
#for D bits (numbered as per FIPS 46) 8 9 11 12 13 14
[
U32(0x00000000L),U32(0x08000000L),U32(0x00000008L),U32(0x08000008L),
U32(0x00000400L),U32(0x08000400L),U32(0x00000408L),U32(0x08000408L),
U32(0x00020000L),U32(0x08020000L),U32(0x00020008L),U32(0x08020008L),
U32(0x00020400L),U32(0x08020400L),U32(0x00020408L),U32(0x08020408L),
U32(0x00000001L),U32(0x08000001L),U32(0x00000009L),U32(0x08000009L),
U32(0x00000401L),U32(0x08000401L),U32(0x00000409L),U32(0x08000409L),
U32(0x00020001L),U32(0x08020001L),U32(0x00020009L),U32(0x08020009L),
U32(0x00020401L),U32(0x08020401L),U32(0x00020409L),U32(0x08020409L),
U32(0x02000000L),U32(0x0A000000L),U32(0x02000008L),U32(0x0A000008L),
U32(0x02000400L),U32(0x0A000400L),U32(0x02000408L),U32(0x0A000408L),
U32(0x02020000L),U32(0x0A020000L),U32(0x02020008L),U32(0x0A020008L),
U32(0x02020400L),U32(0x0A020400L),U32(0x02020408L),U32(0x0A020408L),
U32(0x02000001L),U32(0x0A000001L),U32(0x02000009L),U32(0x0A000009L),
U32(0x02000401L),U32(0x0A000401L),U32(0x02000409L),U32(0x0A000409L),
U32(0x02020001L),U32(0x0A020001L),U32(0x02020009L),U32(0x0A020009L),
U32(0x02020401L),U32(0x0A020401L),U32(0x02020409L),U32(0x0A020409L),
],
#for D bits (numbered as per FIPS 46) 16 17 18 19 20 21
[
U32(0x00000000L),U32(0x00000100L),U32(0x00080000L),U32(0x00080100L),
U32(0x01000000L),U32(0x01000100L),U32(0x01080000L),U32(0x01080100L),
U32(0x00000010L),U32(0x00000110L),U32(0x00080010L),U32(0x00080110L),
U32(0x01000010L),U32(0x01000110L),U32(0x01080010L),U32(0x01080110L),
U32(0x00200000L),U32(0x00200100L),U32(0x00280000L),U32(0x00280100L),
U32(0x01200000L),U32(0x01200100L),U32(0x01280000L),U32(0x01280100L),
U32(0x00200010L),U32(0x00200110L),U32(0x00280010L),U32(0x00280110L),
U32(0x01200010L),U32(0x01200110L),U32(0x01280010L),U32(0x01280110L),
U32(0x00000200L),U32(0x00000300L),U32(0x00080200L),U32(0x00080300L),
U32(0x01000200L),U32(0x01000300L),U32(0x01080200L),U32(0x01080300L),
U32(0x00000210L),U32(0x00000310L),U32(0x00080210L),U32(0x00080310L),
U32(0x01000210L),U32(0x01000310L),U32(0x01080210L),U32(0x01080310L),
U32(0x00200200L),U32(0x00200300L),U32(0x00280200L),U32(0x00280300L),
U32(0x01200200L),U32(0x01200300L),U32(0x01280200L),U32(0x01280300L),
U32(0x00200210L),U32(0x00200310L),U32(0x00280210L),U32(0x00280310L),
U32(0x01200210L),U32(0x01200310L),U32(0x01280210L),U32(0x01280310L),
],
#for D bits (numbered as per FIPS 46) 22 23 24 25 27 28
[
U32(0x00000000L),U32(0x04000000L),U32(0x00040000L),U32(0x04040000L),
U32(0x00000002L),U32(0x04000002L),U32(0x00040002L),U32(0x04040002L),
U32(0x00002000L),U32(0x04002000L),U32(0x00042000L),U32(0x04042000L),
U32(0x00002002L),U32(0x04002002L),U32(0x00042002L),U32(0x04042002L),
U32(0x00000020L),U32(0x04000020L),U32(0x00040020L),U32(0x04040020L),
U32(0x00000022L),U32(0x04000022L),U32(0x00040022L),U32(0x04040022L),
U32(0x00002020L),U32(0x04002020L),U32(0x00042020L),U32(0x04042020L),
U32(0x00002022L),U32(0x04002022L),U32(0x00042022L),U32(0x04042022L),
U32(0x00000800L),U32(0x04000800L),U32(0x00040800L),U32(0x04040800L),
U32(0x00000802L),U32(0x04000802L),U32(0x00040802L),U32(0x04040802L),
U32(0x00002800L),U32(0x04002800L),U32(0x00042800L),U32(0x04042800L),
U32(0x00002802L),U32(0x04002802L),U32(0x00042802L),U32(0x04042802L),
U32(0x00000820L),U32(0x04000820L),U32(0x00040820L),U32(0x04040820L),
U32(0x00000822L),U32(0x04000822L),U32(0x00040822L),U32(0x04040822L),
U32(0x00002820L),U32(0x04002820L),U32(0x00042820L),U32(0x04042820L),
U32(0x00002822L),U32(0x04002822L),U32(0x00042822L),U32(0x04042822L),
]
]

View File

@@ -1,466 +0,0 @@
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
import struct
import base64
import string
import des
import hashlib
import hmac
import random
from socket import gethostname
NTLM_NegotiateUnicode = 0x00000001
NTLM_NegotiateOEM = 0x00000002
NTLM_RequestTarget = 0x00000004
NTLM_Unknown9 = 0x00000008
NTLM_NegotiateSign = 0x00000010
NTLM_NegotiateSeal = 0x00000020
NTLM_NegotiateDatagram = 0x00000040
NTLM_NegotiateLanManagerKey = 0x00000080
NTLM_Unknown8 = 0x00000100
NTLM_NegotiateNTLM = 0x00000200
NTLM_NegotiateNTOnly = 0x00000400
NTLM_Anonymous = 0x00000800
NTLM_NegotiateOemDomainSupplied = 0x00001000
NTLM_NegotiateOemWorkstationSupplied = 0x00002000
NTLM_Unknown6 = 0x00004000
NTLM_NegotiateAlwaysSign = 0x00008000
NTLM_TargetTypeDomain = 0x00010000
NTLM_TargetTypeServer = 0x00020000
NTLM_TargetTypeShare = 0x00040000
NTLM_NegotiateExtendedSecurity = 0x00080000
NTLM_NegotiateIdentify = 0x00100000
NTLM_Unknown5 = 0x00200000
NTLM_RequestNonNTSessionKey = 0x00400000
NTLM_NegotiateTargetInfo = 0x00800000
NTLM_Unknown4 = 0x01000000
NTLM_NegotiateVersion = 0x02000000
NTLM_Unknown3 = 0x04000000
NTLM_Unknown2 = 0x08000000
NTLM_Unknown1 = 0x10000000
NTLM_Negotiate128 = 0x20000000
NTLM_NegotiateKeyExchange = 0x40000000
NTLM_Negotiate56 = 0x80000000
# we send these flags with our type 1 message
NTLM_TYPE1_FLAGS = (NTLM_NegotiateUnicode | \
NTLM_NegotiateOEM | \
NTLM_RequestTarget | \
NTLM_NegotiateNTLM | \
NTLM_NegotiateOemDomainSupplied | \
NTLM_NegotiateOemWorkstationSupplied | \
NTLM_NegotiateAlwaysSign | \
NTLM_NegotiateExtendedSecurity | \
NTLM_NegotiateVersion | \
NTLM_Negotiate128 | \
NTLM_Negotiate56 )
NTLM_TYPE2_FLAGS = (NTLM_NegotiateUnicode | \
NTLM_RequestTarget | \
NTLM_NegotiateNTLM | \
NTLM_NegotiateAlwaysSign | \
NTLM_NegotiateExtendedSecurity | \
NTLM_NegotiateTargetInfo | \
NTLM_NegotiateVersion | \
NTLM_Negotiate128 | \
NTLM_Negotiate56)
NTLM_MsvAvEOL = 0 # Indicates that this is the last AV_PAIR in the list. AvLen MUST be 0. This type of information MUST be present in the AV pair list.
NTLM_MsvAvNbComputerName = 1 # The server's NetBIOS computer name. The name MUST be in Unicode, and is not null-terminated. This type of information MUST be present in the AV_pair list.
NTLM_MsvAvNbDomainName = 2 # The server's NetBIOS domain name. The name MUST be in Unicode, and is not null-terminated. This type of information MUST be present in the AV_pair list.
NTLM_MsvAvDnsComputerName = 3 # The server's Active Directory DNS computer name. The name MUST be in Unicode, and is not null-terminated.
NTLM_MsvAvDnsDomainName = 4 # The server's Active Directory DNS domain name. The name MUST be in Unicode, and is not null-terminated.
NTLM_MsvAvDnsTreeName = 5 # The server's Active Directory (AD) DNS forest tree name. The name MUST be in Unicode, and is not null-terminated.
NTLM_MsvAvFlags = 6 # A field containing a 32-bit value indicating server or client configuration. 0x00000001: indicates to the client that the account authentication is constrained. 0x00000002: indicates that the client is providing message integrity in the MIC field (section 2.2.1.3) in the AUTHENTICATE_MESSAGE.
NTLM_MsvAvTimestamp = 7 # A FILETIME structure ([MS-DTYP] section 2.3.1) in little-endian byte order that contains the server local time.<12>
NTLM_MsAvRestrictions = 8 #A Restriction_Encoding structure (section 2.2.2.2). The Value field contains a structure representing the integrity level of the security principal, as well as a MachineID created at computer startup to identify the calling machine. <13>
"""
utility functions for Microsoft NTLM authentication
References:
[MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol Specification
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NLMP%5D.pdf
[MS-NTHT]: NTLM Over HTTP Protocol Specification
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NTHT%5D.pdf
Cntlm Authentication Proxy
http://cntlm.awk.cz/
NTLM Authorization Proxy Server
http://sourceforge.net/projects/ntlmaps/
Optimized Attack for NTLM2 Session Response
http://www.blackhat.com/presentations/bh-asia-04/bh-jp-04-pdfs/bh-jp-04-seki.pdf
"""
def dump_NegotiateFlags(NegotiateFlags):
if NegotiateFlags & NTLM_NegotiateUnicode:
print "NTLM_NegotiateUnicode set"
if NegotiateFlags & NTLM_NegotiateOEM:
print "NTLM_NegotiateOEM set"
if NegotiateFlags & NTLM_RequestTarget:
print "NTLM_RequestTarget set"
if NegotiateFlags & NTLM_Unknown9:
print "NTLM_Unknown9 set"
if NegotiateFlags & NTLM_NegotiateSign:
print "NTLM_NegotiateSign set"
if NegotiateFlags & NTLM_NegotiateSeal:
print "NTLM_NegotiateSeal set"
if NegotiateFlags & NTLM_NegotiateDatagram:
print "NTLM_NegotiateDatagram set"
if NegotiateFlags & NTLM_NegotiateLanManagerKey:
print "NTLM_NegotiateLanManagerKey set"
if NegotiateFlags & NTLM_Unknown8:
print "NTLM_Unknown8 set"
if NegotiateFlags & NTLM_NegotiateNTLM:
print "NTLM_NegotiateNTLM set"
if NegotiateFlags & NTLM_NegotiateNTOnly:
print "NTLM_NegotiateNTOnly set"
if NegotiateFlags & NTLM_Anonymous:
print "NTLM_Anonymous set"
if NegotiateFlags & NTLM_NegotiateOemDomainSupplied:
print "NTLM_NegotiateOemDomainSupplied set"
if NegotiateFlags & NTLM_NegotiateOemWorkstationSupplied:
print "NTLM_NegotiateOemWorkstationSupplied set"
if NegotiateFlags & NTLM_Unknown6:
print "NTLM_Unknown6 set"
if NegotiateFlags & NTLM_NegotiateAlwaysSign:
print "NTLM_NegotiateAlwaysSign set"
if NegotiateFlags & NTLM_TargetTypeDomain:
print "NTLM_TargetTypeDomain set"
if NegotiateFlags & NTLM_TargetTypeServer:
print "NTLM_TargetTypeServer set"
if NegotiateFlags & NTLM_TargetTypeShare:
print "NTLM_TargetTypeShare set"
if NegotiateFlags & NTLM_NegotiateExtendedSecurity:
print "NTLM_NegotiateExtendedSecurity set"
if NegotiateFlags & NTLM_NegotiateIdentify:
print "NTLM_NegotiateIdentify set"
if NegotiateFlags & NTLM_Unknown5:
print "NTLM_Unknown5 set"
if NegotiateFlags & NTLM_RequestNonNTSessionKey:
print "NTLM_RequestNonNTSessionKey set"
if NegotiateFlags & NTLM_NegotiateTargetInfo:
print "NTLM_NegotiateTargetInfo set"
if NegotiateFlags & NTLM_Unknown4:
print "NTLM_Unknown4 set"
if NegotiateFlags & NTLM_NegotiateVersion:
print "NTLM_NegotiateVersion set"
if NegotiateFlags & NTLM_Unknown3:
print "NTLM_Unknown3 set"
if NegotiateFlags & NTLM_Unknown2:
print "NTLM_Unknown2 set"
if NegotiateFlags & NTLM_Unknown1:
print "NTLM_Unknown1 set"
if NegotiateFlags & NTLM_Negotiate128:
print "NTLM_Negotiate128 set"
if NegotiateFlags & NTLM_NegotiateKeyExchange:
print "NTLM_NegotiateKeyExchange set"
if NegotiateFlags & NTLM_Negotiate56:
print "NTLM_Negotiate56 set"
def create_NTLM_NEGOTIATE_MESSAGE(user, type1_flags=NTLM_TYPE1_FLAGS):
BODY_LENGTH = 40
Payload_start = BODY_LENGTH # in bytes
protocol = 'NTLMSSP\0' #name
type = struct.pack('<I',1) #type 1
flags = struct.pack('<I', type1_flags)
Workstation = gethostname().upper().encode('ascii')
user_parts = user.split('\\', 1)
if type1_flags & NTLM_NegotiateOemDomainSupplied:
DomainName = user_parts[0].upper().encode('ascii')
else:
DomainName = ''
EncryptedRandomSessionKey = ""
WorkstationLen = struct.pack('<H', len(Workstation))
WorkstationMaxLen = struct.pack('<H', len(Workstation))
WorkstationBufferOffset = struct.pack('<I', Payload_start)
Payload_start += len(Workstation)
DomainNameLen = struct.pack('<H', len(DomainName))
DomainNameMaxLen = struct.pack('<H', len(DomainName))
DomainNameBufferOffset = struct.pack('<I',Payload_start)
Payload_start += len(DomainName)
ProductMajorVersion = struct.pack('<B', 5)
ProductMinorVersion = struct.pack('<B', 1)
ProductBuild = struct.pack('<H', 2600)
VersionReserved1 = struct.pack('<B', 0)
VersionReserved2 = struct.pack('<B', 0)
VersionReserved3 = struct.pack('<B', 0)
NTLMRevisionCurrent = struct.pack('<B', 15)
msg1 = protocol + type + flags + \
DomainNameLen + DomainNameMaxLen + DomainNameBufferOffset + \
WorkstationLen + WorkstationMaxLen + WorkstationBufferOffset + \
ProductMajorVersion + ProductMinorVersion + ProductBuild + \
VersionReserved1 + VersionReserved2 + VersionReserved3 + NTLMRevisionCurrent
assert BODY_LENGTH==len(msg1), "BODY_LENGTH: %d != msg1: %d" % (BODY_LENGTH,len(msg1))
msg1 += Workstation + DomainName
msg1 = base64.encodestring(msg1)
msg1 = string.replace(msg1, '\n', '')
return msg1
def parse_NTLM_CHALLENGE_MESSAGE(msg2):
""
msg2 = base64.decodestring(msg2)
Signature = msg2[0:8]
msg_type = struct.unpack("<I",msg2[8:12])[0]
assert(msg_type==2)
TargetNameLen = struct.unpack("<H",msg2[12:14])[0]
TargetNameMaxLen = struct.unpack("<H",msg2[14:16])[0]
TargetNameOffset = struct.unpack("<I",msg2[16:20])[0]
TargetName = msg2[TargetNameOffset:TargetNameOffset+TargetNameMaxLen]
NegotiateFlags = struct.unpack("<I",msg2[20:24])[0]
ServerChallenge = msg2[24:32]
Reserved = msg2[32:40]
# Fixes some NTLM auth that don't include the target info
# I have no idea if such a server is broken or not, but
# this helped with my testing
if TargetNameOffset > 40:
TargetInfoLen = struct.unpack("<H",msg2[40:42])[0]
TargetInfoMaxLen = struct.unpack("<H",msg2[42:44])[0]
TargetInfoOffset = struct.unpack("<I",msg2[44:48])[0]
TargetInfo = msg2[TargetInfoOffset:TargetInfoOffset+TargetInfoLen]
i=0
TimeStamp = '\0'*8
while(i<TargetInfoLen):
AvId = struct.unpack("<H",TargetInfo[i:i+2])[0]
AvLen = struct.unpack("<H",TargetInfo[i+2:i+4])[0]
AvValue = TargetInfo[i+4:i+4+AvLen]
i = i+4+AvLen
if AvId == NTLM_MsvAvTimestamp:
TimeStamp = AvValue
#~ print AvId, AvValue.decode('utf-16')
return (ServerChallenge, NegotiateFlags)
def create_NTLM_AUTHENTICATE_MESSAGE(nonce, user, domain, password, NegotiateFlags):
""
is_unicode = NegotiateFlags & NTLM_NegotiateUnicode
is_NegotiateExtendedSecurity = NegotiateFlags & NTLM_NegotiateExtendedSecurity
flags = struct.pack('<I',NTLM_TYPE2_FLAGS)
BODY_LENGTH = 72
Payload_start = BODY_LENGTH # in bytes
Workstation = gethostname().upper()
DomainName = domain.upper()
UserName = user
EncryptedRandomSessionKey = ""
if is_unicode:
Workstation = Workstation.encode('utf-16-le')
DomainName = DomainName.encode('utf-16-le')
UserName = UserName.encode('utf-16-le')
EncryptedRandomSessionKey = EncryptedRandomSessionKey.encode('utf-16-le')
LmChallengeResponse = calc_resp(create_LM_hashed_password_v1(password), nonce)
NtChallengeResponse = calc_resp(create_NT_hashed_password_v1(password), nonce)
if is_NegotiateExtendedSecurity:
pwhash = create_NT_hashed_password_v1(password, UserName, DomainName)
ClientChallenge = ""
for i in range(8):
ClientChallenge+= chr(random.getrandbits(8))
(NtChallengeResponse, LmChallengeResponse) = ntlm2sr_calc_resp(pwhash, nonce, ClientChallenge) #='\x39 e3 f4 cd 59 c5 d8 60')
Signature = 'NTLMSSP\0'
MessageType = struct.pack('<I',3) #type 3
DomainNameLen = struct.pack('<H', len(DomainName))
DomainNameMaxLen = struct.pack('<H', len(DomainName))
DomainNameOffset = struct.pack('<I', Payload_start)
Payload_start += len(DomainName)
UserNameLen = struct.pack('<H', len(UserName))
UserNameMaxLen = struct.pack('<H', len(UserName))
UserNameOffset = struct.pack('<I', Payload_start)
Payload_start += len(UserName)
WorkstationLen = struct.pack('<H', len(Workstation))
WorkstationMaxLen = struct.pack('<H', len(Workstation))
WorkstationOffset = struct.pack('<I', Payload_start)
Payload_start += len(Workstation)
LmChallengeResponseLen = struct.pack('<H', len(LmChallengeResponse))
LmChallengeResponseMaxLen = struct.pack('<H', len(LmChallengeResponse))
LmChallengeResponseOffset = struct.pack('<I', Payload_start)
Payload_start += len(LmChallengeResponse)
NtChallengeResponseLen = struct.pack('<H', len(NtChallengeResponse))
NtChallengeResponseMaxLen = struct.pack('<H', len(NtChallengeResponse))
NtChallengeResponseOffset = struct.pack('<I', Payload_start)
Payload_start += len(NtChallengeResponse)
EncryptedRandomSessionKeyLen = struct.pack('<H', len(EncryptedRandomSessionKey))
EncryptedRandomSessionKeyMaxLen = struct.pack('<H', len(EncryptedRandomSessionKey))
EncryptedRandomSessionKeyOffset = struct.pack('<I',Payload_start)
Payload_start += len(EncryptedRandomSessionKey)
NegotiateFlags = flags
ProductMajorVersion = struct.pack('<B', 5)
ProductMinorVersion = struct.pack('<B', 1)
ProductBuild = struct.pack('<H', 2600)
VersionReserved1 = struct.pack('<B', 0)
VersionReserved2 = struct.pack('<B', 0)
VersionReserved3 = struct.pack('<B', 0)
NTLMRevisionCurrent = struct.pack('<B', 15)
MIC = struct.pack('<IIII',0,0,0,0)
msg3 = Signature + MessageType + \
LmChallengeResponseLen + LmChallengeResponseMaxLen + LmChallengeResponseOffset + \
NtChallengeResponseLen + NtChallengeResponseMaxLen + NtChallengeResponseOffset + \
DomainNameLen + DomainNameMaxLen + DomainNameOffset + \
UserNameLen + UserNameMaxLen + UserNameOffset + \
WorkstationLen + WorkstationMaxLen + WorkstationOffset + \
EncryptedRandomSessionKeyLen + EncryptedRandomSessionKeyMaxLen + EncryptedRandomSessionKeyOffset + \
NegotiateFlags + \
ProductMajorVersion + ProductMinorVersion + ProductBuild + \
VersionReserved1 + VersionReserved2 + VersionReserved3 + NTLMRevisionCurrent
assert BODY_LENGTH==len(msg3), "BODY_LENGTH: %d != msg3: %d" % (BODY_LENGTH,len(msg3))
Payload = DomainName + UserName + Workstation + LmChallengeResponse + NtChallengeResponse + EncryptedRandomSessionKey
msg3 += Payload
msg3 = base64.encodestring(msg3)
msg3 = string.replace(msg3, '\n', '')
return msg3
def calc_resp(password_hash, server_challenge):
"""calc_resp generates the LM response given a 16-byte password hash and the
challenge from the Type-2 message.
@param password_hash
16-byte password hash
@param server_challenge
8-byte challenge from Type-2 message
returns
24-byte buffer to contain the LM response upon return
"""
# padding with zeros to make the hash 21 bytes long
password_hash = password_hash + '\0' * (21 - len(password_hash))
res = ''
dobj = des.DES(password_hash[0:7])
res = res + dobj.encrypt(server_challenge[0:8])
dobj = des.DES(password_hash[7:14])
res = res + dobj.encrypt(server_challenge[0:8])
dobj = des.DES(password_hash[14:21])
res = res + dobj.encrypt(server_challenge[0:8])
return res
def ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ServerName, ClientChallenge='\xaa'*8, Time='\0'*8):
LmChallengeResponse = hmac.new(ResponseKeyLM, ServerChallenge+ClientChallenge).digest() + ClientChallenge
Responserversion = '\x01'
HiResponserversion = '\x01'
temp = Responserversion + HiResponserversion + '\0'*6 + Time + ClientChallenge + '\0'*4 + ServerChallenge + '\0'*4
NTProofStr = hmac.new(ResponseKeyNT, ServerChallenge + temp).digest()
NtChallengeResponse = NTProofStr + temp
SessionBaseKey = hmac.new(ResponseKeyNT, NTProofStr).digest()
return (NtChallengeResponse, LmChallengeResponse)
def ntlm2sr_calc_resp(ResponseKeyNT, ServerChallenge, ClientChallenge='\xaa'*8):
import hashlib
LmChallengeResponse = ClientChallenge + '\0'*16
sess = hashlib.md5(ServerChallenge+ClientChallenge).digest()
NtChallengeResponse = calc_resp(ResponseKeyNT, sess[0:8])
return (NtChallengeResponse, LmChallengeResponse)
def create_LM_hashed_password_v1(passwd):
"setup LanManager password"
"create LanManager hashed password"
# fix the password length to 14 bytes
passwd = string.upper(passwd)
lm_pw = passwd + '\0' * (14 - len(passwd))
lm_pw = passwd[0:14]
# do hash
magic_str = "KGS!@#$%" # page 57 in [MS-NLMP]
res = ''
dobj = des.DES(lm_pw[0:7])
res = res + dobj.encrypt(magic_str)
dobj = des.DES(lm_pw[7:14])
res = res + dobj.encrypt(magic_str)
return res
def create_NT_hashed_password_v1(passwd, user=None, domain=None):
"create NT hashed password"
digest = hashlib.new('md4', passwd.encode('utf-16le')).digest()
return digest
def create_NT_hashed_password_v2(passwd, user, domain):
"create NT hashed password"
digest = create_NT_hashed_password_v1(passwd)
return hmac.new(digest, (user.upper()+domain).encode('utf-16le')).digest()
return digest
def create_sessionbasekey(password):
return hashlib.new('md4', create_NT_hashed_password_v1(password)).digest()
if __name__ == "__main__":
def ByteToHex( byteStr ):
"""
Convert a byte string to it's hex string representation e.g. for output.
"""
return ' '.join( [ "%02X" % ord( x ) for x in byteStr ] )
def HexToByte( hexStr ):
"""
Convert a string hex byte values into a byte string. The Hex Byte values may
or may not be space separated.
"""
bytes = []
hexStr = ''.join( hexStr.split(" ") )
for i in range(0, len(hexStr), 2):
bytes.append( chr( int (hexStr[i:i+2], 16 ) ) )
return ''.join( bytes )
ServerChallenge = HexToByte("01 23 45 67 89 ab cd ef")
ClientChallenge = '\xaa'*8
Time = '\x00'*8
Workstation = "COMPUTER".encode('utf-16-le')
ServerName = "Server".encode('utf-16-le')
User = "User"
Domain = "Domain"
Password = "Password"
RandomSessionKey = '\55'*16
assert HexToByte("e5 2c ac 67 41 9a 9a 22 4a 3b 10 8f 3f a6 cb 6d") == create_LM_hashed_password_v1(Password) # [MS-NLMP] page 72
assert HexToByte("a4 f4 9c 40 65 10 bd ca b6 82 4e e7 c3 0f d8 52") == create_NT_hashed_password_v1(Password) # [MS-NLMP] page 73
assert HexToByte("d8 72 62 b0 cd e4 b1 cb 74 99 be cc cd f1 07 84") == create_sessionbasekey(Password)
assert HexToByte("67 c4 30 11 f3 02 98 a2 ad 35 ec e6 4f 16 33 1c 44 bd be d9 27 84 1f 94") == calc_resp(create_NT_hashed_password_v1(Password), ServerChallenge)
assert HexToByte("98 de f7 b8 7f 88 aa 5d af e2 df 77 96 88 a1 72 de f1 1c 7d 5c cd ef 13") == calc_resp(create_LM_hashed_password_v1(Password), ServerChallenge)
(NTLMv1Response,LMv1Response) = ntlm2sr_calc_resp(create_NT_hashed_password_v1(Password), ServerChallenge, ClientChallenge)
assert HexToByte("aa aa aa aa aa aa aa aa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00") == LMv1Response # [MS-NLMP] page 75
assert HexToByte("75 37 f8 03 ae 36 71 28 ca 45 82 04 bd e7 ca f8 1e 97 ed 26 83 26 72 32") == NTLMv1Response
assert HexToByte("0c 86 8a 40 3b fd 7a 93 a3 00 1e f2 2e f0 2e 3f") == create_NT_hashed_password_v2(Password, User, Domain) # [MS-NLMP] page 76
ResponseKeyLM = ResponseKeyNT = create_NT_hashed_password_v2(Password, User, Domain)
(NTLMv2Response,LMv2Response) = ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ServerName, ClientChallenge, Time)
assert HexToByte("86 c3 50 97 ac 9c ec 10 25 54 76 4a 57 cc cc 19 aa aa aa aa aa aa aa aa") == LMv2Response # [MS-NLMP] page 76
# expected failure
# According to the spec in section '3.3.2 NTLM v2 Authentication' the NTLMv2Response should be longer than the value given on page 77 (this suggests a mistake in the spec)
#~ assert HexToByte("68 cd 0a b8 51 e5 1c 96 aa bc 92 7b eb ef 6a 1c") == NTLMv2Response, "\nExpected: 68 cd 0a b8 51 e5 1c 96 aa bc 92 7b eb ef 6a 1c\nActual: %s" % ByteToHex(NTLMv2Response) # [MS-NLMP] page 77

View File

@@ -1,4 +1,5 @@
{
"1.3.0": "messages/1.3.0.txt",
"1.6.0": "messages/1.6.0.txt"
}
"1.6.0": "messages/1.6.0.txt",
"2.0.0": "messages/2.0.0.txt"
}

View File

@@ -0,0 +1,64 @@
Package Control 2.0.0 Changelog:
Today I'd like to announce two big milestones:
- Package Control 2.0 for ST2 and ST3
- A new Package Control website at https://sublime.wbond.net
The full announcement about the PC 2.0 release is available on the news page at
https://sublime.wbond.net/news.
If you are running the "testing" version of Package Control (1.6.9 - 1.6.11),
you will likely need to restart Sublime Text before Package Control will work
properly.
Giving Back
Part of the new Package Control website is in-depth information about each
package. The new package pages include a link where you can give a tip to the
developer/maintainer of your favorite packages.
The donate links go to https://www.gittip.com, which is building an excellent,
and open platform for users to say "thank you" to open source developers. It
is possible to give a small amount each week, such as $0.25, however these small
amounts multiplied by the large size of the community can be a big thank you!
One of the less glamorous jobs involved with making Package Control happen is
reviewing and giving package developers feedback before adding their packages
to the default channel. The follow contributors deserve a big thank you:
FichteFoll - https://www.gittip.com/FichteFoll/
joneshf - https://www.gittip.com/on/github/joneshf/
sentience - https://www.gittip.com/on/github/sentience/
Finally, I'm looking to raise some money to obtain a Mac Mini for the purposes
of supporting ST3 on OS X and a license for a Windows 8 VM. If you are inclined
to donate to those, or want to just buy me a beer, check out:
https://sublime.wbond.net/say_thanks
Notable Features
- A new Windows downloader that uses WinINet and should provide much better
proxy support
- Using operating system-supplied SSL CA certs on all platforms, with a
deprecated fallback to certificates served through the channel
- Proxy server fixes for OS X
- A completely revamped channel and repository system with support for more
information about packages including labels; readme, issues, donate and buy
URLs; tag-based releases; platform targetting without a custom packages.json
file; and Sublime Text version targetting
- Support for installing via .sublime-package files in ST3, which allows users
to easily override specific files from the package. Package developers who
need a loose folder of files may include a .no-sublime-package file in their
repo.
- In the coming days the new Package Control website will be released as open
source on GitHub

View File

@@ -1,5 +1,5 @@
{
"version": "1.6.3",
"url": "http://wbond.net/sublime_packages/package_control",
"version": "2.0.1-beta1",
"url": "https://sublime.wbond.net",
"description": "A full-featured package manager"
}
}

View File

@@ -0,0 +1,2 @@
__version__ = "2.0.1-beta1"
__version_info__ = (2, 0, 1, 'beta1')

View File

@@ -0,0 +1,215 @@
import threading
import re
import os
import datetime
import time
import sublime
from .console_write import console_write
from .package_installer import PackageInstaller
from .package_renamer import PackageRenamer
from .open_compat import open_compat, read_compat
class AutomaticUpgrader(threading.Thread):
"""
Automatically checks for updated packages and installs them. controlled
by the `auto_upgrade`, `auto_upgrade_ignore`, and `auto_upgrade_frequency`
settings.
"""
def __init__(self, found_packages):
"""
:param found_packages:
A list of package names for the packages that were found to be
installed on the machine.
"""
self.installer = PackageInstaller()
self.manager = self.installer.manager
self.load_settings()
self.package_renamer = PackageRenamer()
self.package_renamer.load_settings()
self.auto_upgrade = self.settings.get('auto_upgrade')
self.auto_upgrade_ignore = self.settings.get('auto_upgrade_ignore')
self.load_last_run()
self.determine_next_run()
# Detect if a package is missing that should be installed
self.missing_packages = list(set(self.installed_packages) -
set(found_packages))
if self.auto_upgrade and self.next_run <= time.time():
self.save_last_run(time.time())
threading.Thread.__init__(self)
def load_last_run(self):
"""
Loads the last run time from disk into memory
"""
self.last_run = None
self.last_run_file = os.path.join(sublime.packages_path(), 'User',
'Package Control.last-run')
if os.path.isfile(self.last_run_file):
with open_compat(self.last_run_file) as fobj:
try:
self.last_run = int(read_compat(fobj))
except ValueError:
pass
def determine_next_run(self):
"""
Figure out when the next run should happen
"""
self.next_run = int(time.time())
frequency = self.settings.get('auto_upgrade_frequency')
if frequency:
if self.last_run:
self.next_run = int(self.last_run) + (frequency * 60 * 60)
else:
self.next_run = time.time()
def save_last_run(self, last_run):
"""
Saves a record of when the last run was
:param last_run:
The unix timestamp of when to record the last run as
"""
with open_compat(self.last_run_file, 'w') as fobj:
fobj.write(str(int(last_run)))
def load_settings(self):
"""
Loads the list of installed packages from the
Package Control.sublime-settings file
"""
self.settings_file = 'Package Control.sublime-settings'
self.settings = sublime.load_settings(self.settings_file)
self.installed_packages = self.settings.get('installed_packages', [])
self.should_install_missing = self.settings.get('install_missing')
if not isinstance(self.installed_packages, list):
self.installed_packages = []
def run(self):
self.install_missing()
if self.next_run > time.time():
self.print_skip()
return
self.upgrade_packages()
def install_missing(self):
"""
Installs all packages that were listed in the list of
`installed_packages` from Package Control.sublime-settings but were not
found on the filesystem and passed as `found_packages`.
"""
if not self.missing_packages or not self.should_install_missing:
return
console_write(u'Installing %s missing packages' % len(self.missing_packages), True)
for package in self.missing_packages:
if self.installer.manager.install_package(package):
console_write(u'Installed missing package %s' % package, True)
def print_skip(self):
"""
Prints a notice in the console if the automatic upgrade is skipped
due to already having been run in the last `auto_upgrade_frequency`
hours.
"""
last_run = datetime.datetime.fromtimestamp(self.last_run)
next_run = datetime.datetime.fromtimestamp(self.next_run)
date_format = '%Y-%m-%d %H:%M:%S'
message_string = u'Skipping automatic upgrade, last run at %s, next run at %s or after' % (
last_run.strftime(date_format), next_run.strftime(date_format))
console_write(message_string, True)
def upgrade_packages(self):
"""
Upgrades all packages that are not currently upgraded to the lastest
version. Also renames any installed packages to their new names.
"""
if not self.auto_upgrade:
return
self.package_renamer.rename_packages(self.installer)
package_list = self.installer.make_package_list(['install',
'reinstall', 'downgrade', 'overwrite', 'none'],
ignore_packages=self.auto_upgrade_ignore)
# If Package Control is being upgraded, just do that and restart
for package in package_list:
if package[0] != 'Package Control':
continue
def reset_last_run():
# Re-save the last run time so it runs again after PC has
# been updated
self.save_last_run(self.last_run)
sublime.set_timeout(reset_last_run, 1)
package_list = [package]
break
if not package_list:
console_write(u'No updated packages', True)
return
console_write(u'Installing %s upgrades' % len(package_list), True)
disabled_packages = []
def do_upgrades():
# Wait so that the ignored packages can be "unloaded"
time.sleep(0.5)
# We use a function to generate the on-complete lambda because if
# we don't, the lambda will bind to info at the current scope, and
# thus use the last value of info from the loop
def make_on_complete(name):
return lambda: self.installer.reenable_package(name)
for info in package_list:
if info[0] in disabled_packages:
on_complete = make_on_complete(info[0])
else:
on_complete = None
self.installer.manager.install_package(info[0])
version = re.sub('^.*?(v[\d\.]+).*?$', '\\1', info[2])
if version == info[2] and version.find('pull with') != -1:
vcs = re.sub('^pull with (\w+).*?$', '\\1', version)
version = 'latest %s commit' % vcs
message_string = u'Upgraded %s to %s' % (info[0], version)
console_write(message_string, True)
if on_complete:
sublime.set_timeout(on_complete, 1)
# Disabling a package means changing settings, which can only be done
# in the main thread. We then create a new background thread so that
# the upgrade process does not block the UI.
def disable_packages():
disabled_packages.extend(self.installer.disable_packages([info[0] for info in package_list]))
threading.Thread(target=do_upgrades).start()
sublime.set_timeout(disable_packages, 1)

View File

@@ -0,0 +1,378 @@
import hashlib
import os
import re
import time
import sys
from .cmd import Cli
from .console_write import console_write
from .open_compat import open_compat, read_compat
# Have somewhere to store the CA bundle, even when not running in Sublime Text
try:
import sublime
ca_bundle_dir = None
except (ImportError):
ca_bundle_dir = os.path.join(os.path.expanduser('~'), '.package_control')
if not os.path.exists(ca_bundle_dir):
os.mkdir(ca_bundle_dir)
def find_root_ca_cert(settings, domain):
runner = OpensslCli(settings.get('openssl_binary'), settings.get('debug'))
binary = runner.retrieve_binary()
args = [binary, 's_client', '-showcerts', '-connect', domain + ':443']
result = runner.execute(args, os.path.dirname(binary))
certs = []
temp = []
in_block = False
for line in result.splitlines():
if line.find('BEGIN CERTIFICATE') != -1:
in_block = True
if in_block:
temp.append(line)
if line.find('END CERTIFICATE') != -1:
in_block = False
certs.append(u"\n".join(temp))
temp = []
# Remove the cert for the domain itself, just leaving the
# chain cert and the CA cert
certs.pop(0)
# Look for the "parent" root CA cert
subject = openssl_get_cert_subject(settings, certs[-1])
issuer = openssl_get_cert_issuer(settings, certs[-1])
cert = get_ca_cert_by_subject(settings, issuer)
cert_hash = hashlib.md5(cert.encode('utf-8')).hexdigest()
return [cert, cert_hash]
def get_system_ca_bundle_path(settings):
"""
Get the filesystem path to the system CA bundle. On Linux it looks in a
number of predefined places, however on OS X it has to be programatically
exported from the SystemRootCertificates.keychain. Windows does not ship
with a CA bundle, but also we use WinINet on Windows, so we don't need to
worry about CA certs.
:param settings:
A dict to look in for `debug` and `openssl_binary` keys
:return:
The full filesystem path to the .ca-bundle file, or False on error
"""
# If the sublime module is available, we bind this value at run time
# since the sublime.packages_path() is not available at import time
global ca_bundle_dir
platform = sys.platform
debug = settings.get('debug')
ca_path = False
if platform == 'win32':
console_write(u"Unable to get system CA cert path since Windows does not ship with them", True)
return False
# OS X
if platform == 'darwin':
if not ca_bundle_dir:
ca_bundle_dir = os.path.join(sublime.packages_path(), 'User')
ca_path = os.path.join(ca_bundle_dir, 'Package Control.system-ca-bundle')
exists = os.path.exists(ca_path)
# The bundle is old if it is a week or more out of date
is_old = exists and os.stat(ca_path).st_mtime < time.time() - 604800
if not exists or is_old:
if debug:
console_write(u"Generating new CA bundle from system keychain", True)
_osx_create_ca_bundle(settings, ca_path)
if debug:
console_write(u"Finished generating new CA bundle at %s" % ca_path, True)
elif debug:
console_write(u"Found previously exported CA bundle at %s" % ca_path, True)
# Linux
else:
# Common CA cert paths
paths = [
'/usr/lib/ssl/certs/ca-certificates.crt',
'/etc/ssl/certs/ca-certificates.crt',
'/etc/pki/tls/certs/ca-bundle.crt',
'/etc/ssl/ca-bundle.pem'
]
for path in paths:
if os.path.exists(path):
ca_path = path
break
if debug and ca_path:
console_write(u"Found system CA bundle at %s" % ca_path, True)
return ca_path
def get_ca_cert_by_subject(settings, subject):
bundle_path = get_system_ca_bundle_path(settings)
with open_compat(bundle_path, 'r') as f:
contents = read_compat(f)
temp = []
in_block = False
for line in contents.splitlines():
if line.find('BEGIN CERTIFICATE') != -1:
in_block = True
if in_block:
temp.append(line)
if line.find('END CERTIFICATE') != -1:
in_block = False
cert = u"\n".join(temp)
temp = []
if openssl_get_cert_subject(settings, cert) == subject:
return cert
return False
def openssl_get_cert_issuer(settings, cert):
"""
Uses the openssl command line client to extract the issuer of an x509
certificate.
:param settings:
A dict to look in for `debug` and `openssl_binary` keys
:param cert:
A string containing the PEM-encoded x509 certificate to extract the
issuer from
:return:
The cert issuer
"""
runner = OpensslCli(settings.get('openssl_binary'), settings.get('debug'))
binary = runner.retrieve_binary()
args = [binary, 'x509', '-noout', '-issuer']
output = runner.execute(args, os.path.dirname(binary), cert)
return re.sub('^issuer=\s*', '', output)
def openssl_get_cert_name(settings, cert):
"""
Uses the openssl command line client to extract the name of an x509
certificate. If the commonName is set, that is used, otherwise the first
organizationalUnitName is used. This mirrors what OS X uses for storing
trust preferences.
:param settings:
A dict to look in for `debug` and `openssl_binary` keys
:param cert:
A string containing the PEM-encoded x509 certificate to extract the
name from
:return:
The cert subject name, which is the commonName (if available), or the
first organizationalUnitName
"""
runner = OpensslCli(settings.get('openssl_binary'), settings.get('debug'))
binary = runner.retrieve_binary()
args = [binary, 'x509', '-noout', '-subject', '-nameopt',
'sep_multiline,lname,utf8']
result = runner.execute(args, os.path.dirname(binary), cert)
# First look for the common name
cn = None
# If there is no common name for the cert, the trust prefs use the first
# orginizational unit name
first_ou = None
for line in result.splitlines():
match = re.match('^\s+commonName=(.*)$', line)
if match:
cn = match.group(1)
break
match = re.match('^\s+organizationalUnitName=(.*)$', line)
if first_ou is None and match:
first_ou = match.group(1)
continue
# This is the name of the cert that would be used in the trust prefs
return cn or first_ou
def openssl_get_cert_subject(settings, cert):
"""
Uses the openssl command line client to extract the subject of an x509
certificate.
:param settings:
A dict to look in for `debug` and `openssl_binary` keys
:param cert:
A string containing the PEM-encoded x509 certificate to extract the
subject from
:return:
The cert subject
"""
runner = OpensslCli(settings.get('openssl_binary'), settings.get('debug'))
binary = runner.retrieve_binary()
args = [binary, 'x509', '-noout', '-subject']
output = runner.execute(args, os.path.dirname(binary), cert)
return re.sub('^subject=\s*', '', output)
def _osx_create_ca_bundle(settings, destination):
"""
Uses the OS X `security` command line tool to export the system's list of
CA certs from /System/Library/Keychains/SystemRootCertificates.keychain.
Checks the cert names against the trust preferences, ensuring that
distrusted certs are not exported.
:param settings:
A dict to look in for `debug` and `openssl_binary` keys
:param destination:
The full filesystem path to the destination .ca-bundle file
"""
distrusted_certs = _osx_get_distrusted_certs(settings)
# Export the root certs
args = ['/usr/bin/security', 'export', '-k',
'/System/Library/Keychains/SystemRootCertificates.keychain', '-t',
'certs', '-p']
result = Cli(None, settings.get('debug')).execute(args, '/usr/bin')
certs = []
temp = []
in_block = False
for line in result.splitlines():
if line.find('BEGIN CERTIFICATE') != -1:
in_block = True
if in_block:
temp.append(line)
if line.find('END CERTIFICATE') != -1:
in_block = False
cert = u"\n".join(temp)
temp = []
if distrusted_certs:
# If it is a distrusted cert, we move on to the next
cert_name = openssl_get_cert_name(settings, cert)
if cert_name in distrusted_certs:
if settings.get('debug'):
console_write(u'Skipping root certficate %s because it is distrusted' % cert_name, True)
continue
certs.append(cert)
with open_compat(destination, 'w') as f:
f.write(u"\n".join(certs))
def _osx_get_distrusted_certs(settings):
"""
Uses the OS X `security` binary to get a list of admin trust settings,
which is what is set when a user changes the trust setting on a root
certificate. By looking at the SSL policy, we can properly exclude
distrusted certs from out export.
Tested on OS X 10.6 and 10.8
:param settings:
A dict to look in for `debug` key
:return:
A list of CA cert names, where the name is the commonName (if
available), or the first organizationalUnitName
"""
args = ['/usr/bin/security', 'dump-trust-settings', '-d']
result = Cli(None, settings.get('debug')).execute(args, '/usr/bin')
distrusted_certs = []
cert_name = None
ssl_policy = False
for line in result.splitlines():
if line == '':
continue
# Reset for each cert
match = re.match('Cert\s+\d+:\s+(.*)$', line)
if match:
cert_name = match.group(1)
continue
# Reset for each trust setting
if re.match('^\s+Trust\s+Setting\s+\d+:', line):
ssl_policy = False
continue
# We are only interested in SSL policies
if re.match('^\s+Policy\s+OID\s+:\s+SSL', line):
ssl_policy = True
continue
distrusted = re.match('^\s+Result\s+Type\s+:\s+kSecTrustSettingsResultDeny', line)
if ssl_policy and distrusted and cert_name not in distrusted_certs:
if settings.get('debug'):
console_write(u'Found SSL distrust setting for root certificate %s' % cert_name, True)
distrusted_certs.append(cert_name)
return distrusted_certs
class OpensslCli(Cli):
cli_name = 'openssl'
def retrieve_binary(self):
"""
Returns the path to the openssl executable
:return: The string path to the executable or False on error
"""
name = 'openssl'
if os.name == 'nt':
name += '.exe'
binary = self.find_binary(name)
if binary and os.path.isdir(binary):
full_path = os.path.join(binary, name)
if os.path.exists(full_path):
binary = full_path
if not binary:
show_error((u'Unable to find %s. Please set the openssl_binary ' +
u'setting by accessing the Preferences > Package Settings > ' +
u'Package Control > Settings \u2013 User menu entry. The ' +
u'Settings \u2013 Default entry can be used for reference, ' +
u'but changes to that will be overwritten upon next upgrade.') % name)
return False
return binary

View File

@@ -0,0 +1,173 @@
import time
# A cache of channel and repository info to allow users to install multiple
# packages without having to wait for the metadata to be downloaded more
# than once. The keys are managed locally by the utilizing code.
_channel_repository_cache = {}
def clear_cache():
global _channel_repository_cache
_channel_repository_cache = {}
def get_cache(key, default=None):
"""
Gets an in-memory cache value
:param key:
The string key
:param default:
The value to return if the key has not been set, or the ttl expired
:return:
The cached value, or default
"""
struct = _channel_repository_cache.get(key, {})
expires = struct.get('expires')
if expires and expires > time.time():
return struct.get('data')
return default
def merge_cache_over_settings(destination, setting, key_prefix):
"""
Take the cached value of `key` and put it into the key `setting` of
the destination.settings dict. Merge the values by overlaying the
cached setting over the existing info.
:param destination:
An object that has a `.settings` attribute that is a dict
:param setting:
The dict key to use when pushing the value into the settings dict
:param key_prefix:
The string to prefix to `setting` to make the cache key
"""
existing = destination.settings.get(setting, {})
value = get_cache(key_prefix + '.' + setting, {})
if value:
existing.update(value)
destination.settings[setting] = existing
def merge_cache_under_settings(destination, setting, key_prefix, list_=False):
"""
Take the cached value of `key` and put it into the key `setting` of
the destination.settings dict. Merge the values by overlaying the
existing setting value over the cached info.
:param destination:
An object that has a `.settings` attribute that is a dict
:param setting:
The dict key to use when pushing the value into the settings dict
:param key_prefix:
The string to prefix to `setting` to make the cache key
:param list_:
If a list should be used instead of a dict
"""
default = {} if not list_ else []
existing = destination.settings.get(setting)
value = get_cache(key_prefix + '.' + setting, default)
if value:
if existing:
if list_:
# Prevent duplicate values
base = dict(zip(value, [None]*len(value)))
for val in existing:
if val in base:
continue
value.append(val)
else:
value.update(existing)
destination.settings[setting] = value
def set_cache(key, data, ttl=300):
"""
Sets an in-memory cache value
:param key:
The string key
:param data:
The data to cache
:param ttl:
The integer number of second to cache the data for
"""
_channel_repository_cache[key] = {
'data': data,
'expires': time.time() + ttl
}
def set_cache_over_settings(destination, setting, key_prefix, value, ttl):
"""
Take the value passed, and merge it over the current `setting`. Once
complete, take the value and set the cache `key` and destination.settings
`setting` to that value, using the `ttl` for set_cache().
:param destination:
An object that has a `.settings` attribute that is a dict
:param setting:
The dict key to use when pushing the value into the settings dict
:param key_prefix:
The string to prefix to `setting` to make the cache key
:param value:
The value to set
:param ttl:
The cache ttl to use
"""
existing = destination.settings.get(setting, {})
existing.update(value)
set_cache(key_prefix + '.' + setting, value, ttl)
destination.settings[setting] = value
def set_cache_under_settings(destination, setting, key_prefix, value, ttl, list_=False):
"""
Take the value passed, and merge the current `setting` over it. Once
complete, take the value and set the cache `key` and destination.settings
`setting` to that value, using the `ttl` for set_cache().
:param destination:
An object that has a `.settings` attribute that is a dict
:param setting:
The dict key to use when pushing the value into the settings dict
:param key_prefix:
The string to prefix to `setting` to make the cache key
:param value:
The value to set
:param ttl:
The cache ttl to use
"""
default = {} if not list_ else []
existing = destination.settings.get(setting, default)
if value:
if list_:
value.extend(existing)
else:
value.update(existing)
set_cache(key_prefix + '.' + setting, value, ttl)
destination.settings[setting] = value

View File

@@ -0,0 +1,37 @@
import os
def clear_directory(directory, ignore_paths=None):
"""
Tries to delete all files and folders from a directory
:param directory:
The string directory path
:param ignore_paths:
An array of paths to ignore while deleting files
:return:
If all of the files and folders were successfully deleted
"""
was_exception = False
for root, dirs, files in os.walk(directory, topdown=False):
paths = [os.path.join(root, f) for f in files]
paths.extend([os.path.join(root, d) for d in dirs])
for path in paths:
try:
# Don't delete the metadata file, that way we have it
# when the reinstall happens, and the appropriate
# usage info can be sent back to the server
if ignore_paths and path in ignore_paths:
continue
if os.path.isdir(path):
os.rmdir(path)
else:
os.remove(path)
except (OSError, IOError):
was_exception = True
return not was_exception

View File

@@ -0,0 +1,257 @@
import re
from ..versions import version_sort, version_filter
from .json_api_client import JSONApiClient
# A predefined list of readme filenames to look for
_readme_filenames = [
'readme',
'readme.txt',
'readme.md',
'readme.mkd',
'readme.mdown',
'readme.markdown',
'readme.textile',
'readme.creole',
'readme.rst'
]
class BitBucketClient(JSONApiClient):
def download_info(self, url):
"""
Retrieve information about downloading a package
:param url:
The URL of the repository, in one of the forms:
https://bitbucket.org/{user}/{repo}
https://bitbucket.org/{user}/{repo}/src/{branch}
https://bitbucket.org/{user}/{repo}/#tags
If the last option, grabs the info from the newest
tag that is a valid semver version.
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, False if no commit, or a dict with the following keys:
`version` - the version number of the download
`url` - the download URL of a zip file of the package
`date` - the ISO-8601 timestamp string when the version was published
"""
commit_info = self._commit_info(url)
if not commit_info:
return commit_info
return {
'version': commit_info['version'],
'url': 'https://bitbucket.org/%s/get/%s.zip' % (commit_info['user_repo'], commit_info['commit']),
'date': commit_info['timestamp']
}
def repo_info(self, url):
"""
Retrieve general information about a repository
:param url:
The URL to the repository, in one of the forms:
https://bitbucket.org/{user}/{repo}
https://bitbucket.org/{user}/{repo}/src/{branch}
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, or a dict with the following keys:
`name`
`description`
`homepage` - URL of the homepage
`author`
`readme` - URL of the readme
`issues` - URL of bug tracker
`donate` - URL of a donate page
"""
user_repo, branch = self._user_repo_branch(url)
if not user_repo:
return user_repo
api_url = self._make_api_url(user_repo)
info = self.fetch_json(api_url)
issues_url = u'https://bitbucket.org/%s/issues' % user_repo
return {
'name': info['name'],
'description': info['description'] or 'No description provided',
'homepage': info['website'] or url,
'author': info['owner'],
'donate': u'https://www.gittip.com/on/bitbucket/%s/' % info['owner'],
'readme': self._readme_url(user_repo, branch),
'issues': issues_url if info['has_issues'] else None
}
def _commit_info(self, url):
"""
Fetches info about the latest commit to a repository
:param url:
The URL to the repository, in one of the forms:
https://bitbucket.org/{user}/{repo}
https://bitbucket.org/{user}/{repo}/src/{branch}
https://bitbucket.org/{user}/{repo}/#tags
If the last option, grabs the info from the newest
tag that is a valid semver version.
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, False if no commit, or a dict with the following keys:
`user_repo` - the user/repo name
`timestamp` - the ISO-8601 UTC timestamp string
`commit` - the branch or tag name
`version` - the extracted version number
"""
tags_match = re.match('https?://bitbucket.org/([^/]+/[^#/]+)/?#tags$', url)
version = None
if tags_match:
user_repo = tags_match.group(1)
tags_url = self._make_api_url(user_repo, '/tags')
tags_list = self.fetch_json(tags_url)
tags = version_filter(tags_list.keys(), self.settings.get('install_prereleases'))
tags = version_sort(tags, reverse=True)
if not tags:
return False
commit = tags[0]
version = re.sub('^v', '', commit)
else:
user_repo, commit = self._user_repo_branch(url)
if not user_repo:
return user_repo
changeset_url = self._make_api_url(user_repo, '/changesets/%s' % commit)
commit_info = self.fetch_json(changeset_url)
commit_date = commit_info['timestamp'][0:19]
if not version:
version = re.sub('[\-: ]', '.', commit_date)
return {
'user_repo': user_repo,
'timestamp': commit_date,
'commit': commit,
'version': version
}
def _main_branch_name(self, user_repo):
"""
Fetch the name of the default branch
:param user_repo:
The user/repo name to get the main branch for
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
The name of the main branch - `master` or `default`
"""
main_branch_url = self._make_api_url(user_repo, '/main-branch')
main_branch_info = self.fetch_json(main_branch_url, True)
return main_branch_info['name']
def _make_api_url(self, user_repo, suffix=''):
"""
Generate a URL for the BitBucket API
:param user_repo:
The user/repo of the repository
:param suffix:
The extra API path info to add to the URL
:return:
The API URL
"""
return 'https://api.bitbucket.org/1.0/repositories/%s%s' % (user_repo, suffix)
def _readme_url(self, user_repo, branch, prefer_cached=False):
"""
Parse the root directory listing for the repo and return the URL
to any file that looks like a readme
:param user_repo:
The user/repo string
:param branch:
The branch to fetch the readme from
:param prefer_cached:
If a cached directory listing should be used instead of a new HTTP request
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
The URL to the readme file, or None
"""
listing_url = self._make_api_url(user_repo, '/src/%s/' % branch)
root_dir_info = self.fetch_json(listing_url, prefer_cached)
for entry in root_dir_info['files']:
if entry['path'].lower() in _readme_filenames:
return 'https://bitbucket.org/%s/raw/%s/%s' % (user_repo,
branch, entry['path'])
return None
def _user_repo_branch(self, url):
"""
Extract the username/repo and branch name from the URL
:param url:
The URL to extract the info from, in one of the forms:
https://bitbucket.org/{user}/{repo}
https://bitbucket.org/{user}/{repo}/src/{branch}
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
A tuple of (user/repo, branch name) or (None, None) if not matching
"""
repo_match = re.match('https?://bitbucket.org/([^/]+/[^/]+)/?$', url)
branch_match = re.match('https?://bitbucket.org/([^/]+/[^/]+)/src/([^/]+)/?$', url)
if repo_match:
user_repo = repo_match.group(1)
branch = self._main_branch_name(user_repo)
elif branch_match:
user_repo = branch_match.group(1)
branch = branch_match.group(2)
else:
return (None, None)
return (user_repo, branch)

View File

@@ -0,0 +1,5 @@
class ClientException(Exception):
"""If a client could not fetch information"""
def __str__(self):
return self.args[0]

View File

@@ -0,0 +1,292 @@
import re
try:
# Python 3
from urllib.parse import urlencode, quote
except (ImportError):
# Python 2
from urllib import urlencode, quote
from ..versions import version_sort, version_filter
from .json_api_client import JSONApiClient
from ..downloaders.downloader_exception import DownloaderException
class GitHubClient(JSONApiClient):
def download_info(self, url):
"""
Retrieve information about downloading a package
:param url:
The URL of the repository, in one of the forms:
https://github.com/{user}/{repo}
https://github.com/{user}/{repo}/tree/{branch}
https://github.com/{user}/{repo}/tags
If the last option, grabs the info from the newest
tag that is a valid semver version.
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, False if no commit, or a dict with the following keys:
`version` - the version number of the download
`url` - the download URL of a zip file of the package
`date` - the ISO-8601 timestamp string when the version was published
"""
commit_info = self._commit_info(url)
if not commit_info:
return commit_info
return {
'version': commit_info['version'],
# We specifically use codeload.github.com here because the download
# URLs all redirect there, and some of the downloaders don't follow
# HTTP redirect headers
'url': 'https://codeload.github.com/%s/zip/%s' % (commit_info['user_repo'], quote(commit_info['commit'])),
'date': commit_info['timestamp']
}
def repo_info(self, url):
"""
Retrieve general information about a repository
:param url:
The URL to the repository, in one of the forms:
https://github.com/{user}/{repo}
https://github.com/{user}/{repo}/tree/{branch}
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, or a dict with the following keys:
`name`
`description`
`homepage` - URL of the homepage
`author`
`readme` - URL of the readme
`issues` - URL of bug tracker
`donate` - URL of a donate page
"""
user_repo, branch = self._user_repo_branch(url)
if not user_repo:
return user_repo
api_url = self._make_api_url(user_repo)
info = self.fetch_json(api_url)
output = self._extract_repo_info(info)
output['readme'] = None
readme_info = self._readme_info(user_repo, branch)
if not readme_info:
return output
output['readme'] = 'https://raw.github.com/%s/%s/%s' % (user_repo,
branch, readme_info['path'])
return output
def user_info(self, url):
"""
Retrieve general information about all repositories that are
part of a user/organization.
:param url:
The URL to the user/organization, in the following form:
https://github.com/{user}
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, or am list of dicts with the following keys:
`name`
`description`
`homepage` - URL of the homepage
`author`
`readme` - URL of the readme
`issues` - URL of bug tracker
`donate` - URL of a donate page
"""
user_match = re.match('https?://github.com/([^/]+)/?$', url)
if user_match == None:
return None
user = user_match.group(1)
api_url = self._make_api_url(user)
repos_info = self.fetch_json(api_url)
output = []
for info in repos_info:
output.append(self._extract_repo_info(info))
return output
def _commit_info(self, url):
"""
Fetches info about the latest commit to a repository
:param url:
The URL to the repository, in one of the forms:
https://github.com/{user}/{repo}
https://github.com/{user}/{repo}/tree/{branch}
https://github.com/{user}/{repo}/tags
If the last option, grabs the info from the newest
tag that is a valid semver version.
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
None if no match, False is no commit, or a dict with the following keys:
`user_repo` - the user/repo name
`timestamp` - the ISO-8601 UTC timestamp string
`commit` - the branch or tag name
`version` - the extracted version number
"""
tags_match = re.match('https?://github.com/([^/]+/[^/]+)/tags/?$', url)
version = None
if tags_match:
user_repo = tags_match.group(1)
tags_url = self._make_api_url(user_repo, '/tags')
tags_list = self.fetch_json(tags_url)
tags = [tag['name'] for tag in tags_list]
tags = version_filter(tags, self.settings.get('install_prereleases'))
tags = version_sort(tags, reverse=True)
if not tags:
return False
commit = tags[0]
version = re.sub('^v', '', commit)
else:
user_repo, commit = self._user_repo_branch(url)
if not user_repo:
return user_repo
query_string = urlencode({'sha': commit, 'per_page': 1})
commit_url = self._make_api_url(user_repo, '/commits?%s' % query_string)
commit_info = self.fetch_json(commit_url)
commit_date = commit_info[0]['commit']['committer']['date'][0:19].replace('T', ' ')
if not version:
version = re.sub('[\-: ]', '.', commit_date)
return {
'user_repo': user_repo,
'timestamp': commit_date,
'commit': commit,
'version': version
}
def _extract_repo_info(self, result):
"""
Extracts information about a repository from the API result
:param result:
A dict representing the data returned from the GitHub API
:return:
A dict with the following keys:
`name`
`description`
`homepage` - URL of the homepage
`author`
`issues` - URL of bug tracker
`donate` - URL of a donate page
"""
issues_url = u'https://github.com/%s/%s/issues' % (result['owner']['login'], result['name'])
return {
'name': result['name'],
'description': result['description'] or 'No description provided',
'homepage': result['homepage'] or result['html_url'],
'author': result['owner']['login'],
'issues': issues_url if result['has_issues'] else None,
'donate': u'https://www.gittip.com/on/github/%s/' % result['owner']['login']
}
def _make_api_url(self, user_repo, suffix=''):
"""
Generate a URL for the BitBucket API
:param user_repo:
The user/repo of the repository
:param suffix:
The extra API path info to add to the URL
:return:
The API URL
"""
return 'https://api.github.com/repos/%s%s' % (user_repo, suffix)
def _readme_info(self, user_repo, branch, prefer_cached=False):
"""
Fetches the raw GitHub API information about a readme
:param user_repo:
The user/repo of the repository
:param branch:
The branch to pull the readme from
:param prefer_cached:
If a cached version of the info should be returned instead of making a new HTTP request
:raises:
DownloaderException: when there is an error downloading
ClientException: when there is an error parsing the response
:return:
A dict containing all of the info from the GitHub API, or None if no readme exists
"""
query_string = urlencode({'ref': branch})
readme_url = self._make_api_url(user_repo, '/readme?%s' % query_string)
try:
return self.fetch_json(readme_url, prefer_cached)
except (DownloaderException) as e:
if str(e).find('HTTP error 404') != -1:
return None
raise
def _user_repo_branch(self, url):
"""
Extract the username/repo and branch name from the URL
:param url:
The URL to extract the info from, in one of the forms:
https://github.com/{user}/{repo}
https://github.com/{user}/{repo}/tree/{branch}
:return:
A tuple of (user/repo, branch name) or (None, None) if no match
"""
branch = 'master'
branch_match = re.match('https?://github.com/[^/]+/[^/]+/tree/([^/]+)/?$', url)
if branch_match != None:
branch = branch_match.group(1)
repo_match = re.match('https?://github.com/([^/]+/[^/]+)($|/.*$)', url)
if repo_match == None:
return (None, None)
user_repo = repo_match.group(1)
return (user_repo, branch)

View File

@@ -0,0 +1,64 @@
import json
try:
# Python 3
from urllib.parse import urlencode, urlparse
except (ImportError):
# Python 2
from urllib import urlencode
from urlparse import urlparse
from .client_exception import ClientException
from ..download_manager import downloader
class JSONApiClient():
def __init__(self, settings):
self.settings = settings
def fetch(self, url, prefer_cached=False):
"""
Retrieves the contents of a URL
:param url:
The URL to download the content from
:param prefer_cached:
If a cached copy of the content is preferred
:return: The bytes/string
"""
# If there are extra params for the domain name, add them
extra_params = self.settings.get('query_string_params')
domain_name = urlparse(url).netloc
if extra_params and domain_name in extra_params:
params = urlencode(extra_params[domain_name])
joiner = '?%s' if url.find('?') == -1 else '&%s'
url += joiner % params
with downloader(url, self.settings) as manager:
content = manager.fetch(url, 'Error downloading repository.',
prefer_cached)
return content
def fetch_json(self, url, prefer_cached=False):
"""
Retrieves and parses the JSON from a URL
:param url:
The URL to download the JSON from
:param prefer_cached:
If a cached copy of the JSON is preferred
:return: A dict or list from the JSON
"""
repository_json = self.fetch(url, prefer_cached)
try:
return json.loads(repository_json.decode('utf-8'))
except (ValueError):
error_string = u'Error parsing JSON from URL %s.' % url
raise ClientException(error_string)

View File

@@ -0,0 +1,83 @@
import re
import os
import base64
try:
# Python 3
from urllib.parse import urlencode
except (ImportError):
# Python 2
from urllib import urlencode
from .json_api_client import JSONApiClient
from ..downloaders.downloader_exception import DownloaderException
# Used to map file extensions to formats
_readme_formats = {
'.md': 'markdown',
'.mkd': 'markdown',
'.mdown': 'markdown',
'.markdown': 'markdown',
'.textile': 'textile',
'.creole': 'creole',
'.rst': 'rst'
}
class ReadmeClient(JSONApiClient):
def readme_info(self, url):
"""
Retrieve the readme and info about it
:param url:
The URL of the readme file
:raises:
DownloaderException: if there is an error downloading the readme
ClientException: if there is an error parsing the response
:return:
A dict with the following keys:
`filename`
`format` - `markdown`, `textile`, `creole`, `rst` or `txt`
`contents` - contents of the readme as str/unicode
"""
contents = None
# Try to grab the contents of a GitHub-based readme by grabbing the cached
# content of the readme API call
github_match = re.match('https://raw.github.com/([^/]+/[^/]+)/([^/]+)/readme(\.(md|mkd|mdown|markdown|textile|creole|rst|txt))?$', url, re.I)
if github_match:
user_repo = github_match.group(1)
branch = github_match.group(2)
query_string = urlencode({'ref': branch})
readme_json_url = 'https://api.github.com/repos/%s/readme?%s' % (user_repo, query_string)
try:
info = self.fetch_json(readme_json_url, prefer_cached=True)
contents = base64.b64decode(info['content'])
except (ValueError) as e:
pass
if not contents:
contents = self.fetch(url)
basename, ext = os.path.splitext(url)
format = 'txt'
ext = ext.lower()
if ext in _readme_formats:
format = _readme_formats[ext]
try:
contents = contents.decode('utf-8')
except (UnicodeDecodeError) as e:
contents = contents.decode('cp1252', errors='replace')
return {
'filename': os.path.basename(url),
'format': format,
'contents': contents
}

View File

@@ -0,0 +1,167 @@
import os
import subprocess
import re
if os.name == 'nt':
from ctypes import windll, create_unicode_buffer
from .console_write import console_write
from .unicode import unicode_from_os
from .show_error import show_error
try:
# Python 2
str_cls = unicode
except (NameError):
# Python 3
str_cls = str
def create_cmd(args, basename_binary=False):
"""
Takes an array of strings to be passed to subprocess.Popen and creates
a string that can be pasted into a terminal
:param args:
The array containing the binary name/path and all arguments
:param basename_binary:
If only the basename of the binary should be disabled instead of the full path
:return:
The command string
"""
if basename_binary:
args[0] = os.path.basename(args[0])
if os.name == 'nt':
return subprocess.list2cmdline(args)
else:
escaped_args = []
for arg in args:
if re.search('^[a-zA-Z0-9/_^\\-\\.:=]+$', arg) == None:
arg = u"'" + arg.replace(u"'", u"'\\''") + u"'"
escaped_args.append(arg)
return u' '.join(escaped_args)
class Cli(object):
"""
Base class for running command line apps
:param binary:
The full filesystem path to the executable for the version control
system. May be set to None to allow the code to try and find it.
"""
cli_name = None
def __init__(self, binary, debug):
self.binary = binary
self.debug = debug
def execute(self, args, cwd, input=None):
"""
Creates a subprocess with the executable/args
:param args:
A list of the executable path and all arguments to it
:param cwd:
The directory in which to run the executable
:param input:
The input text to send to the program
:return: A string of the executable output
"""
startupinfo = None
if os.name == 'nt':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
# Make sure the cwd is ascii
try:
cwd.encode('ascii')
except UnicodeEncodeError:
buf = create_unicode_buffer(512)
if windll.kernel32.GetShortPathNameW(cwd, buf, len(buf)):
cwd = buf.value
if self.debug:
console_write(u"Trying to execute command %s" % create_cmd(args), True)
try:
proc = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
startupinfo=startupinfo, cwd=cwd)
if input and isinstance(input, str_cls):
input = input.encode('utf-8')
output, _ = proc.communicate(input)
output = output.decode('utf-8')
output = output.replace('\r\n', '\n').rstrip(' \n\r')
return output
except (OSError) as e:
cmd = create_cmd(args)
error = unicode_from_os(e)
message = u"Error executing: %s\n%s\n\nTry checking your \"%s_binary\" setting?" % (cmd, error, self.cli_name)
show_error(message)
return False
def find_binary(self, name):
"""
Locates the executable by looking in the PATH and well-known directories
:param name:
The string filename of the executable
:return: The filesystem path to the executable, or None if not found
"""
if self.binary:
if self.debug:
error_string = u"Using \"%s_binary\" from settings \"%s\"" % (
self.cli_name, self.binary)
console_write(error_string, True)
return self.binary
# Try the path first
for dir_ in os.environ['PATH'].split(os.pathsep):
path = os.path.join(dir_, name)
if os.path.exists(path):
if self.debug:
console_write(u"Found %s at \"%s\"" % (self.cli_name, path), True)
return path
# This is left in for backwards compatibility and for windows
# users who may have the binary, albeit in a common dir that may
# not be part of the PATH
if os.name == 'nt':
dirs = ['C:\\Program Files\\Git\\bin',
'C:\\Program Files (x86)\\Git\\bin',
'C:\\Program Files\\TortoiseGit\\bin',
'C:\\Program Files\\Mercurial',
'C:\\Program Files (x86)\\Mercurial',
'C:\\Program Files (x86)\\TortoiseHg',
'C:\\Program Files\\TortoiseHg',
'C:\\cygwin\\bin']
else:
# ST seems to launch with a minimal set of environmental variables
# on OS X, so we add some common paths for it
dirs = ['/usr/local/git/bin', '/usr/local/bin']
for dir_ in dirs:
path = os.path.join(dir_, name)
if os.path.exists(path):
if self.debug:
console_write(u"Found %s at \"%s\"" % (self.cli_name, path), True)
return path
if self.debug:
console_write(u"Could not find %s on your machine" % self.cli_name, True)
return None

View File

@@ -0,0 +1,39 @@
import os
from .add_channel_command import AddChannelCommand
from .add_repository_command import AddRepositoryCommand
from .create_binary_package_command import CreateBinaryPackageCommand
from .create_package_command import CreatePackageCommand
from .disable_package_command import DisablePackageCommand
from .discover_packages_command import DiscoverPackagesCommand
from .enable_package_command import EnablePackageCommand
from .grab_certs_command import GrabCertsCommand
from .install_package_command import InstallPackageCommand
from .list_packages_command import ListPackagesCommand
from .remove_package_command import RemovePackageCommand
from .upgrade_all_packages_command import UpgradeAllPackagesCommand
from .upgrade_package_command import UpgradePackageCommand
from .package_message_command import PackageMessageCommand
__all__ = [
'AddChannelCommand',
'AddRepositoryCommand',
'CreateBinaryPackageCommand',
'CreatePackageCommand',
'DisablePackageCommand',
'DiscoverPackagesCommand',
'EnablePackageCommand',
'InstallPackageCommand',
'ListPackagesCommand',
'RemovePackageCommand',
'UpgradeAllPackagesCommand',
'UpgradePackageCommand',
'PackageMessageCommand'
]
# Windows uses the wininet downloader, so it doesn't use the CA cert bundle
# and thus does not need the ability to grab to CA certs. Additionally,
# there is no openssl.exe on Windows.
if os.name != 'nt':
__all__.append('GrabCertsCommand')

View File

@@ -0,0 +1,46 @@
import re
import sublime
import sublime_plugin
from ..show_error import show_error
class AddChannelCommand(sublime_plugin.WindowCommand):
"""
A command to add a new channel (list of repositories) to the user's machine
"""
def run(self):
self.window.show_input_panel('Channel JSON URL', '',
self.on_done, self.on_change, self.on_cancel)
def on_done(self, input):
"""
Input panel handler - adds the provided URL as a channel
:param input:
A string of the URL to the new channel
"""
input = input.strip()
if re.match('https?://', input, re.I) == None:
show_error(u"Unable to add the channel \"%s\" since it does not appear to be served via HTTP (http:// or https://)." % input)
return
settings = sublime.load_settings('Package Control.sublime-settings')
channels = settings.get('channels', [])
if not channels:
channels = []
channels.append(input)
settings.set('channels', channels)
sublime.save_settings('Package Control.sublime-settings')
sublime.status_message(('Channel %s successfully ' +
'added') % input)
def on_change(self, input):
pass
def on_cancel(self):
pass

View File

@@ -0,0 +1,46 @@
import re
import sublime
import sublime_plugin
from ..show_error import show_error
class AddRepositoryCommand(sublime_plugin.WindowCommand):
"""
A command to add a new repository to the user's machine
"""
def run(self):
self.window.show_input_panel('GitHub or BitBucket Web URL, or Custom' +
' JSON Repository URL', '', self.on_done,
self.on_change, self.on_cancel)
def on_done(self, input):
"""
Input panel handler - adds the provided URL as a repository
:param input:
A string of the URL to the new repository
"""
input = input.strip()
if re.match('https?://', input, re.I) == None:
show_error(u"Unable to add the repository \"%s\" since it does not appear to be served via HTTP (http:// or https://)." % input)
return
settings = sublime.load_settings('Package Control.sublime-settings')
repositories = settings.get('repositories', [])
if not repositories:
repositories = []
repositories.append(input)
settings.set('repositories', repositories)
sublime.save_settings('Package Control.sublime-settings')
sublime.status_message('Repository %s successfully added' % input)
def on_change(self, input):
pass
def on_cancel(self):
pass

View File

@@ -0,0 +1,35 @@
import sublime_plugin
from ..package_creator import PackageCreator
class CreateBinaryPackageCommand(sublime_plugin.WindowCommand, PackageCreator):
"""
Command to create a binary .sublime-package file. Binary packages in
general exclude the .py source files and instead include the .pyc files.
Actual included and excluded files are controlled by settings.
"""
def run(self):
self.show_panel()
def on_done(self, picked):
"""
Quick panel user selection handler - processes the user package
selection and create the package file
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package_name = self.packages[picked]
package_destination = self.get_package_destination()
if self.manager.create_package(package_name, package_destination,
binary_package=True):
self.window.run_command('open_dir', {"dir":
package_destination, "file": package_name +
'.sublime-package'})

View File

@@ -0,0 +1,32 @@
import sublime_plugin
from ..package_creator import PackageCreator
class CreatePackageCommand(sublime_plugin.WindowCommand, PackageCreator):
"""
Command to create a regular .sublime-package file
"""
def run(self):
self.show_panel()
def on_done(self, picked):
"""
Quick panel user selection handler - processes the user package
selection and create the package file
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package_name = self.packages[picked]
package_destination = self.get_package_destination()
if self.manager.create_package(package_name, package_destination):
self.window.run_command('open_dir', {"dir":
package_destination, "file": package_name +
'.sublime-package'})

View File

@@ -0,0 +1,48 @@
import sublime
import sublime_plugin
from ..show_error import show_error
from ..package_manager import PackageManager
from ..preferences_filename import preferences_filename
class DisablePackageCommand(sublime_plugin.WindowCommand):
"""
A command that adds a package to Sublime Text's ignored packages list
"""
def run(self):
manager = PackageManager()
packages = manager.list_all_packages()
self.settings = sublime.load_settings(preferences_filename())
ignored = self.settings.get('ignored_packages')
if not ignored:
ignored = []
self.package_list = list(set(packages) - set(ignored))
self.package_list.sort()
if not self.package_list:
show_error('There are no enabled packages to disable.')
return
self.window.show_quick_panel(self.package_list, self.on_done)
def on_done(self, picked):
"""
Quick panel user selection handler - disables the selected package
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package = self.package_list[picked]
ignored = self.settings.get('ignored_packages')
if not ignored:
ignored = []
ignored.append(package)
self.settings.set('ignored_packages', ignored)
sublime.save_settings(preferences_filename())
sublime.status_message(('Package %s successfully added to list of ' +
'disabled packages - restarting Sublime Text may be required') %
package)

View File

@@ -0,0 +1,11 @@
import sublime_plugin
class DiscoverPackagesCommand(sublime_plugin.WindowCommand):
"""
A command that opens the community package list webpage
"""
def run(self):
self.window.run_command('open_url',
{'url': 'http://wbond.net/sublime_packages/community'})

View File

@@ -0,0 +1,40 @@
import sublime
import sublime_plugin
from ..show_error import show_error
from ..preferences_filename import preferences_filename
class EnablePackageCommand(sublime_plugin.WindowCommand):
"""
A command that removes a package from Sublime Text's ignored packages list
"""
def run(self):
self.settings = sublime.load_settings(preferences_filename())
self.disabled_packages = self.settings.get('ignored_packages')
self.disabled_packages.sort()
if not self.disabled_packages:
show_error('There are no disabled packages to enable.')
return
self.window.show_quick_panel(self.disabled_packages, self.on_done)
def on_done(self, picked):
"""
Quick panel user selection handler - enables the selected package
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package = self.disabled_packages[picked]
ignored = self.settings.get('ignored_packages')
self.settings.set('ignored_packages',
list(set(ignored) - set([package])))
sublime.save_settings(preferences_filename())
sublime.status_message(('Package %s successfully removed from list ' +
'of disabled packages - restarting Sublime Text may be required') %
package)

View File

@@ -0,0 +1,69 @@
import os
import re
import sublime
from ..package_manager import PackageManager
class ExistingPackagesCommand():
"""
Allows listing installed packages and their current version
"""
def __init__(self):
self.manager = PackageManager()
def make_package_list(self, action=''):
"""
Returns a list of installed packages suitable for displaying in the
quick panel.
:param action:
An action to display at the beginning of the third element of the
list returned for each package
:return:
A list of lists, each containing three strings:
0 - package name
1 - package description
2 - [action] installed version; package url
"""
packages = self.manager.list_packages()
if action:
action += ' '
package_list = []
for package in sorted(packages, key=lambda s: s.lower()):
package_entry = [package]
metadata = self.manager.get_metadata(package)
package_dir = os.path.join(sublime.packages_path(), package)
description = metadata.get('description')
if not description:
description = 'No description provided'
package_entry.append(description)
version = metadata.get('version')
if not version and os.path.exists(os.path.join(package_dir,
'.git')):
installed_version = 'git repository'
elif not version and os.path.exists(os.path.join(package_dir,
'.hg')):
installed_version = 'hg repository'
else:
installed_version = 'v' + version if version else \
'unknown version'
url = metadata.get('url')
if url:
url = '; ' + re.sub('^https?://', '', url)
else:
url = ''
package_entry.append(action + installed_version + url)
package_list.append(package_entry)
return package_list

View File

@@ -0,0 +1,109 @@
import os
import re
import socket
import threading
try:
# Python 3
from urllib.parse import urlparse
except (ImportError):
# Python 2
from urlparse import urlparse
import sublime
import sublime_plugin
from ..show_error import show_error
from ..open_compat import open_compat
from ..ca_certs import find_root_ca_cert
from ..thread_progress import ThreadProgress
from ..package_manager import PackageManager
class GrabCertsCommand(sublime_plugin.WindowCommand):
"""
A command that extracts the CA certs for a domain name, allowing a user to
fetch packages from sources other than those used by the default channel
"""
def run(self):
panel = self.window.show_input_panel('Domain Name', 'example.com', self.on_done,
None, None)
panel.sel().add(sublime.Region(0, panel.size()))
def on_done(self, domain):
"""
Input panel handler - grabs the CA certs for the domain name presented
:param domain:
A string of the domain name
"""
domain = domain.strip()
# Make sure the user enters something
if domain == '':
show_error(u"Please enter a domain name, or press cancel")
self.run()
return
# If the user inputs a URL, extract the domain name
if domain.find('/') != -1:
parts = urlparse(domain)
if parts.hostname:
domain = parts.hostname
# Allow _ even though it technically isn't valid, this is really
# just to try and prevent people from typing in gibberish
if re.match('^(?:[a-zA-Z0-9]+(?:[\-_]*[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,6}$', domain, re.I) == None:
show_error(u"Unable to get the CA certs for \"%s\" since it does not appear to be a validly formed domain name" % domain)
return
# Make sure it is a real domain
try:
socket.gethostbyname(domain)
except (socket.gaierror) as e:
error = unicode_from_os(e)
show_error(u"Error trying to lookup \"%s\":\n\n%s" % (domain, error))
return
manager = PackageManager()
thread = GrabCertsThread(manager.settings, domain)
thread.start()
ThreadProgress(thread, 'Grabbing CA certs for %s' % domain,
'CA certs for %s added to settings' % domain)
class GrabCertsThread(threading.Thread):
"""
A thread to run openssl so that the Sublime Text UI does not become frozen
"""
def __init__(self, settings, domain):
self.settings = settings
self.domain = domain
threading.Thread.__init__(self)
def run(self):
cert, cert_hash = find_root_ca_cert(self.settings, self.domain)
certs_dir = os.path.join(sublime.packages_path(), 'User',
'Package Control.ca-certs')
if not os.path.exists(certs_dir):
os.mkdir(certs_dir)
cert_path = os.path.join(certs_dir, self.domain + '-ca.crt')
with open_compat(cert_path, 'w') as f:
f.write(cert)
def save_certs():
settings = sublime.load_settings('Package Control.sublime-settings')
certs = settings.get('certs', {})
if not certs:
certs = {}
certs[self.domain] = [cert_hash, cert_path]
settings.set('certs', certs)
sublime.save_settings('Package Control.sublime-settings')
sublime.set_timeout(save_certs, 10)

View File

@@ -0,0 +1,50 @@
import threading
import sublime
import sublime_plugin
from ..show_error import show_error
from ..package_installer import PackageInstaller
from ..thread_progress import ThreadProgress
class InstallPackageCommand(sublime_plugin.WindowCommand):
"""
A command that presents the list of available packages and allows the
user to pick one to install.
"""
def run(self):
thread = InstallPackageThread(self.window)
thread.start()
ThreadProgress(thread, 'Loading repositories', '')
class InstallPackageThread(threading.Thread, PackageInstaller):
"""
A thread to run the action of retrieving available packages in. Uses the
default PackageInstaller.on_done quick panel handler.
"""
def __init__(self, window):
"""
:param window:
An instance of :class:`sublime.Window` that represents the Sublime
Text window to show the available package list in.
"""
self.window = window
self.completion_type = 'installed'
threading.Thread.__init__(self)
PackageInstaller.__init__(self)
def run(self):
self.package_list = self.make_package_list(['upgrade', 'downgrade',
'reinstall', 'pull', 'none'])
def show_quick_panel():
if not self.package_list:
show_error('There are no packages available for installation')
return
self.window.show_quick_panel(self.package_list, self.on_done)
sublime.set_timeout(show_quick_panel, 10)

View File

@@ -0,0 +1,63 @@
import threading
import os
import sublime
import sublime_plugin
from ..show_error import show_error
from .existing_packages_command import ExistingPackagesCommand
class ListPackagesCommand(sublime_plugin.WindowCommand):
"""
A command that shows a list of all installed packages in the quick panel
"""
def run(self):
ListPackagesThread(self.window).start()
class ListPackagesThread(threading.Thread, ExistingPackagesCommand):
"""
A thread to prevent the listing of existing packages from freezing the UI
"""
def __init__(self, window):
"""
:param window:
An instance of :class:`sublime.Window` that represents the Sublime
Text window to show the list of installed packages in.
"""
self.window = window
threading.Thread.__init__(self)
ExistingPackagesCommand.__init__(self)
def run(self):
self.package_list = self.make_package_list()
def show_quick_panel():
if not self.package_list:
show_error('There are no packages to list')
return
self.window.show_quick_panel(self.package_list, self.on_done)
sublime.set_timeout(show_quick_panel, 10)
def on_done(self, picked):
"""
Quick panel user selection handler - opens the homepage for any
selected package in the user's browser
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package_name = self.package_list[picked][0]
def open_dir():
self.window.run_command('open_dir',
{"dir": os.path.join(sublime.packages_path(), package_name)})
sublime.set_timeout(open_dir, 10)

View File

@@ -0,0 +1,11 @@
import sublime
import sublime_plugin
class PackageMessageCommand(sublime_plugin.TextCommand):
"""
A command to write a package message to the Package Control messaging buffer
"""
def run(self, edit, string=''):
self.view.insert(edit, self.view.size(), string)

View File

@@ -0,0 +1,88 @@
import threading
import sublime
import sublime_plugin
from ..show_error import show_error
from .existing_packages_command import ExistingPackagesCommand
from ..preferences_filename import preferences_filename
from ..thread_progress import ThreadProgress
class RemovePackageCommand(sublime_plugin.WindowCommand,
ExistingPackagesCommand):
"""
A command that presents a list of installed packages, allowing the user to
select one to remove
"""
def __init__(self, window):
"""
:param window:
An instance of :class:`sublime.Window` that represents the Sublime
Text window to show the list of installed packages in.
"""
self.window = window
ExistingPackagesCommand.__init__(self)
def run(self):
self.package_list = self.make_package_list('remove')
if not self.package_list:
show_error('There are no packages that can be removed.')
return
self.window.show_quick_panel(self.package_list, self.on_done)
def on_done(self, picked):
"""
Quick panel user selection handler - deletes the selected package
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
package = self.package_list[picked][0]
settings = sublime.load_settings(preferences_filename())
ignored = settings.get('ignored_packages')
if not ignored:
ignored = []
# Don't disable Package Control so it does not get stuck disabled
if package != 'Package Control':
if not package in ignored:
ignored.append(package)
settings.set('ignored_packages', ignored)
sublime.save_settings(preferences_filename())
ignored.remove(package)
thread = RemovePackageThread(self.manager, package,
ignored)
thread.start()
ThreadProgress(thread, 'Removing package %s' % package,
'Package %s successfully removed' % package)
class RemovePackageThread(threading.Thread):
"""
A thread to run the remove package operation in so that the Sublime Text
UI does not become frozen
"""
def __init__(self, manager, package, ignored):
self.manager = manager
self.package = package
self.ignored = ignored
threading.Thread.__init__(self)
def run(self):
self.result = self.manager.remove_package(self.package)
def unignore_package():
settings = sublime.load_settings(preferences_filename())
settings.set('ignored_packages', self.ignored)
sublime.save_settings(preferences_filename())
sublime.set_timeout(unignore_package, 10)

View File

@@ -0,0 +1,77 @@
import time
import threading
import sublime
import sublime_plugin
from ..thread_progress import ThreadProgress
from ..package_installer import PackageInstaller, PackageInstallerThread
from ..package_renamer import PackageRenamer
class UpgradeAllPackagesCommand(sublime_plugin.WindowCommand):
"""
A command to automatically upgrade all installed packages that are
upgradable.
"""
def run(self):
package_renamer = PackageRenamer()
package_renamer.load_settings()
thread = UpgradeAllPackagesThread(self.window, package_renamer)
thread.start()
ThreadProgress(thread, 'Loading repositories', '')
class UpgradeAllPackagesThread(threading.Thread, PackageInstaller):
"""
A thread to run the action of retrieving upgradable packages in.
"""
def __init__(self, window, package_renamer):
self.window = window
self.package_renamer = package_renamer
self.completion_type = 'upgraded'
threading.Thread.__init__(self)
PackageInstaller.__init__(self)
def run(self):
self.package_renamer.rename_packages(self)
package_list = self.make_package_list(['install', 'reinstall', 'none'])
disabled_packages = []
def do_upgrades():
# Pause so packages can be disabled
time.sleep(0.5)
# We use a function to generate the on-complete lambda because if
# we don't, the lambda will bind to info at the current scope, and
# thus use the last value of info from the loop
def make_on_complete(name):
return lambda: self.reenable_package(name)
for info in package_list:
if info[0] in disabled_packages:
on_complete = make_on_complete(info[0])
else:
on_complete = None
thread = PackageInstallerThread(self.manager, info[0],
on_complete)
thread.start()
ThreadProgress(thread, 'Upgrading package %s' % info[0],
'Package %s successfully %s' % (info[0],
self.completion_type))
# Disabling a package means changing settings, which can only be done
# in the main thread. We then create a new background thread so that
# the upgrade process does not block the UI.
def disable_packages():
package_names = []
for info in package_list:
package_names.append(info[0])
disabled_packages.extend(self.disable_packages(package_names))
threading.Thread(target=do_upgrades).start()
sublime.set_timeout(disable_packages, 1)

View File

@@ -0,0 +1,81 @@
import threading
import sublime
import sublime_plugin
from ..show_error import show_error
from ..thread_progress import ThreadProgress
from ..package_installer import PackageInstaller, PackageInstallerThread
from ..package_renamer import PackageRenamer
class UpgradePackageCommand(sublime_plugin.WindowCommand):
"""
A command that presents the list of installed packages that can be upgraded
"""
def run(self):
package_renamer = PackageRenamer()
package_renamer.load_settings()
thread = UpgradePackageThread(self.window, package_renamer)
thread.start()
ThreadProgress(thread, 'Loading repositories', '')
class UpgradePackageThread(threading.Thread, PackageInstaller):
"""
A thread to run the action of retrieving upgradable packages in.
"""
def __init__(self, window, package_renamer):
"""
:param window:
An instance of :class:`sublime.Window` that represents the Sublime
Text window to show the list of upgradable packages in.
:param package_renamer:
An instance of :class:`PackageRenamer`
"""
self.window = window
self.package_renamer = package_renamer
self.completion_type = 'upgraded'
threading.Thread.__init__(self)
PackageInstaller.__init__(self)
def run(self):
self.package_renamer.rename_packages(self)
self.package_list = self.make_package_list(['install', 'reinstall',
'none'])
def show_quick_panel():
if not self.package_list:
show_error('There are no packages ready for upgrade')
return
self.window.show_quick_panel(self.package_list, self.on_done)
sublime.set_timeout(show_quick_panel, 10)
def on_done(self, picked):
"""
Quick panel user selection handler - disables a package, upgrades it,
then re-enables the package
:param picked:
An integer of the 0-based package name index from the presented
list. -1 means the user cancelled.
"""
if picked == -1:
return
name = self.package_list[picked][0]
if name in self.disable_packages(name):
on_complete = lambda: self.reenable_package(name)
else:
on_complete = None
thread = PackageInstallerThread(self.manager, name, on_complete)
thread.start()
ThreadProgress(thread, 'Upgrading package %s' % name,
'Package %s successfully %s' % (name, self.completion_type))

View File

@@ -0,0 +1,20 @@
import sys
def console_write(string, prefix=False):
"""
Writes a value to the Sublime Text console, encoding unicode to utf-8 first
:param string:
The value to write
:param prefix:
If the string "Package Control: " should be prefixed to the string
"""
if sys.version_info < (3,):
if isinstance(string, unicode):
string = string.encode('UTF-8')
if prefix:
sys.stdout.write('Package Control: ')
print(string)

View File

@@ -0,0 +1,231 @@
import sys
import re
import socket
from threading import Lock, Timer
from contextlib import contextmanager
try:
# Python 3
from urllib.parse import urlparse
except (ImportError):
# Python 2
from urlparse import urlparse
from . import __version__
from .show_error import show_error
from .console_write import console_write
from .cache import set_cache, get_cache
from .unicode import unicode_from_os
from .downloaders import DOWNLOADERS
from .downloaders.binary_not_found_error import BinaryNotFoundError
from .downloaders.rate_limit_exception import RateLimitException
from .downloaders.no_ca_cert_exception import NoCaCertException
from .downloaders.downloader_exception import DownloaderException
from .http_cache import HttpCache
# A dict of domains - each points to a list of downloaders
_managers = {}
# How many managers are currently checked out
_in_use = 0
# Make sure connection management doesn't run into threading issues
_lock = Lock()
# A timer used to disconnect all managers after a period of no usage
_timer = None
@contextmanager
def downloader(url, settings):
try:
manager = _grab(url, settings)
yield manager
finally:
_release(url, manager)
def _grab(url, settings):
global _managers, _lock, _in_use, _timer
_lock.acquire()
try:
if _timer:
_timer.cancel()
_timer = None
hostname = urlparse(url).hostname.lower()
if hostname not in _managers:
_managers[hostname] = []
if not _managers[hostname]:
_managers[hostname].append(DownloadManager(settings))
_in_use += 1
return _managers[hostname].pop()
finally:
_lock.release()
def _release(url, manager):
global _managers, _lock, _in_use, _timer
_lock.acquire()
try:
hostname = urlparse(url).hostname.lower()
_managers[hostname].insert(0, manager)
_in_use -= 1
if _timer:
_timer.cancel()
_timer = None
if _in_use == 0:
_timer = Timer(5.0, close_all_connections)
_timer.start()
finally:
_lock.release()
def close_all_connections():
global _managers, _lock, _in_use, _timer
_lock.acquire()
try:
if _timer:
_timer.cancel()
_timer = None
for domain, managers in _managers.items():
for manager in managers:
manager.close()
_managers = {}
finally:
_lock.release()
class DownloadManager(object):
def __init__(self, settings):
# Cache the downloader for re-use
self.downloader = None
user_agent = settings.get('user_agent')
if user_agent and user_agent.find('%s') != -1:
settings['user_agent'] = user_agent % __version__
self.settings = settings
if settings.get('http_cache'):
cache_length = settings.get('http_cache_length', 604800)
self.settings['cache'] = HttpCache(cache_length)
def close(self):
if self.downloader:
self.downloader.close()
self.downloader = None
def fetch(self, url, error_message, prefer_cached=False):
"""
Downloads a URL and returns the contents
:param url:
The string URL to download
:param error_message:
The error message to include if the download fails
:param prefer_cached:
If cached version of the URL content is preferred over a new request
:raises:
DownloaderException: if there was an error downloading the URL
:return:
The string contents of the URL
"""
is_ssl = re.search('^https://', url) != None
# Make sure we have a downloader, and it supports SSL if we need it
if not self.downloader or (is_ssl and not self.downloader.supports_ssl()):
for downloader_class in DOWNLOADERS:
try:
downloader = downloader_class(self.settings)
if is_ssl and not downloader.supports_ssl():
continue
self.downloader = downloader
break
except (BinaryNotFoundError):
pass
if not self.downloader:
error_string = u'Unable to download %s due to no ssl module available and no capable program found. Please install curl or wget.' % url
show_error(error_string)
raise DownloaderException(error_string)
url = url.replace(' ', '%20')
hostname = urlparse(url).hostname
if hostname:
hostname = hostname.lower()
timeout = self.settings.get('timeout', 3)
rate_limited_domains = get_cache('rate_limited_domains', [])
no_ca_cert_domains = get_cache('no_ca_cert_domains', [])
if self.settings.get('debug'):
try:
ip = socket.gethostbyname(hostname)
except (socket.gaierror) as e:
ip = unicode_from_os(e)
except (TypeError) as e:
ip = None
console_write(u"Download Debug", True)
console_write(u" URL: %s" % url)
console_write(u" Resolved IP: %s" % ip)
console_write(u" Timeout: %s" % str(timeout))
if hostname in rate_limited_domains:
error_string = u"Skipping due to hitting rate limit for %s" % hostname
if self.settings.get('debug'):
console_write(u" %s" % error_string)
raise DownloaderException(error_string)
if hostname in no_ca_cert_domains:
error_string = u" Skipping since there are no CA certs for %s" % hostname
if self.settings.get('debug'):
console_write(u" %s" % error_string)
raise DownloaderException(error_string)
try:
return self.downloader.download(url, error_message, timeout, 3, prefer_cached)
except (RateLimitException) as e:
rate_limited_domains.append(hostname)
set_cache('rate_limited_domains', rate_limited_domains, self.settings.get('cache_length'))
error_string = (u'Hit rate limit of %s for %s, skipping all futher ' +
u'download requests for this domain') % (e.limit, e.domain)
console_write(error_string, True)
raise
except (NoCaCertException) as e:
no_ca_cert_domains.append(hostname)
set_cache('no_ca_cert_domains', no_ca_cert_domains, self.settings.get('cache_length'))
error_string = (u'No CA certs available for %s, skipping all futher ' +
u'download requests for this domain. If you are on a trusted ' +
u'network, you can add the CA certs by running the "Grab ' +
u'CA Certs" command from the command palette.') % e.domain
console_write(error_string, True)
raise

View File

@@ -0,0 +1,11 @@
import os
if os.name == 'nt':
from .wininet_downloader import WinINetDownloader
DOWNLOADERS = [WinINetDownloader]
else:
from .urllib_downloader import UrlLibDownloader
from .curl_downloader import CurlDownloader
from .wget_downloader import WgetDownloader
DOWNLOADERS = [UrlLibDownloader, CurlDownloader, WgetDownloader]

View File

@@ -0,0 +1,62 @@
import threading
class BackgroundDownloader(threading.Thread):
"""
Downloads information from one or more URLs in the background.
Normal usage is to use one BackgroundDownloader per domain name.
:param settings:
A dict containing at least the following fields:
`cache_length`,
`debug`,
`timeout`,
`user_agent`,
`http_proxy`,
`https_proxy`,
`proxy_username`,
`proxy_password`
:param providers:
An array of providers that can download the URLs
"""
def __init__(self, settings, providers):
self.settings = settings
self.urls = []
self.providers = providers
self.used_providers = {}
threading.Thread.__init__(self)
def add_url(self, url):
"""
Adds a URL to the list to download
:param url:
The URL to download info about
"""
self.urls.append(url)
def get_provider(self, url):
"""
Returns the provider for the URL specified
:param url:
The URL to return the provider for
:return:
The provider object for the URL
"""
return self.used_providers[url]
def run(self):
for url in self.urls:
for provider_class in self.providers:
if provider_class.match_url(url):
provider = provider_class(url, self.settings)
break
provider.prefetch()
self.used_providers[url] = provider

View File

@@ -0,0 +1,4 @@
class BinaryNotFoundError(Exception):
"""If a necessary executable is not found in the PATH on the system"""
pass

View File

@@ -0,0 +1,185 @@
import sys
import re
import json
import hashlib
from ..console_write import console_write
class CachingDownloader(object):
"""
A base downloader that will use a caching backend to cache HTTP requests
and make conditional requests.
"""
def add_conditional_headers(self, url, headers):
"""
Add `If-Modified-Since` and `If-None-Match` headers to a request if a
cached copy exists
:param headers:
A dict with the request headers
:return:
The request headers dict, possibly with new headers added
"""
if not self.settings.get('cache'):
return headers
info_key = self.generate_key(url, '.info')
info_json = self.settings['cache'].get(info_key)
if not info_json:
return headers
# Make sure we have the cached content to use if we get a 304
key = self.generate_key(url)
if not self.settings['cache'].has(key):
return headers
try:
info = json.loads(info_json.decode('utf-8'))
except ValueError:
return headers
etag = info.get('etag')
if etag:
headers['If-None-Match'] = etag
last_modified = info.get('last-modified')
if last_modified:
headers['If-Modified-Since'] = last_modified
return headers
def cache_result(self, method, url, status, headers, content):
"""
Processes a request result, either caching the result, or returning
the cached version of the url.
:param method:
The HTTP method used for the request
:param url:
The url of the request
:param status:
The numeric response status of the request
:param headers:
A dict of reponse headers, with keys being lowercase
:param content:
The response content
:return:
The response content
"""
debug = self.settings.get('debug', False)
if not self.settings.get('cache'):
if debug:
console_write(u"Skipping cache since there is no cache object", True)
return content
if method.lower() != 'get':
if debug:
console_write(u"Skipping cache since the HTTP method != GET", True)
return content
status = int(status)
# Don't do anything unless it was successful or not modified
if status not in [200, 304]:
if debug:
console_write(u"Skipping cache since the HTTP status code not one of: 200, 304", True)
return content
key = self.generate_key(url)
if status == 304:
cached_content = self.settings['cache'].get(key)
if cached_content:
if debug:
console_write(u"Using cached content for %s" % url, True)
return cached_content
# If we got a 304, but did not have the cached content
# stop here so we don't cache an empty response
return content
# If we got here, the status is 200
# Respect some basic cache control headers
cache_control = headers.get('cache-control', '')
if cache_control:
fields = re.split(',\s*', cache_control)
for field in fields:
if field == 'no-store':
return content
# Don't ever cache zip/binary files for the sake of hard drive space
if headers.get('content-type') in ['application/zip', 'application/octet-stream']:
if debug:
console_write(u"Skipping cache since the response is a zip file", True)
return content
etag = headers.get('etag')
last_modified = headers.get('last-modified')
if not etag and not last_modified:
return content
struct = {'etag': etag, 'last-modified': last_modified}
struct_json = json.dumps(struct, indent=4)
info_key = self.generate_key(url, '.info')
if debug:
console_write(u"Caching %s in %s" % (url, key), True)
self.settings['cache'].set(info_key, struct_json.encode('utf-8'))
self.settings['cache'].set(key, content)
return content
def generate_key(self, url, suffix=''):
"""
Generates a key to store the cache under
:param url:
The URL being cached
:param suffix:
A string to append to the key
:return:
A string key for the URL
"""
if sys.version_info >= (3,) or isinstance(url, unicode):
url = url.encode('utf-8')
key = hashlib.md5(url).hexdigest()
return key + suffix
def retrieve_cached(self, url):
"""
Tries to return the cached content for a URL
:param url:
The URL to get the cached content for
:return:
The cached content
"""
key = self.generate_key(url)
if not self.settings['cache'].has(key):
return False
if self.settings.get('debug'):
console_write(u"Using cached content for %s" % url, True)
return self.settings['cache'].get(key)

View File

@@ -0,0 +1,203 @@
import os
import re
import json
import sublime
from ..console_write import console_write
from ..open_compat import open_compat, read_compat
from ..package_io import read_package_file
from ..cache import get_cache
from ..ca_certs import get_system_ca_bundle_path
from .no_ca_cert_exception import NoCaCertException
from .downloader_exception import DownloaderException
class CertProvider(object):
"""
A base downloader that provides access to a ca-bundle for validating
SSL certificates.
"""
def check_certs(self, domain, timeout):
"""
Ensures that the SSL CA cert for a domain is present on the machine
:param domain:
The domain to ensure there is a CA cert for
:param timeout:
The int timeout for downloading the CA cert from the channel
:raises:
NoCaCertException: when a suitable CA cert could not be found
:return:
The CA cert bundle path
"""
# Try to use the system CA bundle
ca_bundle_path = get_system_ca_bundle_path(self.settings)
if ca_bundle_path:
return ca_bundle_path
# If the system bundle did not work, fall back to our CA distribution
# system. Hopefully this will be going away soon.
if self.settings.get('debug'):
console_write(u'Unable to find system CA cert bundle, falling back to certs provided by Package Control')
cert_match = False
certs_list = get_cache('*.certs', self.settings.get('certs', {}))
ca_bundle_path = os.path.join(sublime.packages_path(), 'User', 'Package Control.ca-bundle')
if not os.path.exists(ca_bundle_path) or os.stat(ca_bundle_path).st_size == 0:
bundle_contents = read_package_file('Package Control', 'Package Control.ca-bundle', True)
if not bundle_contents:
raise NoCaCertException(u'Unable to copy distributed Package Control.ca-bundle', domain)
with open_compat(ca_bundle_path, 'wb') as f:
f.write(bundle_contents)
cert_info = certs_list.get(domain)
if cert_info:
cert_match = self.locate_cert(cert_info[0],
cert_info[1], domain, timeout)
wildcard_info = certs_list.get('*')
if wildcard_info:
cert_match = self.locate_cert(wildcard_info[0],
wildcard_info[1], domain, timeout) or cert_match
if not cert_match:
raise NoCaCertException(u'No CA certs available for %s' % domain, domain)
return ca_bundle_path
def locate_cert(self, cert_id, location, domain, timeout):
"""
Makes sure the SSL cert specified has been added to the CA cert
bundle that is present on the machine
:param cert_id:
The identifier for CA cert(s). For those provided by the channel
system, this will be an md5 of the contents of the cert(s). For
user-provided certs, this is something they provide.
:param location:
An http(s) URL, or absolute filesystem path to the CA cert(s)
:param domain:
The domain to ensure there is a CA cert for
:param timeout:
The int timeout for downloading the CA cert from the channel
:return:
If the cert specified (by cert_id) is present on the machine and
part of the Package Control.ca-bundle file in the User package folder
"""
ca_list_path = os.path.join(sublime.packages_path(), 'User', 'Package Control.ca-list')
if not os.path.exists(ca_list_path) or os.stat(ca_list_path).st_size == 0:
list_contents = read_package_file('Package Control', 'Package Control.ca-list')
if not list_contents:
raise NoCaCertException(u'Unable to copy distributed Package Control.ca-list', domain)
with open_compat(ca_list_path, 'w') as f:
f.write(list_contents)
ca_certs = []
with open_compat(ca_list_path, 'r') as f:
ca_certs = json.loads(read_compat(f))
if not cert_id in ca_certs:
if str(location) != '':
if re.match('^https?://', location):
contents = self.download_cert(cert_id, location, domain,
timeout)
else:
contents = self.load_cert(cert_id, location, domain)
if contents:
self.save_cert(cert_id, contents)
return True
return False
return True
def download_cert(self, cert_id, url, domain, timeout):
"""
Downloads CA cert(s) from a URL
:param cert_id:
The identifier for CA cert(s). For those provided by the channel
system, this will be an md5 of the contents of the cert(s). For
user-provided certs, this is something they provide.
:param url:
An http(s) URL to the CA cert(s)
:param domain:
The domain to ensure there is a CA cert for
:param timeout:
The int timeout for downloading the CA cert from the channel
:return:
The contents of the CA cert(s)
"""
cert_downloader = self.__class__(self.settings)
if self.settings.get('debug'):
console_write(u"Downloading CA cert for %s from \"%s\"" % (domain, url), True)
return cert_downloader.download(url,
'Error downloading CA certs for %s.' % domain, timeout, 1)
def load_cert(self, cert_id, path, domain):
"""
Copies CA cert(s) from a file path
:param cert_id:
The identifier for CA cert(s). For those provided by the channel
system, this will be an md5 of the contents of the cert(s). For
user-provided certs, this is something they provide.
:param path:
The absolute filesystem path to a file containing the CA cert(s)
:param domain:
The domain name the cert is for
:return:
The contents of the CA cert(s)
"""
if os.path.exists(path):
if self.settings.get('debug'):
console_write(u"Copying CA cert for %s from \"%s\"" % (domain, path), True)
with open_compat(path, 'rb') as f:
return f.read()
else:
raise NoCaCertException(u"Unable to find CA cert for %s at \"%s\"" % (domain, path), domain)
def save_cert(self, cert_id, contents):
"""
Saves CA cert(s) to the Package Control.ca-bundle
:param cert_id:
The identifier for CA cert(s). For those provided by the channel
system, this will be an md5 of the contents of the cert(s). For
user-provided certs, this is something they provide.
:param contents:
The contents of the CA cert(s)
"""
ca_bundle_path = os.path.join(sublime.packages_path(), 'User', 'Package Control.ca-bundle')
with open_compat(ca_bundle_path, 'ab') as f:
f.write(b"\n" + contents)
ca_list_path = os.path.join(sublime.packages_path(), 'User', 'Package Control.ca-list')
with open_compat(ca_list_path, 'r') as f:
ca_certs = json.loads(read_compat(f))
ca_certs.append(cert_id)
with open_compat(ca_list_path, 'w') as f:
f.write(json.dumps(ca_certs, indent=4))

View File

@@ -0,0 +1,81 @@
import os
import subprocess
from ..console_write import console_write
from ..cmd import create_cmd
from .non_clean_exit_error import NonCleanExitError
from .binary_not_found_error import BinaryNotFoundError
class CliDownloader(object):
"""
Base for downloaders that use a command line program
:param settings:
A dict of the various Package Control settings. The Sublime Text
Settings API is not used because this code is run in a thread.
"""
def __init__(self, settings):
self.settings = settings
def clean_tmp_file(self):
if os.path.exists(self.tmp_file):
os.remove(self.tmp_file)
def find_binary(self, name):
"""
Finds the given executable name in the system PATH
:param name:
The exact name of the executable to find
:return:
The absolute path to the executable
:raises:
BinaryNotFoundError when the executable can not be found
"""
dirs = os.environ['PATH'].split(os.pathsep)
if os.name != 'nt':
# This is mostly for OS X, which seems to launch ST with a
# minimal set of environmental variables
dirs.append('/usr/local/bin')
for dir_ in dirs:
path = os.path.join(dir_, name)
if os.path.exists(path):
return path
raise BinaryNotFoundError('The binary %s could not be located' % name)
def execute(self, args):
"""
Runs the executable and args and returns the result
:param args:
A list of the executable path and all arguments to be passed to it
:return:
The text output of the executable
:raises:
NonCleanExitError when the executable exits with an error
"""
if self.settings.get('debug'):
console_write(u"Trying to execute command %s" % create_cmd(args), True)
proc = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = proc.stdout.read()
self.stderr = proc.stderr.read()
returncode = proc.wait()
if returncode != 0:
error = NonCleanExitError(returncode)
error.stderr = self.stderr
error.stdout = output
raise error
return output

View File

@@ -0,0 +1,267 @@
import tempfile
import re
import os
from ..console_write import console_write
from ..open_compat import open_compat, read_compat
from .cli_downloader import CliDownloader
from .non_clean_exit_error import NonCleanExitError
from .rate_limit_exception import RateLimitException
from .downloader_exception import DownloaderException
from .cert_provider import CertProvider
from .limiting_downloader import LimitingDownloader
from .caching_downloader import CachingDownloader
class CurlDownloader(CliDownloader, CertProvider, LimitingDownloader, CachingDownloader):
"""
A downloader that uses the command line program curl
:param settings:
A dict of the various Package Control settings. The Sublime Text
Settings API is not used because this code is run in a thread.
:raises:
BinaryNotFoundError: when curl can not be found
"""
def __init__(self, settings):
self.settings = settings
self.curl = self.find_binary('curl')
def close(self):
"""
No-op for compatibility with UrllibDownloader and WinINetDownloader
"""
pass
def download(self, url, error_message, timeout, tries, prefer_cached=False):
"""
Downloads a URL and returns the contents
:param url:
The URL to download
:param error_message:
A string to include in the console error that is printed
when an error occurs
:param timeout:
The int number of seconds to set the timeout to
:param tries:
The int number of times to try and download the URL in the case of
a timeout or HTTP 503 error
:param prefer_cached:
If a cached version should be returned instead of trying a new request
:raises:
NoCaCertException: when no CA certs can be found for the url
RateLimitException: when a rate limit is hit
DownloaderException: when any other download error occurs
:return:
The string contents of the URL
"""
if prefer_cached:
cached = self.retrieve_cached(url)
if cached:
return cached
self.tmp_file = tempfile.NamedTemporaryFile().name
command = [self.curl, '--user-agent', self.settings.get('user_agent'),
'--connect-timeout', str(int(timeout)), '-sSL',
# Don't be alarmed if the response from the server does not select
# one of these since the server runs a relatively new version of
# OpenSSL which supports compression on the SSL layer, and Apache
# will use that instead of HTTP-level encoding.
'--compressed',
# We have to capture the headers to check for rate limit info
'--dump-header', self.tmp_file]
request_headers = self.add_conditional_headers(url, {})
for name, value in request_headers.items():
command.extend(['--header', "%s: %s" % (name, value)])
secure_url_match = re.match('^https://([^/]+)', url)
if secure_url_match != None:
secure_domain = secure_url_match.group(1)
bundle_path = self.check_certs(secure_domain, timeout)
command.extend(['--cacert', bundle_path])
debug = self.settings.get('debug')
if debug:
command.append('-v')
http_proxy = self.settings.get('http_proxy')
https_proxy = self.settings.get('https_proxy')
proxy_username = self.settings.get('proxy_username')
proxy_password = self.settings.get('proxy_password')
if debug:
console_write(u"Curl Debug Proxy", True)
console_write(u" http_proxy: %s" % http_proxy)
console_write(u" https_proxy: %s" % https_proxy)
console_write(u" proxy_username: %s" % proxy_username)
console_write(u" proxy_password: %s" % proxy_password)
if http_proxy or https_proxy:
command.append('--proxy-anyauth')
if proxy_username or proxy_password:
command.extend(['-U', u"%s:%s" % (proxy_username, proxy_password)])
if http_proxy:
os.putenv('http_proxy', http_proxy)
if https_proxy:
os.putenv('HTTPS_PROXY', https_proxy)
command.append(url)
error_string = None
while tries > 0:
tries -= 1
try:
output = self.execute(command)
with open_compat(self.tmp_file, 'r') as f:
headers_str = read_compat(f)
self.clean_tmp_file()
message = 'OK'
status = 200
headers = {}
for header in headers_str.splitlines():
if header[0:5] == 'HTTP/':
message = re.sub('^HTTP/\d\.\d\s+\d+\s*', '', header)
status = int(re.sub('^HTTP/\d\.\d\s+(\d+)(\s+.*)?$', '\\1', header))
continue
if header.strip() == '':
continue
name, value = header.split(':', 1)
headers[name.lower()] = value.strip()
if debug:
self.print_debug(self.stderr.decode('utf-8'))
self.handle_rate_limit(headers, url)
if status not in [200, 304]:
e = NonCleanExitError(22)
e.stderr = "%s %s" % (status, message)
raise e
output = self.cache_result('get', url, status, headers, output)
return output
except (NonCleanExitError) as e:
# Stderr is used for both the error message and the debug info
# so we need to process it to extra the debug info
if self.settings.get('debug'):
if hasattr(e.stderr, 'decode'):
e.stderr = e.stderr.decode('utf-8')
e.stderr = self.print_debug(e.stderr)
self.clean_tmp_file()
if e.returncode == 22:
code = re.sub('^.*?(\d+)([\w\s]+)?$', '\\1', e.stderr)
if code == '503' and tries != 0:
# GitHub and BitBucket seem to rate limit via 503
error_string = u'Downloading %s was rate limited' % url
if tries:
error_string += ', trying again'
if debug:
console_write(error_string, True)
continue
download_error = u'HTTP error ' + code
elif e.returncode == 6:
download_error = u'URL error host not found'
elif e.returncode == 28:
# GitHub and BitBucket seem to time out a lot
error_string = u'Downloading %s timed out' % url
if tries:
error_string += ', trying again'
if debug:
console_write(error_string, True)
continue
else:
download_error = e.stderr.rstrip()
error_string = u'%s %s downloading %s.' % (error_message, download_error, url)
break
raise DownloaderException(error_string)
def supports_ssl(self):
"""
Indicates if the object can handle HTTPS requests
:return:
If the object supports HTTPS requests
"""
return True
def print_debug(self, string):
"""
Takes debug output from curl and groups and prints it
:param string:
The complete debug output from curl
:return:
A string containing any stderr output
"""
section = 'General'
last_section = None
output = ''
for line in string.splitlines():
# Placeholder for body of request
if line and line[0:2] == '{ ':
continue
if line and line[0:18] == '} [data not shown]':
continue
if len(line) > 1:
subtract = 0
if line[0:2] == '* ':
section = 'General'
subtract = 2
elif line[0:2] == '> ':
section = 'Write'
subtract = 2
elif line[0:2] == '< ':
section = 'Read'
subtract = 2
line = line[subtract:]
# If the line does not start with "* ", "< ", "> " or " "
# then it is a real stderr message
if subtract == 0 and line[0:2] != ' ':
output += line.rstrip() + ' '
continue
if line.strip() == '':
continue
if section != last_section:
console_write(u"Curl HTTP Debug %s" % section, True)
console_write(u' ' + line)
last_section = section
return output.rstrip()

View File

@@ -0,0 +1,24 @@
import gzip
import zlib
try:
# Python 3
from io import BytesIO as StringIO
except (ImportError):
# Python 2
from StringIO import StringIO
class DecodingDownloader(object):
"""
A base for downloaders that provides the ability to decode gzipped
or deflated content.
"""
def decode_response(self, encoding, response):
if encoding == 'gzip':
return gzip.GzipFile(fileobj=StringIO(response)).read()
elif encoding == 'deflate':
decompresser = zlib.decompressobj(-zlib.MAX_WBITS)
return decompresser.decompress(response) + decompresser.flush()
return response

View File

@@ -0,0 +1,5 @@
class DownloaderException(Exception):
"""If a downloader could not download a URL"""
def __str__(self):
return self.args[0]

View File

@@ -0,0 +1,9 @@
class HttpError(Exception):
"""If a downloader was able to download a URL, but the result was not a 200 or 304"""
def __init__(self, message, code):
self.code = code
super(HttpError, self).__init__(message)
def __str__(self):
return self.args[0]

View File

@@ -0,0 +1,36 @@
try:
# Python 3
from urllib.parse import urlparse
except (ImportError):
# Python 2
from urlparse import urlparse
from .rate_limit_exception import RateLimitException
class LimitingDownloader(object):
"""
A base for downloaders that checks for rate limiting headers.
"""
def handle_rate_limit(self, headers, url):
"""
Checks the headers of a response object to make sure we are obeying the
rate limit
:param headers:
The dict-like object that contains lower-cased headers
:param url:
The URL that was requested
:raises:
RateLimitException when the rate limit has been hit
"""
limit_remaining = headers.get('x-ratelimit-remaining', '1')
limit = headers.get('x-ratelimit-limit', '1')
if str(limit_remaining) == '0':
hostname = urlparse(url).hostname
raise RateLimitException(hostname, limit)

View File

@@ -0,0 +1,11 @@
from .downloader_exception import DownloaderException
class NoCaCertException(DownloaderException):
"""
An exception for when there is no CA cert for a domain name
"""
def __init__(self, message, domain):
self.domain = domain
super(NoCaCertException, self).__init__(message)

View File

@@ -0,0 +1,13 @@
class NonCleanExitError(Exception):
"""
When an subprocess does not exit cleanly
:param returncode:
The command line integer return code of the subprocess
"""
def __init__(self, returncode):
self.returncode = returncode
def __str__(self):
return repr(self.returncode)

View File

@@ -0,0 +1,5 @@
class NonHttpError(Exception):
"""If a downloader had a non-clean exit, but it was not due to an HTTP error"""
def __str__(self):
return self.args[0]

Some files were not shown because too many files have changed in this diff Show More