diff --git a/sublime/Packages/AAAPackageDev/.gitignore b/sublime/Packages/AAAPackageDev/.gitignore new file mode 100644 index 0000000..ce5880b --- /dev/null +++ b/sublime/Packages/AAAPackageDev/.gitignore @@ -0,0 +1,4 @@ +*.pyc +*.cache +*.sublime-project +*.sublime-workspace \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/.hgignore b/sublime/Packages/AAAPackageDev/.hgignore new file mode 100644 index 0000000..8dd251a --- /dev/null +++ b/sublime/Packages/AAAPackageDev/.hgignore @@ -0,0 +1,16 @@ +syntax: glob + +*.pyc +_*.txt +*.cache +*.sublime-project +*.sublime-workspace +sample-grammar.js +Manifest +MANIFEST + +dist/ +build/ +data/ +Doc/ +_ref/ diff --git a/sublime/Packages/AAAPackageDev/AAA.py b/sublime/Packages/AAAPackageDev/AAA.py new file mode 100644 index 0000000..2b5b562 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/AAA.py @@ -0,0 +1,9 @@ +import sublime + +import os +import sys + +# Makes sublime_lib package available for all packages. +if not os.path.join(sublime.packages_path(), "AAAPackageDev/Lib") in sys.path: + sys.path.append(os.path.join(sublime.packages_path(), "AAAPackageDev/Lib")) + print "[AAAPackageDev] Added sublime_lib to sys.path." diff --git a/sublime/Packages/AAAPackageDev/LICENSE.txt b/sublime/Packages/AAAPackageDev/LICENSE.txt new file mode 100644 index 0000000..af66480 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/LICENSE.txt @@ -0,0 +1 @@ +The license under which this package is released. \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/__init__.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/constants.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/constants.py new file mode 100644 index 0000000..418b24b --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/constants.py @@ -0,0 +1,63 @@ +KEY_UP = "up" +KEY_DOWN = "down" +KEY_RIGHT = "right" +KEY_LEFT = "left" +KEY_INSERT = "insert" +KEY_HOME = "home" +KEY_END = "end" +KEY_PAGEUP = "pageup" +KEY_PAGEDOWN = "pagedown" +KEY_BACKSPACE = "backspace" +KEY_DELETE = "delete" +KEY_TAB = "tab" +KEY_ENTER = "enter" +KEY_PAUSE = "pause" +KEY_ESCAPE = "escape" +KEY_SPACE = "space" +KEY_KEYPAD0 = "keypad0" +KEY_KEYPAD1 = "keypad1" +KEY_KEYPAD2 = "keypad2" +KEY_KEYPAD3 = "keypad3" +KEY_KEYPAD4 = "keypad4" +KEY_KEYPAD5 = "keypad5" +KEY_KEYPAD6 = "keypad6" +KEY_KEYPAD7 = "keypad7" +KEY_KEYPAD8 = "keypad8" +KEY_KEYPAD9 = "keypad9" +KEY_KEYPAD_PERIOD = "keypad_period" +KEY_KEYPAD_DIVIDE = "keypad_divide" +KEY_KEYPAD_MULTIPLY = "keypad_multiply" +KEY_KEYPAD_MINUS = "keypad_minus" +KEY_KEYPAD_PLUS = "keypad_plus" +KEY_KEYPAD_ENTER = "keypad_enter" +KEY_CLEAR = "clear" +KEY_F1 = "f1" +KEY_F2 = "f2" +KEY_F3 = "f3" +KEY_F4 = "f4" +KEY_F5 = "f5" +KEY_F6 = "f6" +KEY_F7 = "f7" +KEY_F8 = "f8" +KEY_F9 = "f9" +KEY_F10 = "f10" +KEY_F11 = "f11" +KEY_F12 = "f12" +KEY_F13 = "f13" +KEY_F14 = "f14" +KEY_F15 = "f15" +KEY_F16 = "f16" +KEY_F17 = "f17" +KEY_F18 = "f18" +KEY_F19 = "f19" +KEY_F20 = "f20" +KEY_SYSREQ = "sysreq" +KEY_BREAK = "break" +KEY_CONTEXT_MENU = "context_menu" +KEY_BROWSER_BACK = "browser_back" +KEY_BROWSER_FORWARD = "browser_forward" +KEY_BROWSER_REFRESH = "browser_refresh" +KEY_BROWSER_STOP = "browser_stop" +KEY_BROWSER_SEARCH = "browser_search" +KEY_BROWSER_FAVORITES = "browser_favorites" +KEY_BROWSER_HOME = "browser_home" \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/path.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/path.py new file mode 100644 index 0000000..4c74b65 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/path.py @@ -0,0 +1,25 @@ +import sublime + +import os + + +FTYPE_EXT_KEYMAP = ".sublime-keymap" +FTYPE_EXT_COMPLETIONS = ".sublime-completions" +FTYPE_EXT_SNIPPET = ".sublime-snippet" +FTYPE_EXT_BUILD = ".sublime-build" +FTYPE_EXT_SETTINGS = ".sublime-settings" +FTYPE_EXT_TMPREFERENCES = ".tmPreferences" +FTYPE_EXT_TMLANGUAGE = ".tmLanguage" + + +def root_at_packages(*leafs): + """Combines leafs with path to Sublime's Packages folder. + """ + return os.path.join(sublime.packages_path(), *leafs) + + +def root_at_data(*leafs): + """Combines leafs with Sublime's ``Data`` folder. + """ + data = os.path.join(os.path.split(sublime.packages_path())[0]) + return os.path.join(data, *leafs) \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/__init__.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/__init__.py new file mode 100644 index 0000000..36ef48c --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/__init__.py @@ -0,0 +1 @@ +from ._view import * \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/_view.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/_view.py new file mode 100644 index 0000000..2ff1a82 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/_view.py @@ -0,0 +1,126 @@ +import contextlib +from sublime import Region + + +def append(view, text): + """Appends text to view.""" + with in_one_edit(view) as edit: + view.insert(edit, view.size(), text) + + +@contextlib.contextmanager +def in_one_edit(view): + """Context manager to group edits in a view. + + Example: + ... + with in_one_edit(view): + ... + ... + """ + try: + edit = view.begin_edit() + yield edit + finally: + view.end_edit(edit) + + +def has_sels(view): + """Returns ``True`` if ``view`` has one selection or more.`` + """ + return len(view.sel()) > 0 + + +def has_file_ext(view, ext): + """Returns ``True`` if view has file extension ``ext``. + ``ext`` may be specified with or without leading ``.``. + """ + if not view.file_name() or not ext.strip().replace('.', ''): + return False + + if not ext.startswith('.'): + ext = '.' + ext + + return view.file_name().endswith(ext) + + +def rowcount(view): + """Returns the number of rows in ``view``. + """ + return view.rowcol(view.size())[0] + 1 + + +def rowwidth(view, row): + """Returns the number of characters of ``row`` in ``view``. + """ + return view.rowcol(view.line(view.text_point(row, 0)).end())[1] + + +def relative_point(view, x=0, y=0, p=None): + """Returns a point (int) to the given coordinates. + + Supports relative (negative) parameters and checks if they are in the + bounds (other than ``View.text_point()``). + + If p (indexable -> ``p[0]``, ``len(p) == 2``; preferrably a tuple) is + specified, x and y parameters are overridden. + """ + if p is not None: + if len(p) != 2: + raise TypeError("Coordinates have 2 dimensions, not %d" % len(p)) + (x, y) = p + row, col = x, y + + # shortcut + if x == -1 and y == -1: + return view.size() + + # calc absolute coords and check if coords are in the bounds + rowc = rowcount(view) + if x < 0: + row = max(rowc + x, 0) + else: + row = min(row, rowc) + + roww = rowwidth(view, row) + if y < 0: + col = max(roww + y, 0) + else: + col = min(col, roww) + + return view.text_point(row, col) + + +def coorded_region(view, reg1=None, reg2=None): + """Returns a region of two coordinate pairs parsed by ``relative_point(view, p=reg1)``. + + The pairs are supporsed to be indexable and have a length of 2. + Tuples are preferred. + + Defaults to the whole buffer (``reg1=(0, 0), reg2=(-1, -1)``). + """ + reg1 = reg1 or (0, 0) + reg2 = reg2 or (-1, -1) + + p1 = relative_point(view, p=reg1) + p2 = relative_point(view, p=reg2) + return Region(p1, p2) + + +def coorded_substr(view, reg1=None, reg2=None): + """Returns the string of two coordinate pairs parsed by ``relative_point(view, p=reg1)``. + + The pairs are supporsed to be indexable and have a length of 2. + Tuples are preferred. + + Defaults to the whole buffer. + """ + return view.substr(coorded_region(view, reg1, reg2)) + + +def get_text(view): + """Returns the whole string of a buffer. + + Alias for ``coorded_substr(view)``. + """ + return coorded_substr(view) diff --git a/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/sel.py b/sublime/Packages/AAAPackageDev/Lib/sublime_lib/view/sel.py new file mode 100644 index 0000000..e69de29 diff --git a/sublime/Packages/AAAPackageDev/Main.sublime-menu b/sublime/Packages/AAAPackageDev/Main.sublime-menu new file mode 100644 index 0000000..773a195 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Main.sublime-menu @@ -0,0 +1,30 @@ +[ + { + "id": "tools", + "children": + [ + { + "id": "packages", + "caption": "Packages", + "children": + [ + { + "caption": "Package Development", + "children": + [ + { "caption": "New Package…", "command": "new_package" }, + { "caption": "Delete Package…", "command": "delete_package" }, + { "caption": "-" }, + { "caption": "New Syntax Definition", "command": "new_syntax_def" }, + { "caption": "New Syntax Definition from Buffer", "command": "new_syntax_def_from_buffer" }, + { "caption": "-" }, + { "caption": "New Raw Snippet…", "command": "new_raw_snippet" }, + { "caption": "New Raw Snippet from Snippet…", "command": "new_raw_snippet_from_snippet" }, + { "caption": "Generate Snippet from Raw Snippet", "command": "generate_snippet_from_raw_snippet" } + ] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/README.rst b/sublime/Packages/AAAPackageDev/README.rst new file mode 100644 index 0000000..790f821 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/README.rst @@ -0,0 +1,190 @@ +============= +AAAPackageDev +============= + +status: beta + +Overview +======== + +AAAPackageDev helps create and edit snippets, completions files, build systems +and other Sublime Text extensions. + +The general workflow looks like this: + +- run ``new_*`` command (``new_raw_snippet``, ``new_completions``, ``new_syntax_def``...) +- edit file (with specific snippets, completions, higlighting, build systems...) +- save file + +AAAPackageDev ``new_*`` commands are typically accessible through the *Command +Palette* (``Ctrl+Shift+P``). + + +Getting Started +=============== + +#. Download and install `AAAPackageDev`_. (See `installation instructions`_ for ``.sublime-package`` files.) +#. Access commands from **Tools | Packages | Package Development** or the *Command Palette* (``Ctrl+Shift+P``). + +.. _AAAPackageDev: https://bitbucket.org/guillermooo/aaapackagedev/downloads/AAAPackageDev.sublime-package +.. _installation instructions: http://sublimetext.info/docs/en/extensibility/packages.html#installation-of-packages + + +Syntax Definition Development +============================= + +In AAAPackageDev, syntax definitions are written in JSON. Because Sublime Text +uses ``.tmLanguage`` files, though, they need to be converted before use. The +conversion is done through the included build system ``JSON to Property List``. + +Creating a New Syntax Definition +******************************** + +#. Create new template (through **Tools | Packages | Package Development**) or the *Command Palette* +#. Select ``JSON to Property List`` build system from **Tools | Build System** or leave as ``Automatic`` +#. Press ``F7`` + + +Other included resources for syntax definition development: + +* Snippets + + +Package Development +=================== + +Resources for package development are in a very early stage. + +Commands +******** + +``new_package`` + Window command. Prompts for a name and creates a new package skeleton in ``Packages``. + +``delete_package`` + Window command. Opens file browser at ``Packages``. + + +.. Completions +.. ----------- +.. +.. * sublime text plugin dev (off by default) +.. Will clutter your completions list in any kind of python dev. +.. To turn on, change scope selector to ``source.python``. + + +Build System Development +======================== + +* Syntax definition for ``.build-system`` files. + + +Key Map Development +=================== + +* Syntax definition for ``.sublime-keymap`` files. +* Completions +* Snippets + + +Snippet Development +=================== + +AAAPackageDev provides a means to edit snippets using snippets. These snippets +are called *raw snippets*. You can use snippets and snippet-like syntax in many +files, but if you want to create ``.sublime-snippet`` files, you need to convert +raw snippets first. This converion is done with a command. + +Inside ``AAAPackageDev/Support`` you will find a ``.sublime-keymap`` file. +The key bindings in it are included for reference. If you want them to work, +you need to copy the contents over to your personal ``.sublime-keymap`` file +under ``Packages/User``. + +Creating Snippets +***************** + +#. Create new raw snippet with included commands (**Tools | Packages | Package Development** or *Command Palette*) +#. Edit snippet +#. If needed, convert to ``.sublime-snippet`` with included command + +You can use raw snippets directly in some files, like ``.sublime-completions`` files. + + +Completions Development +======================= + +* Syntax definition for ``.sublime-completions`` files +* Snippets + +You can use raw snippets directly in the ``contents`` element of a trigger-based +completion. + + +Settings File Development +========================= + +* Syntax definition for ``.sublime-settings`` files +* Snippets + + +JSON and Property List Conversion +================================= + +If you need to parse a ``.plist`` into a ``.json`` file or vice versa AAAPackageDev +can also be of help. + +Commands +******** + +``json_to_plist`` (Palette: ``JSON to Property List``) + This command has already been mentioned in the Syntax Definition section, but it + is not stated that this command in fact works for almost any JSON file you can imagine. + + It considers the current file's filename and adjusts the target filename accordingly. + + * ``I am json.json`` will be parsed into ``I am json.plist``. + * ``I am json.JSON-propertyList`` will be parsed into ``I am json.propertyList``. + +``plist_to_json`` (Palette: ``Property List to JSON``) + This command is just the reverse of the above. Considers the current file's filename + similarly and adjusts the target filename. However, if your file's extension is not + ``.plist`` you need the doctype `` or ) result in unpredictable + behavior. Floats types ( or ) tend to lose precision when being cast into + Python data types. + + * ``I am json.plist`` will be parsed into ``I am json.json``. + * ``I am json.propertyList`` will be parsed into ``I am json.JSON-propertyList`` *only + if the doctype* `` + + source.sublimekeymap + args + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context Entry.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context Entry.sublime-snippet new file mode 100644 index 0000000..a84a970 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context Entry.sublime-snippet @@ -0,0 +1,5 @@ + + + source.sublimekeymap + c + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context.sublime-snippet new file mode 100644 index 0000000..5b1acc0 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Context.sublime-snippet @@ -0,0 +1,8 @@ + + + source.sublimekeymap + ctx + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Simple Key Binding.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Simple Key Binding.sublime-snippet new file mode 100644 index 0000000..487412d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Key Bindings/Simple Key Binding.sublime-snippet @@ -0,0 +1,8 @@ + + + source.sublimekeymap + k + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Settings Development/Settings Development.sublime-completions b/sublime/Packages/AAAPackageDev/Snippets/Settings Development/Settings Development.sublime-completions new file mode 100644 index 0000000..587034d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Settings Development/Settings Development.sublime-completions @@ -0,0 +1,13 @@ +{ + "scope": "source.sublime-settings", + + "completions": [ + { "trigger": "s", "contents": "\"$1\":$0" }, + { "trigger": "i", "contents": "\"$1\":$0" }, + + { "trigger": "ss", "contents": "\"$1\": {$0}" }, + { "trigger": "ii", "contents": "\"$1\": {$0}" }, + + { "trigger": "arr", "contents": "[$0]" } + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Snippet Development/Snippet Development.sublime-completions b/sublime/Packages/AAAPackageDev/Snippets/Snippet Development/Snippet Development.sublime-completions new file mode 100644 index 0000000..14a281e --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Snippet Development/Snippet Development.sublime-completions @@ -0,0 +1,14 @@ +{ + "scope": "source.sublimesnippetraw", + + "completions": [ + { "trigger": "f", "contents": "\\$${1:field_name}" }, + { "trigger": "i", "contents": "\\$${1:field_name}" }, + + { "trigger": "ff", "contents": "\\${${1:1}:${2:some_text}}" }, + { "trigger": "ii", "contents": "\\${${1:1}:${2:some_text}}" }, + + { "trigger": "fff", "contents": "\\${${1:1}/${2:search_text}/${3:replacement_text}/$4}$0" }, + { "trigger": "iii", "contents": "\\${${1:1}/${2:search_text}/${3:replacement_text}/$4}$0" } + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/(repoit) Repository Item.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/(repoit) Repository Item.sublime-snippet new file mode 100644 index 0000000..1fde5b6 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/(repoit) Repository Item.sublime-snippet @@ -0,0 +1,8 @@ + + + repoit + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/bcaptures-(beginCaptures).sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/bcaptures-(beginCaptures).sublime-snippet new file mode 100644 index 0000000..70b924f --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/bcaptures-(beginCaptures).sublime-snippet @@ -0,0 +1,7 @@ + + + bcaptures + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/begin.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/begin.sublime-snippet new file mode 100644 index 0000000..046a1ad --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/begin.sublime-snippet @@ -0,0 +1,9 @@ + + + begin + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/capture.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/capture.sublime-snippet new file mode 100644 index 0000000..60c443e --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/capture.sublime-snippet @@ -0,0 +1,5 @@ + + + capture + source.json-tmlanguage + diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/captures.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/captures.sublime-snippet new file mode 100644 index 0000000..508c7f8 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/captures.sublime-snippet @@ -0,0 +1,7 @@ + + + captures + source.json-tmlanguage + diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/comment.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/comment.sublime-snippet new file mode 100644 index 0000000..1c69e2d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/comment.sublime-snippet @@ -0,0 +1,5 @@ + + + comment + source.json-tmlaguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ecaptures-(endCaptures).sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ecaptures-(endCaptures).sublime-snippet new file mode 100644 index 0000000..c83dd98 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ecaptures-(endCaptures).sublime-snippet @@ -0,0 +1,7 @@ + + + ecaptures + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ftypes-(fileTypes).sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ftypes-(fileTypes).sublime-snippet new file mode 100644 index 0000000..145f94c --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/ftypes-(fileTypes).sublime-snippet @@ -0,0 +1,5 @@ + + + ftypes + source.json-tmlanguage + diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/include.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/include.sublime-snippet new file mode 100644 index 0000000..2b9e6d5 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/include.sublime-snippet @@ -0,0 +1,5 @@ + + + include + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/key.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/key.sublime-snippet new file mode 100644 index 0000000..fc8b177 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/key.sublime-snippet @@ -0,0 +1,5 @@ + + + key + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/match.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/match.sublime-snippet new file mode 100644 index 0000000..fd4350b --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/match.sublime-snippet @@ -0,0 +1,7 @@ + + + match + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/patterns.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/patterns.sublime-snippet new file mode 100644 index 0000000..2a146c0 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/patterns.sublime-snippet @@ -0,0 +1,6 @@ + + + patterns + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/repository.sublime-snippet b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/repository.sublime-snippet new file mode 100644 index 0000000..38ceda7 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Snippets/Syntax Definitions/repository.sublime-snippet @@ -0,0 +1,5 @@ + + + repo + source.json-tmlanguage + \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/AAAPackageDev.sublime-commands b/sublime/Packages/AAAPackageDev/Support/AAAPackageDev.sublime-commands new file mode 100644 index 0000000..0bcfa70 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/AAAPackageDev.sublime-commands @@ -0,0 +1,25 @@ +[ + { "caption": "z:AAAPackageDev: New Raw Snippet", "command": "new_raw_snippet" }, + { "caption": "z:AAAPackageDev: New Raw Snippet from Snippet", "command": "new_raw_snippet_from_snippet" }, + { "caption": "z:AAAPackageDev: Generate Snippet from Raw Snippet", "command": "generate_snippet_from_raw_snippet" }, + + { "caption": "z:AAAPackageDev: New Syntax Definition", "command": "new_syntax_def" }, + { "caption": "z:AAAPackageDev: New Syntax Definition from Buffer", "command": "new_syntax_def_from_buffer" }, + + { "caption": "z:AAAPackageDev: JSON to Property List", "command": "json_to_plist" }, + { "caption": "z:AAAPackageDev: Property List to JSON", "command": "plist_to_json" }, + + { "caption": "z:AAAPackageDev: New Settings File", "command": "new_settings" }, + + { "caption": "z:AAAPackageDev: New Completions File", "command": "new_completions" }, + + { "caption": "z:AAAPackageDev: New Commands File", "command": "new_commands_file" }, + + { "caption": "z:AAAPackageDev: New Build System", "command": "new_build_system2" }, + + { "caption": "z:AAAPackageDev: New Plugin", "command": "new_plugin" }, + + { "caption": "z:AAAPackageDev: New Package", "command": "new_package" }, + { "caption": "z:AAAPackageDev: Delete Package", "command": "delete_package" } + +] diff --git a/sublime/Packages/AAAPackageDev/Support/API/API.sublime-completions b/sublime/Packages/AAAPackageDev/Support/API/API.sublime-completions new file mode 100644 index 0000000..dab44bb --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/API/API.sublime-completions @@ -0,0 +1,138 @@ +{ + "scope": "source.off", + + "completions": [ + + { "trigger": "sublime", "contents": "sublime" }, + { "trigger": "sublime_plugin", "contents": "sublime_plugin" }, + + + {"trigger": "set_timeout", "contents": "set_timeout(${1:callback}, ${2:delay})" }, + {"trigger": "status_message", "contents": "status_message(${1:string})" }, + {"trigger": "error_message", "contents": "error_message(${1:string})" }, + {"trigger": "load_settings", "contents": "load_settings(${1:base_name})" }, + {"trigger": "save_settings", "contents": "save_settings(${1:base_name})" }, + {"trigger": "windows", "contents": "windows()" }, + {"trigger": "active_window", "contents": "active_window()" }, + {"trigger": "packages_path", "contents": "packages_path()" }, + {"trigger": "installed_packages_path", "contents": "installed_packages_path()" }, + {"trigger": "get_clipboard", "contents": "get_clipboard()" }, + {"trigger": "set_clipboard", "contents": "set_clipboard(${1:string})" }, + {"trigger": "log_commands", "contents": "log_commands(${1:flag})" }, + + + { "trigger": "id", "contents": "id()" }, + { "trigger": "buffer_id", "contents": "buffer_id()" }, + { "trigger": "file_name", "contents": "file_name()" }, + { "trigger": "name", "contents": "name()" }, + { "trigger": "set_name", "contents": "set_name(${1:name})" }, + { "trigger": "is_loading", "contents": "is_loading()" }, + { "trigger": "is_dirty", "contents": "is_dirty()" }, + { "trigger": "is_read_only", "contents": "is_read_only()" }, + { "trigger": "set_read_only", "contents": "set_read_only(${1:value})" }, + { "trigger": "is_scratch", "contents": "is_scratch()" }, + { "trigger": "set_scratch", "contents": "set_scratch(${1:value})" }, + { "trigger": "settings", "contents": "settings()" }, + { "trigger": "window", "contents": "window()" }, + { "trigger": "run_command", "contents": "run_command(${1:string}, ${2:})" }, + { "trigger": "size", "contents": "size()" }, + { "trigger": "substr", "contents": "substr(${1:region or point})" }, + { "trigger": "begin_edit", "contents": "begin_edit(${1:}, ${2:})" }, + { "trigger": "end_edit", "contents": "end_edit(${1:edit})" }, + { "trigger": "insert", "contents": "insert(${1:edit}, ${2:point}, ${3:string})" }, + { "trigger": "erase", "contents": "erase(${1:edit}, ${2:region})" }, + { "trigger": "replace", "contents": "replace(${1:edit}, ${2:region}, ${3:string})" }, + { "trigger": "sel", "contents": "sel()" }, + { "trigger": "line", "contents": "line(${1:point or region})" }, + { "trigger": "full_line", "contents": "full_line(${1:point or region})" }, + { "trigger": "lines", "contents": "lines(${1:region})" }, + { "trigger": "split_by_newlines", "contents": "split_by_newlines(${1:region})" }, + { "trigger": "word", "contents": "word(${1:point or region})" }, + { "trigger": "find", "contents": "find(${1:pattern}, ${2:fromPosition}, ${3:})" }, + { "trigger": "find_all", "contents": "find_all(${1:pattern}, ${2:}, ${3:}, ${4:})" }, + { "trigger": "rowcol", "contents": "rowcol(${1:point})" }, + { "trigger": "text_point", "contents": "text_point(${1:row}, ${2:col})" }, + { "trigger": "set_syntax_file", "contents": "set_syntax_file(${1:syntax_file})" }, + { "trigger": "extract_scope", "contents": "extract_scope(${1:point})" }, + { "trigger": "scope_name", "contents": "scope_name(${1:point})" }, + { "trigger": "match_selector", "contents": "match_selector(${1:point}, ${2:selector})" }, + { "trigger": "show", "contents": "show(${1:point or region or region_set}, ${2:})" }, + { "trigger": "show_at_center", "contents": "show_at_center(${1:point or region})" }, + { "trigger": "visible_region", "contents": "visible_region()" }, + { "trigger": "add_regions", "contents": "add_regions(${1:key}, [${2:regions}], ${3:scope}, ${4:}, ${5:})" }, + { "trigger": "DRAW_EMPTY", "contents": "DRAW_EMPTY" }, + { "trigger": "HIDE_ON_MINIMAP", "contents": "HIDE_ON_MINIMAP" }, + { "trigger": "DRAW_EMPTY_AS_OVERWRITE", "contents": "DRAW_EMPTY_AS_OVERWRITE" }, + { "trigger": "DRAW_OUTLINED", "contents": "DRAW_OUTLINED" }, + { "trigger": "PERSISTENT", "contents": "PERSISTENT" }, + { "trigger": "HIDDEN", "contents": "HIDDEN" }, + { "trigger": "get_regions", "contents": "get_regions(${1:key})" }, + { "trigger": "erase_regions", "contents": "erase_regions(${1:key})" }, + { "trigger": "set_status", "contents": "set_status(${1:key}, ${2:value})" }, + { "trigger": "get_status", "contents": "get_status(${1:key})" }, + { "trigger": "erase_status", "contents": "erase_status(${1:key})" }, + + + { "trigger": "clear", "contents": "clear()" }, + { "trigger": "add", "contents": "add(${1:region})" }, + { "trigger": "add_all", "contents": "add_all(${1:region_set})" }, + { "trigger": "subtract", "contents": "subtract(${1:region})" }, + { "trigger": "contains", "contents": "contains(${1:region})" }, + + + { "trigger": "Region", "contents": "Region(${1:a}, ${2:b})" }, + + + { "trigger": "begin", "contents": "begin()" }, + { "trigger": "end", "contents": "end()" }, + { "trigger": "size", "contents": "size()" }, + { "trigger": "empty", "contents": "empty()" }, + { "trigger": "cover", "contents": "cover(${1:region})" }, + { "trigger": "intersection", "contents": "intersection(${1:region})" }, + { "trigger": "intersects", "contents": "intersects(${1:region})" }, + { "trigger": "contains", "contents": "contains(${1:region})" }, + { "trigger": "contains", "contents": "contains(${1:point})" }, + + + { "trigger": "id", "contents": "id()" }, + { "trigger": "new_file", "contents": "new_file()" }, + { "trigger": "open_file", "contents": "open_file(file_name, )" }, + { "trigger": "ENCODED_POSITION", "contents": "ENCODED_POSITION" }, + { "trigger": "TRANSIENT", "contents": "TRANSIENT" }, + { "trigger": "active_view", "contents": "active_view()" }, + { "trigger": "run_command", "contents": "run_command(string, )" }, + { "trigger": "show_input_panel", "contents": "show_input_panel(caption, initial_text, on_done, on_change, on_cancel)" }, + { "trigger": "get_output_panel", "contents": "get_output_panel(name)" }, + + + { "trigger": "get", "contents": "get(name)" }, + { "trigger": "get", "contents": "get(name, default)" }, + { "trigger": "set", "contents": "set(name, value)" }, + { "trigger": "erase", "contents": "erase(name)" }, + { "trigger": "has", "contents": "has(name)" }, + + + { "trigger": "on_new", "contents": "on_new(view)" }, + { "trigger": "on_load", "contents": "on_load(view)" }, + { "trigger": "on_close", "contents": "on_close(view)" }, + { "trigger": "on_pre_save", "contents": "on_pre_save(view)" }, + { "trigger": "on_post_save", "contents": "on_post_save(view)" }, + { "trigger": "on_modified", "contents": "on_modified(view)" }, + { "trigger": "on_selection_modified", "contents": "on_selection_modified(view)" }, + { "trigger": "on_activated", "contents": "on_activated(view)" }, + { "trigger": "on_deactivated", "contents": "on_deactivated(view)" }, + { "trigger": "on_query_context", "contents": "on_query_context(view, key, operator, operand, match_all)" }, + "OP_EQUAL", + "OP_NOT_EQUAL", + "OP_REGEX_MATCH", + "OP_NOT_REGEX_MATCH", + "OP_REGEX_CONTAINS", + "OP_NOT_REGEX_CONTAINS", + + { "trigger": "run", "contents": "run()" }, + { "trigger": "is_enabled", "contents": "is_enabled()" }, + + + { "trigger": "run", "contents": "run(edit, )" } + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Comments.tmPreferences b/sublime/Packages/AAAPackageDev/Support/Comments.tmPreferences new file mode 100644 index 0000000..20dc4ee --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Comments.tmPreferences @@ -0,0 +1,36 @@ + + + + + name + Comments + scope + source.sublime-settings + settings + + shellVariables + + + name + TM_COMMENT_START + value + // + + + name + TM_COMMENT_START_2 + value + /* + + + name + TM_COMMENT_END_2 + value + */ + + + + uuid + A67A8BD9-A951-406F-9175-018DD4B52FD1 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Default.sublime-keymap b/sublime/Packages/AAAPackageDev/Support/Default.sublime-keymap new file mode 100644 index 0000000..e7b4bf1 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Default.sublime-keymap @@ -0,0 +1,17 @@ +[ + { + "keys": ["ctrl+s"], "command": "generate_snippet_from_raw_snippet", + "context": + [ + { "key": "selector", "operator": "equal", "operand": "source.sublimesnippetraw" } + ] + }, + + { + "keys": ["ctrl+shift+s"], "command": "copy_and_instert_raw_snippet", + "context": + [ + { "key": "selector", "operator": "equal", "operand": "source.sublimesnippetraw" } + ] + } +] \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Generic Array.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Generic Array.JSON-tmLanguage new file mode 100644 index 0000000..3550c99 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Generic Array.JSON-tmLanguage @@ -0,0 +1,26 @@ +{ "name": "JSON Generic Array", + + "scopeName": "source.jsongenericarray", + + "patterns": [ + { "include": "#genericArray" } + ], + + "repository": { + + "genericArray": { + "begin":"\\[", + "beginCaptures": { + "1": { "name": "punctuation.definition.array.start.jsongenericarray"} + }, + "end": "\\]", + "contentName": "meta.definition.array.jsongenericarray", + "patterns": [ + { "include": "source.jsongenericarrayelements" }, + { "include": "#genericArray" } + ] + } + }, + + "uuid": "8a5a7ee7-e39f-46ff-96ba-0691d65e946b" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Generic Array.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Generic Array.tmLanguage new file mode 100644 index 0000000..51ab4fd --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Generic Array.tmLanguage @@ -0,0 +1,50 @@ + + + + + name + JSON Generic Array + patterns + + + include + #genericArray + + + repository + + genericArray + + begin + \[ + beginCaptures + + 1 + + name + punctuation.definition.array.start.jsongenericarray + + + contentName + meta.definition.array.jsongenericarray + end + \] + patterns + + + include + source.jsongenericarrayelements + + + include + #genericArray + + + + + scopeName + source.jsongenericarray + uuid + 8a5a7ee7-e39f-46ff-96ba-0691d65e946b + + diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.JSON-tmLanguage new file mode 100644 index 0000000..4ee93ab --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.JSON-tmLanguage @@ -0,0 +1,41 @@ +{ "name": "JSON Generic Array Elements", + + "scopeName": "source.jsongenericarrayelements", + + "patterns": [ + { "include": "#string" }, + { "include": "#numericConstants" }, + { "include": "#booleanConstants" } + ], + + "repository": { + + "string": { + "begin":"\"", + "end": "\"", + "patterns": [ + { "match": "\\\\[\"tnr]", + "captures": { + "0": { "name": "constant.character.escape.jsongenericarrayelements" } + } + }, + { "include": "source.sublimesnippetraw" }, + { "name": "string.jsongenericarrayelements", + "match": ".+?" + } + ] + }, + + "numericConstants": { + "match": "\\d+(?:\\.\\d+)?", + "name": "constant.numeric.jsongenericarrayelements" + }, + + "booleanConstants": { + "match": "true|false", + "name": "constant.numeric.boolean.jsongenericarrayelements" + } + }, + + "uuid": "6c6128dc-0dcc-4a79-8adb-35bf12199d7f" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.tmLanguage new file mode 100644 index 0000000..6523dad --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic Array Elements.tmLanguage @@ -0,0 +1,76 @@ + + + + + name + JSON Generic Array Elements + patterns + + + include + #string + + + include + #numericConstants + + + include + #booleanConstants + + + repository + + booleanConstants + + match + true|false + name + constant.numeric.boolean.jsongenericarrayelements + + numericConstants + + match + \d+(?:\.\d+)? + name + constant.numeric.jsongenericarrayelements + + string + + begin + " + end + " + patterns + + + captures + + 0 + + name + constant.character.escape.jsongenericarrayelements + + + match + \\["tnr] + + + include + source.sublimesnippetraw + + + match + .+? + name + string.jsongenericarrayelements + + + + + scopeName + source.jsongenericarrayelements + uuid + 6c6128dc-0dcc-4a79-8adb-35bf12199d7f + + diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.JSON-tmLanguage new file mode 100644 index 0000000..d24d23d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.JSON-tmLanguage @@ -0,0 +1,52 @@ +{ "name": "Json Generic Object Elements", + "scopeName": "source.jsongenericobject", + "patterns": [ + { "include": "#key" }, + { "include": "#typeNumber" }, + { "include": "#typeBool" }, + { "include": "#typeString" }, + { "include": "#typeList" }, + { "include": "#typeObject" } + ], + "repository": { + "key": { + "match": "(\".+?\")\\s*(:)", + "captures": { + "1": { "name": "string.generic.key.jsongenericobject" } + } + }, + "typeNumber": { + "match": "[0-9]+(?:.[0-9]+)?(?:[eE][+-]?[0-9]+)?", + "name": "constant.numeric.jsongenericobject" + }, + "typeBool": { + "match": "\\b(?:true|false)\\b", + "name": "constant.numeric.jsongenericobject" + }, + "typeString": { + "name": "string.quoted.double.jsongenericobject", + "begin": "\"", + "end": "\"", + "patterns": [ + { "include": "source.jsonstring" } + ] + }, + "typeList": { + "name": "list.jsongenericobject", + "begin": "\\[", + "end": "]", + "patterns": [ + { "include": "$self" } + ] + }, + "typeObject": { + "name": "object.jsongenericobject", + "begin": "\\{", + "end": "}", + "patterns": [ + { "include": "$self" } + ] + } + }, + "uuid": "4317eb4e-b7ae-496d-a689-7d8ea3711204" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.tmLanguage new file mode 100644 index 0000000..d7be827 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic Object.tmLanguage @@ -0,0 +1,117 @@ + + + + + name + Json Generic Object Elements + patterns + + + include + #key + + + include + #typeNumber + + + include + #typeBool + + + include + #typeString + + + include + #typeList + + + include + #typeObject + + + repository + + key + + captures + + 1 + + name + string.generic.key.jsongenericobject + + + match + (".+?")\s*(:) + + typeBool + + match + \b(?:true|false)\b + name + constant.numeric.jsongenericobject + + typeList + + begin + \[ + end + ] + name + list.jsongenericobject + patterns + + + include + $self + + + + typeNumber + + match + [0-9]+(?:.[0-9]+)?(?:[eE][+-]?[0-9]+)? + name + constant.numeric.jsongenericobject + + typeObject + + begin + \{ + end + } + name + object.jsongenericobject + patterns + + + include + $self + + + + typeString + + begin + " + end + " + name + string.quoted.double.jsongenericobject + patterns + + + include + source.jsonstring + + + + + scopeName + source.jsongenericobject + uuid + 4317eb4e-b7ae-496d-a689-7d8ea3711204 + + diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.JSON-tmLanguage new file mode 100644 index 0000000..43759ac --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.JSON-tmLanguage @@ -0,0 +1,16 @@ +{ "name": "JSON String Content", + "scopeName": "source.jsonstring", + "patterns": [ + { "include": "#escapeSequence" }, + { "name": "string.double.quoted.jsonstring", + "match": ".+?" + } + ], + "repository": { + "escapeSequence": { + "match": "\\\\(?:\"|/|\\\\|[bnfrt]|u[0-9a-fA-F]{4})", + "name": "entity.other.attribute-name.jsonstring" + } + }, + "uuid": "b94a984c-7a66-4c96-a828-dc8e7a6dafe7" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.tmLanguage b/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.tmLanguage new file mode 100644 index 0000000..71a0fee --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON Generic String Content.tmLanguage @@ -0,0 +1,35 @@ + + + + + name + JSON String Content + patterns + + + include + #escapeSequence + + + match + .+? + name + string.double.quoted.jsonstring + + + repository + + escapeSequence + + match + \\(?:"|/|\\|[bnfrt]|u[0-9a-fA-F]{4}) + name + entity.other.attribute-name.jsonstring + + + scopeName + source.jsonstring + uuid + b94a984c-7a66-4c96-a828-dc8e7a6dafe7 + + diff --git a/sublime/Packages/AAAPackageDev/Support/JSON to Property List.sublime-build b/sublime/Packages/AAAPackageDev/Support/JSON to Property List.sublime-build new file mode 100644 index 0000000..e1a5570 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/JSON to Property List.sublime-build @@ -0,0 +1,4 @@ +{ + "target": "json_to_plist", + "selector": "source.json, source.json-tmlanguage" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Left.sublime-completions b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Left.sublime-completions new file mode 100644 index 0000000..b0b78f6 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Left.sublime-completions @@ -0,0 +1,16 @@ +{ + "scope": "context.operand.left.sublimekeymap", + + "completions": [ + "num_selections", + "auto_complete_visible", + "selection_empty", + "preceding_text", + "following_text", + "has_prev_field", + "has_next_field", + "panel_visible", + "overlay_visible", + "setting." + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Right.sublime-completions b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Right.sublime-completions new file mode 100644 index 0000000..0d79e1c --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operand Right.sublime-completions @@ -0,0 +1,8 @@ +{ + "scope": "context.operator.name.sublimekeymap", + + "completions": [ + "true", + "false" + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operators.sublime-completions b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operators.sublime-completions new file mode 100644 index 0000000..65bfbc7 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Context Operators.sublime-completions @@ -0,0 +1,12 @@ +{ + "scope": "context.operator.name.sublimekeymap", + + "completions": [ + "equal", + "not_equal", + "regex_match", + "not_regex_match", + "regex_contains", + "not_regex_contains" + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Key Binding Key Sequence.sublime-completions b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Key Binding Key Sequence.sublime-completions new file mode 100644 index 0000000..82b15bd --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Key Bindings/Key Bindings - Key Binding Key Sequence.sublime-completions @@ -0,0 +1,81 @@ +{ + "scope": "meta.array.key.sequence.sublimekeymap", + + "completions": [ + "super+", + "alt+", + "ctrl+", + "shift+", + "ctrl+shift+", + "alt+shift+", + "ctrl+alt+shift+", + "super+ctrl+", + "super+ctrl+shift+", + "super+shift+", + "super+alt+", + "super+alt+shift+", + "up", + "down", + "right", + "left", + "insert", + "home", + "end", + "pageup", + "pagedown", + "backspace", + "delete", + "tab", + "enter", + "pause", + "escape", + "space", + "keypad0", + "keypad1", + "keypad2", + "keypad3", + "keypad4", + "keypad5", + "keypad6", + "keypad7", + "keypad8", + "keypad9", + "keypad_period", + "keypad_divide", + "keypad_multiply", + "keypad_minus", + "keypad_plus", + "keypad_enter", + "clear", + "f1", + "f2", + "f3", + "f4", + "f5", + "f6", + "f7", + "f8", + "f9", + "f10", + "f11", + "f12", + "f13", + "f14", + "f15", + "f16", + "f17", + "f18", + "f19", + "f20", + "sysreq", + "break", + "context_menu", + "browser_back", + "browser_forward", + "browser_refresh", + "browser_stop", + "browser_search", + "browser_favorites", + "browser_home" + ] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Property List to JSON.sublime-build b/sublime/Packages/AAAPackageDev/Support/Property List to JSON.sublime-build new file mode 100644 index 0000000..32a53aa --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Property List to JSON.sublime-build @@ -0,0 +1,4 @@ +{ + "target": "plist_to_json", + "selector": "text.xml" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).JSON-tmLanguage new file mode 100644 index 0000000..0523cdf --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).JSON-tmLanguage @@ -0,0 +1,129 @@ +{ "name": "Regular Expression (Escaped)", + + "scopeName": "source.escapedregexp", + + "patterns": [ + { "include": "#classes" }, + { "include": "#anchorsWithBackslash" }, + { "include": "#allEscapes" }, + { "include": "#anchors" }, + { "include": "#quantifiers" }, + { "include": "#granularQuantifier" }, + { "include": "#operators" }, + { "include": "#sets" }, + { "include": "#groups" } + ], + + "repository": { + + "allEscapes": { + "comment": "Order matters.", + "patterns" : [ + { "include": "#regexpEscapeSequences" }, + { "include": "#regexpEscapedBackslash" }, + { "include": "#jsonEscapeSequences" } + ] + }, + + "regexpEscapeSequences": { + "match": "(?]|<[=!]))" + }, + { "include": "$self" } + ], + "comment": "XXX: Implement named groups, options and yes/no groups." + }, + + "anchorsWithBackslash": { + "match": "(?:\\\\\\\\[AbBZ])", + "name": "entity.other.attribute-name.anchor.escapedregexp" + }, + + "anchors": { + "match": "[$^]", + "name": "entity.other.attribute-name.anchor.escapedregexp" + } + }, + + "uuid": "26c6799e-6824-4926-b2e5-87140300b97b" +} diff --git a/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).tmLanguage b/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).tmLanguage new file mode 100644 index 0000000..cc0f38d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Regular Expression (Escaped).tmLanguage @@ -0,0 +1,275 @@ + + + + + name + Regular Expression (Escaped) + patterns + + + include + #classes + + + include + #anchorsWithBackslash + + + include + #allEscapes + + + include + #anchors + + + include + #quantifiers + + + include + #granularQuantifier + + + include + #operators + + + include + #sets + + + include + #groups + + + repository + + allEscapes + + comment + Order matters. + patterns + + + include + #regexpEscapeSequences + + + include + #regexpEscapedBackslash + + + include + #jsonEscapeSequences + + + + anchors + + match + [$^] + name + entity.other.attribute-name.anchor.escapedregexp + + anchorsWithBackslash + + match + (?:\\\\[AbBZ]) + name + entity.other.attribute-name.anchor.escapedregexp + + classes + + comment + XXX: Add unicode escapes \x00 and escapes within comments. + match + \\\\[dDsSwW] + name + keyword.other.character-class.escapedregexp + + granularQuantifier + + captures + + 1 + + name + keyword.other.punctuation.quantifier.start.escapedregexp + + 2 + + name + constant.numeric.escapedregexp + + 3 + + name + keyword.other.separator.escapedregexp + + 4 + + name + constant.numeric.escapedregexp + + 5 + + name + keyword.other.punctuation.quantifier.end.escapedregexp + + + match + (\{)([0-9]+)(,)?([0-9]+)?(\}) + name + meta.granular.quantifier.escapedregexp + + groups + + begin + \( + beginCaptures + + 0 + + name + string.regexp.group.escapedregexp + + + comment + XXX: Implement named groups, options and yes/no groups. + end + \) + endCaptures + + 0 + + name + string.regexp.group.escapedregexp + + + patterns + + + match + (\?(?:[:=!>]|<[=!])) + name + support.function.assertion.escapedregexp + + + include + $self + + + + jsonEscapeSequences + + match + \\[bfntr"/] + name + entity.other.attribute-name.escape.sequence.json.escapedregexp + + operators + + match + [|.] + name + keyword.other.operator.escapedregexp + + quantifiers + + match + (\+|\*|\?)(\?)? + name + keyword.other.quantifier.escapedregexp + + regexpEscapeSequences + + comment + Escape next char if the slash isn't being escaped itself. + match + (?<!\\\\)\\\\(?:[]^+?*.(){}$\[]) + name + constant.character.escape.sequence.regexp.escapedregexp + + regexpEscapedBackslash + + match + \\\\ + name + constant.character.escape.sequence.regexp.escapedregexp + + sets + + begin + (\[)(\^)?(\])? + beginCaptures + + 1 + + name + keyword.other.set.escapedregexp + + 2 + + name + keyword.other.set.operator.negate.escapedregexp + + 3 + + name + string.set.element.escapedregexp + + + end + ] + endCaptures + + 0 + + name + keyword.other.set.escapedregexp + + + patterns + + + captures + + 1 + + name + keyword.operator.other.set.range.separator.escapedregexp + + + match + [A-Za-z0-9](-)[A-Za-z0-9] + name + support.function.set.range.escapedregexp + + + include + #regexpEscapeSequences + + + include + #classes + + + include + #jsonEscapeSequences + + + match + .*? + name + string.set.element.escapedregexp + + + + + scopeName + source.escapedregexp + uuid + 26c6799e-6824-4926-b2e5-87140300b97b + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Commands.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Commands.JSON-tmLanguage new file mode 100644 index 0000000..f8f0ba3 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Commands.JSON-tmLanguage @@ -0,0 +1,82 @@ +{ "name": "Sublime Text Commands", + + "scopeName": "source.sublimecommands", + + "fileTypes": ["sublime-commands"], + + "patterns": [ + { "begin": "(\\[)", + "beginCaptures": { + "1": { "name": "punctuation.definition.collection.start.sublimecommands" } + }, + "end": "(\\])", + "endCaptures": { + "1": { "name": "punctuation.definition.collection.end.sublimecommands" } + }, + + "patterns": [ + { "include": "#command" }, + { "include": "#args" }, + { "match": "(?$\\s+\\])", + "comment": "XXX" + } + ] + } + ], + + "repository": { + + "args": { + "begin": "\"(args)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.sublimecommands"} + }, + "end": "(?<=\\})", + "name": "meta.definition.attached.command.arguments.sublimecommands", + "patterns": [ + { "include": "source.jsongenericarray" + }, + { "match": "\"([a-zA-Z0-9_]+)\"\\s*:", + "captures": { + "1": { "name": "support.function.array.generic.key.sublimecommands" } + } + }, + { "include": "source.jsongenericarrayelements" + }, + { "match": "true|false|\\d+", + "name": "constant.numeric.sublimecommands" + }, + + { "match": "\\{", + "name": "punctuation.definition.array.keybinding.key.sequence" + } + ] + }, + + "command": { + "begin": "\\{", + "end": "\\}", + "patterns": [ + { "match": "\"(command|caption)\":\\s*\"([^\"]+)\"", + "captures": { + "1": { "name": "keyword.other.sublimecommands" }, + "2": { "name": "string.attached.command.name.sublimecommands" } + } + }, + { "include": "#args" } + ] + } + }, + + "uuid": "f56e1baa-51fc-4791-a9d9-21301f2e3a01" +} diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Commands.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Commands.tmLanguage new file mode 100644 index 0000000..1cde895 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Commands.tmLanguage @@ -0,0 +1,164 @@ + + + + + fileTypes + + sublime-commands + + name + Sublime Text Commands + patterns + + + begin + (\[) + beginCaptures + + 1 + + name + punctuation.definition.collection.start.sublimecommands + + + end + (\]) + endCaptures + + 1 + + name + punctuation.definition.collection.end.sublimecommands + + + patterns + + + include + #command + + + include + #args + + + match + (?<!\}), + name + invalid.illegal.definition.sublimecommands + + + match + ,{2,} + name + invalid.illegal.definition.sublimecommands + + + match + [^, \s] + name + invalid.illegal.definition.sublimecommands + + + comment + XXX + match + ,(?>$\s+\]) + name + invalid.illegal.definition.sublimecommands + + + + + repository + + args + + begin + "(args)"\s*: + beginCaptures + + 1 + + name + keyword.other.sublimecommands + + + end + (?<=\}) + name + meta.definition.attached.command.arguments.sublimecommands + patterns + + + include + source.jsongenericarray + + + captures + + 1 + + name + support.function.array.generic.key.sublimecommands + + + match + "([a-zA-Z0-9_]+)"\s*: + + + include + source.jsongenericarrayelements + + + match + true|false|\d+ + name + constant.numeric.sublimecommands + + + match + \{ + name + punctuation.definition.array.keybinding.key.sequence + + + + command + + begin + \{ + end + \} + patterns + + + captures + + 1 + + name + keyword.other.sublimecommands + + 2 + + name + string.attached.command.name.sublimecommands + + + match + "(command|caption)":\s*"([^"]+)" + + + include + #args + + + + + scopeName + source.sublimecommands + uuid + f56e1baa-51fc-4791-a9d9-21301f2e3a01 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Completions.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.JSON-tmLanguage new file mode 100644 index 0000000..addcd34 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.JSON-tmLanguage @@ -0,0 +1,92 @@ +{ "name": "Sublime Completions", + + "scopeName": "source.sublimecompletions", + + "fileTypes": ["sublime-completions"], + + "patterns": [ + { "include": "#completionsDict" } + ], + + "repository": { + + "completionsDict": { + "begin": "\\{", + "end": "\\}", + "contentName": "meta.completions.dictionary.sublimecompletions", + "patterns": [ + { "include": "#scope" }, + { "include": "#completionsList" } + ] + }, + + "scope": { + "match": "\"(scope)\"\\s*?:\\s*?\"([a-zA-Z0-9. ,-]+)\"", + "captures": { + "1": { "name": "keyword.key.sublimecompletions" }, + "2": { "name": "string.scope.selector.sublimecompletions" } + } + }, + + "completionsList": { + "begin": "\"(completions)\"\\s*?:\\s*?", + "beginCaptures": { + "1" : { "name": "keyword.key.sublimecompletions" } + }, + "end": "(?<=\\])", + "contentName": "meta.completions.array.sublimecompletions", + "patterns": [ + { "match": "\\[" }, + { "include": "#triggerCompletion" }, + { "include": "#simpleCompletion" } + ] + }, + + "simpleCompletion": { + "match": "\"([a-zA-Z0-9_.]+)\"", + "captures": { + "1": { "name": "string.completion.simple.sublimecompletions" } + } + }, + + "triggerCompletion": { + "begin": "\\{", + "end": "\\}", + "contentName": "meta.completion.trigger-based.sublimecompletions", + "patterns": [ + { "match": "\"(trigger)\"\\s*?:\\s*?\"([a-zA-Z0-9_.-]+)\"", + "captures": { + "1": { "name": "support.function.key.sublimecompletions" }, + "2": { "name": "string.trigger.name.sublimecompletions" } + } + }, + + { "begin": "\"(contents)\"\\s*?:\\s*?\"", + "end": "\"", + "beginCaptures": { + "1": { "name": "support.function.key.sublimecompletions" } + }, + "comment": "XXX: rules below are becoming a mess. escaped $ does not work at the moment after escaped backslashes.", + "patterns": [ + { "name": "constant.character.escape.sequence.snippet.sublimecompletions", + "match": "\\\\\\\\(?:\\$)" + }, + { "name": "entity.other.attribute-name.escape.sequence.json.sublimecompletions", + "match": "\\\\(?:[tvbarn\"\\\\])" + }, + { "name": "invalid.illegal.unescaped.characters.sublimecompletions", + "match": "\\$(?!\\{|[0-9A-Za-z])" + }, + { "include": "source.sublimesnippetraw" }, + { "name": "string.snippet.sublimecompletions", + "match": ".*?" + } + ], + "contentName": "source.sublimesnippetraw" + } + ] + } + }, + + "uuid": "3abbb928-3b6a-49b9-903f-150c021accb2" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Completions.sublime-settings b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.sublime-settings new file mode 100644 index 0000000..5a6a7ba --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.sublime-settings @@ -0,0 +1,3 @@ +{ + "extensions": ["sublime-completions"] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Completions.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.tmLanguage new file mode 100644 index 0000000..22dfc3d --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Completions.tmLanguage @@ -0,0 +1,187 @@ + + + + + fileTypes + + sublime-completions + + name + Sublime Completions + patterns + + + include + #completionsDict + + + repository + + completionsDict + + begin + \{ + contentName + meta.completions.dictionary.sublimecompletions + end + \} + patterns + + + include + #scope + + + include + #completionsList + + + + completionsList + + begin + "(completions)"\s*?:\s*? + beginCaptures + + 1 + + name + keyword.key.sublimecompletions + + + contentName + meta.completions.array.sublimecompletions + end + (?<=\]) + patterns + + + match + \[ + + + include + #triggerCompletion + + + include + #simpleCompletion + + + + scope + + captures + + 1 + + name + keyword.key.sublimecompletions + + 2 + + name + string.scope.selector.sublimecompletions + + + match + "(scope)"\s*?:\s*?"([a-zA-Z0-9. ,-]+)" + + simpleCompletion + + captures + + 1 + + name + string.completion.simple.sublimecompletions + + + match + "([a-zA-Z0-9_.]+)" + + triggerCompletion + + begin + \{ + contentName + meta.completion.trigger-based.sublimecompletions + end + \} + patterns + + + captures + + 1 + + name + support.function.key.sublimecompletions + + 2 + + name + string.trigger.name.sublimecompletions + + + match + "(trigger)"\s*?:\s*?"([a-zA-Z0-9_.-]+)" + + + begin + "(contents)"\s*?:\s*?" + beginCaptures + + 1 + + name + support.function.key.sublimecompletions + + + comment + XXX: rules below are becoming a mess. escaped $ does not work at the moment after escaped backslashes. + contentName + source.sublimesnippetraw + end + " + patterns + + + match + \\\\(?:\$) + name + constant.character.escape.sequence.snippet.sublimecompletions + + + match + \\(?:[tvbarn"\\]) + name + entity.other.attribute-name.escape.sequence.json.sublimecompletions + + + match + \$(?!\{|[0-9A-Za-z]) + name + invalid.illegal.unescaped.characters.sublimecompletions + + + include + source.sublimesnippetraw + + + match + .*? + name + string.snippet.sublimecompletions + + + + + + + scopeName + source.sublimecompletions + uuid + 3abbb928-3b6a-49b9-903f-150c021accb2 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.JSON-tmLanguage new file mode 100644 index 0000000..ce96f06 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.JSON-tmLanguage @@ -0,0 +1,182 @@ +{ "name": "Sublime Text Syntax Definition", + + "scopeName": "source.json-tmlanguage", + + "fileTypes": ["json-tmlanguage"], + + "patterns": [ + { "include": "#syntaxName" }, + { "include": "#scopeName" }, + { "include": "#name" }, + { "include": "#fileTypes" }, + { "include": "#patterns" }, + { "include": "#repo" }, + { "include": "#comment" }, + { "include": "#uuid" } + ], + + "repository": { + + "match": { + "begin": "\"(match|begin|end)\"\\s*?:\\s*(\")", + "end": "(\")", + "name": "meta.definition.error.data.json-tmlanguage", + "patterns": [ + { "include": "source.escapedregexp" } + ], + "beginCaptures": { + "1": { "name": "keyword.other.control.json-tmlanguage"}, + "2": { "name": "punctuation.definition.regex.start.json-tmlanguage" } + }, + "endCaptures": { + "1": { "name": "punctuation.definition.regex.end.json-tmlanguage" } + } + }, + + "include": { + "match": "\"(include)\"\\s*?:\\s*?\"(?:(#)([a-zA-Z0-9_-]+)|(\\$)(self)|([A-Za-z0-9.]+))\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "keyword.other.variable.mark.json-tmlanguage" }, + "3": { "name": "string.repository.item.identifier.json-tmlanguage" }, + "4": { "name": "keyword.other.variable.mark.json-tmlanguage" }, + "5": { "name": "support.function.other.variable.mark.json-tmlanguage" }, + "6": { "name": "string.repository.item.identifier.json-tmlanguage" } + } + }, + + "patterns": { + "begin": "\"(patterns)\"\\s*?:\\s*?\\[", + "beginCaptures": { + "1": { "name": "keyword.other.control.json-tmlanguage" } + }, + "end": "\\]", + "patterns": [ + { "include": "#patternsItem" } + ] + }, + + "patternsItem": { + "begin": "\\{", + "end": "\\}", + "patterns": [ + { "include": "#name" }, + { "include": "#match" }, + { "include": "#include" }, + { "include": "#patterns" }, + { "include": "#captures" }, + { "include": "#comment" } + ] + }, + + "fileTypes": { + "begin": "\"(fileTypes)\"\\s*?:\\s*?\\[", + "beginCaptures": { + "1": { "name": "keyword.other.control.json-tmlanguage" } + }, + "end": "\\]", + "patterns": [ + { "include": "source.jsongenericarrayelements" } + + ], + "contentName": "meta.json.generic.array.json.tmlanguage" + }, + + "name": { + "match": "\"((?:content)?[nN]ame)\"\\s*?:\\s*?\"(.+?)\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "string.meta.data.json-tmlanguage" } + } + }, + + "syntaxName": { + "match": "\"(name)\"\\s*?:\\s*?\"(.+?)\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "string.meta.sytax.name.json-tmlanguage" } + } + }, + + "scopeName": { + "match": "\"(scopeName)\"\\s*?:\\s*?\"(.+?)\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "string.meta.scope.name.json-tmlanguage" } + } + }, + + "comment": { + "match": "\"(comment)\"\\s*?:\\s*?\"(.+?)\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "comment.json-tmlanguage" } + } + }, + + "uuid": { + "match": "\"(uuid)\"\\s*?:\\s*?\"([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)\"", + "captures": { + "1": { "name": "keyword.other.control.json-tmlanguage" }, + "2": { "name": "constant.numeric.json-tmlanguage" }, + "3": { "name": "constant.numeric.json-tmlanguage" }, + "4": { "name": "constant.numeric.json-tmlanguage" }, + "5": { "name": "constant.numeric.json-tmlanguage" }, + "6": { "name": "constant.numeric.json-tmlanguage" } + } + }, + + "repo": { + "begin": "\"(repository)\"\\s*?:\\s*?\\{", + "beginCaptures": { + "1": { "name": "keyword.other.control.json-tmlanguage" } + }, + "end": "\\}", + "patterns": [ + { "include": "#repositoryItem" } + ], + "contentName": "meta.repository.json-tmlanguage" + }, + + "repositoryItem": { + "begin": "\"([a-zA-Z0-9_-]+)\"\\s*?:\\s*?\\{", + "beginCaptures": { + "1": { "name": "entity.other.attribute-name.json-tmlanguage" } + }, + "end": "\\}", + "patterns": [ + { "include": "#match" }, + { "include": "#name" }, + { "include": "#patterns" }, + { "include": "#captures" }, + { "include": "#comment" } + ] + }, + + "captures": { + "begin": "\"((?:begin|end)?[cC]aptures)\"\\s*?:\\s*?\\{", + "beginCaptures": { + "1": { "name": "keyword.other.control.json-tmlanguage" } + }, + "end": "\\}", + "patterns": [ + { "include": "#captureItem" } + ], + "contentName": "meta.captures.json-tmlanguage" + }, + + "captureItem": { + "begin": "\"(\\d+)\"\\s+*?:\\s*?\\{", + "beginCaptures": { + "1": { "name": "constant.numeric.capture.name.json-tmlanguage" } + }, + "end": "\\}", + "patterns": [ + { "include": "#name" } + ], + "contentName": "meta.capture.json-tmlanguage" + } + }, + + "uuid": "8c7e3a99-1780-4b72-9ce5-585949c0563e" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.tmLanguage new file mode 100644 index 0000000..a1c9065 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.tmLanguage @@ -0,0 +1,429 @@ + + + + + fileTypes + + json-tmlanguage + + name + Sublime Text Syntax Definition + patterns + + + include + #syntaxName + + + include + #scopeName + + + include + #name + + + include + #fileTypes + + + include + #patterns + + + include + #repo + + + include + #comment + + + include + #uuid + + + repository + + captureItem + + begin + "(\d+)"\s+*?:\s*?\{ + beginCaptures + + 1 + + name + constant.numeric.capture.name.json-tmlanguage + + + contentName + meta.capture.json-tmlanguage + end + \} + patterns + + + include + #name + + + + captures + + begin + "((?:begin|end)?[cC]aptures)"\s*?:\s*?\{ + beginCaptures + + 1 + + name + keyword.other.control.json-tmlanguage + + + contentName + meta.captures.json-tmlanguage + end + \} + patterns + + + include + #captureItem + + + + comment + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + comment.json-tmlanguage + + + match + "(comment)"\s*?:\s*?"(.+?)" + + fileTypes + + begin + "(fileTypes)"\s*?:\s*?\[ + beginCaptures + + 1 + + name + keyword.other.control.json-tmlanguage + + + contentName + meta.json.generic.array.json.tmlanguage + end + \] + patterns + + + include + source.jsongenericarrayelements + + + + include + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + keyword.other.variable.mark.json-tmlanguage + + 3 + + name + string.repository.item.identifier.json-tmlanguage + + 4 + + name + keyword.other.variable.mark.json-tmlanguage + + 5 + + name + support.function.other.variable.mark.json-tmlanguage + + 6 + + name + string.repository.item.identifier.json-tmlanguage + + + match + "(include)"\s*?:\s*?"(?:(#)([a-zA-Z0-9_-]+)|(\$)(self)|([A-Za-z0-9.]+))" + + match + + begin + "(match|begin|end)"\s*?:\s*(") + beginCaptures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + punctuation.definition.regex.start.json-tmlanguage + + + end + (") + endCaptures + + 1 + + name + punctuation.definition.regex.end.json-tmlanguage + + + name + meta.definition.error.data.json-tmlanguage + patterns + + + include + source.escapedregexp + + + + name + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + string.meta.data.json-tmlanguage + + + match + "((?:content)?[nN]ame)"\s*?:\s*?"(.+?)" + + patterns + + begin + "(patterns)"\s*?:\s*?\[ + beginCaptures + + 1 + + name + keyword.other.control.json-tmlanguage + + + end + \] + patterns + + + include + #patternsItem + + + + patternsItem + + begin + \{ + end + \} + patterns + + + include + #name + + + include + #match + + + include + #include + + + include + #patterns + + + include + #captures + + + include + #comment + + + + repo + + begin + "(repository)"\s*?:\s*?\{ + beginCaptures + + 1 + + name + keyword.other.control.json-tmlanguage + + + contentName + meta.repository.json-tmlanguage + end + \} + patterns + + + include + #repositoryItem + + + + repositoryItem + + begin + "([a-zA-Z0-9_-]+)"\s*?:\s*?\{ + beginCaptures + + 1 + + name + entity.other.attribute-name.json-tmlanguage + + + end + \} + patterns + + + include + #match + + + include + #name + + + include + #patterns + + + include + #captures + + + include + #comment + + + + scopeName + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + string.meta.scope.name.json-tmlanguage + + + match + "(scopeName)"\s*?:\s*?"(.+?)" + + syntaxName + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + string.meta.sytax.name.json-tmlanguage + + + match + "(name)"\s*?:\s*?"(.+?)" + + uuid + + captures + + 1 + + name + keyword.other.control.json-tmlanguage + + 2 + + name + constant.numeric.json-tmlanguage + + 3 + + name + constant.numeric.json-tmlanguage + + 4 + + name + constant.numeric.json-tmlanguage + + 5 + + name + constant.numeric.json-tmlanguage + + 6 + + name + constant.numeric.json-tmlanguage + + + match + "(uuid)"\s*?:\s*?"([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)-([a-z0-9]+)" + + + scopeName + source.json-tmlanguage + uuid + 8c7e3a99-1780-4b72-9ce5-585949c0563e + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Key Map.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Key Map.JSON-tmLanguage new file mode 100644 index 0000000..d0b6597 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Key Map.JSON-tmLanguage @@ -0,0 +1,118 @@ +{ "name": "Sublime Text Key Map", + "scopeName": "source.sublimekeymap", + "fileTypes": ["sublime-keymap"], + "patterns": [ + + { "include": "#multiLineComment" }, + { "include": "#lineComment" }, + + { "begin": "(^\\[$)", + "end": "(^\\]$)", + + "patterns": [ + { "include": "#multiLineComment" }, + { "include": "#lineComment" }, + { "include": "#keys" }, + { "include": "#mainKeys" }, + { "include": "#supportKeys" }, + { "include": "#string" }, + { "include": "#numericPrimitives" } + ], + "contentName": "meta.keybinding.collection.sublimekeymap" + } + ], + "repository": { + "keys": { + "begin": "\"(keys)\": \\[", + "beginCaptures": { + "1": { "name": "keyword.other.sublimekeymap"} + }, + "end": "\\],", + "patterns": [ + { "begin": "(\")", + "beginCaptures": { + "1": { "name": "punctuation.keybinding.definition.key.sequence.start.sublimekeymap" } + }, + "end": "(?", + "captures": { + "1": { "name": "entity.other.attribute-name.key.captured.sublimekeymap" } + } + }, + { "match": ".{1}", + "comment": "XXX What's invalid for key names?", + "name": "string.key.literal.sublimekeymap" + } + ], + "contentName": "meta.key.sequence.sublimekeymap" + }, + { "name": "invalid.illegal.key.sequence.sublimekeymap", + "match": "[^\\s,]" + } + ] + }, + "mainKeys": { + "match": "\"(command|args|context|key)\":", + "captures": { + "1": { "name": "keyword.other.sublimekeymap" } + } + }, + "supportKeys": { + "match": "\"([A-z]+?)\":", + "captures": { + "1": { "name": "support.function.sublimekeymap" } + } + }, + "string": { + "begin" : "\"", + "end": "(? + + + + fileTypes + + sublime-keymap + + name + Sublime Text Key Map + patterns + + + include + #multiLineComment + + + include + #lineComment + + + begin + (^\[$) + contentName + meta.keybinding.collection.sublimekeymap + end + (^\]$) + patterns + + + include + #multiLineComment + + + include + #lineComment + + + include + #keys + + + include + #mainKeys + + + include + #supportKeys + + + include + #string + + + include + #numericPrimitives + + + + + repository + + keys + + begin + "(keys)": \[ + beginCaptures + + 1 + + name + keyword.other.sublimekeymap + + + end + \], + patterns + + + begin + (") + beginCaptures + + 1 + + name + punctuation.keybinding.definition.key.sequence.start.sublimekeymap + + + contentName + meta.key.sequence.sublimekeymap + end + (?<!\\)(") + endCaptures + + 1 + + name + punctuation.keybinding.definition.key.sequence.end.sublime.sublimekeymap + + + patterns + + + match + (?<!shift|ctrl|alt|super|\+)\+ + name + invalid.illegal.key.sequence.sublimekeymap + + + captures + + 1 + + name + support.function.modifier.key.sublimekeymap + + 2 + + name + keyword.modifier.key.connector.sublimekeymap + + + match + (shift|ctrl|alt|super)(\+) + + + match + f(?:[2-9]\d+|\d{3,}) + name + invalid.illegal.key.sublimekeymap + + + match + \b(?:up|down|right|left|insert|home|end|pageup|pagedown|backspace|delete|tab|enter|pause|escape|space|keypad[0-9]|keypad_(?:period|divide|multiply|minus|plus|enter)|clear|sysreq|break|context_menu|browser_(?:back|forward|refresh|stop|search|favorites|home)|forward_slash|backquote|plus|equals|minus|f(20|1[0-9]|[1-9]))\b + name + entity.other.attribute-name.key.named.sublimekeymap + + + match + [A-Za-z0-9,;.:_=+-]{2,} + name + invalid.illegal.key.sublimekeymap + + + captures + + 1 + + name + entity.other.attribute-name.key.captured.sublimekeymap + + + match + <(character)> + name + keyword.control.other.sublimekeymap + + + comment + XXX What's invalid for key names? + match + .{1} + name + string.key.literal.sublimekeymap + + + + + match + [^\s,] + name + invalid.illegal.key.sequence.sublimekeymap + + + + lineComment + + match + //.*?$ + name + comment.single.line.sublimekeymap + + mainKeys + + captures + + 1 + + name + keyword.other.sublimekeymap + + + match + "(command|args|context|key)": + + multiLineComment + + begin + /\* + end + \*/ + name + comment.single.line.sublimekeymap + + numericPrimitives + + patterns + + + match + \b(?:true|false)\b + name + constant.numeric.boolean.sublimekeymap + + + match + \d+(?:\.\d+)? + name + constant.numeric.sublimekeymap + + + + string + + begin + " + contentName + string.double.quote.sublimekeymap + end + (?<!\\)" + patterns + + + include + source.sublimesnippetraw + + + + supportKeys + + captures + + 1 + + name + support.function.sublimekeymap + + + match + "([A-z]+?)": + + + scopeName + source.sublimekeymap + uuid + f56e1baa-51fc-4791-a9d9-21301f2e3a01 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Macros.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Macros.JSON-tmLanguage new file mode 100644 index 0000000..9eda9cf --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Macros.JSON-tmLanguage @@ -0,0 +1,69 @@ +{ "name": "Sublime Text Macro", + + "scopeName": "source.sublimemacro", + + "fileTypes": ["sublime-macro"], + + "patterns": [ + { "begin": "(\\[)", + "beginCaptures": { + "1": { "name": "punctuation.definition.collection.start.sublimemacro" } + }, + "end": "(\\])", + "endCaptures": { + "1": { "name": "punctuation.definition.collection.end.sublimemacro" } + }, + + "patterns": [ + { "include": "#command" }, + { "include": "#args" } + ] + } + ], + + "repository": { + + "args": { + "begin": "\"(args)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.sublimemacro"} + }, + "end": "(?<=\\})", + "name": "meta.definition.attached.command.arguments.sublimemacro", + "patterns": [ + { "include": "source.jsongenericarray" + }, + { "match": "\"([a-zA-Z0-9_]+)\"\\s*:", + "captures": { + "1": { "name": "support.function.array.generic.key.sublimemacro" } + } + }, + { "include": "source.jsongenericarrayelements" + }, + { "match": "true|false|\\d+", + "name": "constant.numeric.sublimemacro" + }, + + { "match": "\\{", + "name": "punctuation.definition.array.keybinding.key.sequence" + } + ] + }, + + "command": { + "begin": "\\{", + "end": "\\}", + "patterns": [ + { "match": "\"(command)\":\\s*\"([^\"]+)\"", + "captures": { + "1": { "name": "keyword.other.sublimemacro" }, + "2": { "name": "string.attached.command.name.sublimemacro" } + } + }, + { "include": "#args" } + ] + } + }, + + "uuid": "f56e1baa-51fc-4791-a9d9-21301f2e3a01" +} diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Macros.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Macros.tmLanguage new file mode 100644 index 0000000..ded7e67 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Macros.tmLanguage @@ -0,0 +1,138 @@ + + + + + fileTypes + + sublime-macro + + name + Sublime Text Macro + patterns + + + begin + (\[) + beginCaptures + + 1 + + name + punctuation.definition.collection.start.sublimecommands + + + end + (\]) + endCaptures + + 1 + + name + punctuation.definition.collection.end.sublimecommands + + + patterns + + + include + #command + + + include + #args + + + + + repository + + args + + begin + "(args)"\s*: + beginCaptures + + 1 + + name + keyword.other.sublimecommands + + + end + (?<=\}) + name + meta.definition.attached.command.arguments.sublimecommands + patterns + + + include + source.jsongenericarray + + + captures + + 1 + + name + support.function.array.generic.key.sublimecommands + + + match + "([a-zA-Z0-9_]+)"\s*: + + + include + source.jsongenericarrayelements + + + match + true|false|\d+ + name + constant.numeric.sublimecommands + + + match + \{ + name + punctuation.definition.array.keybinding.key.sequence + + + + command + + begin + \{ + end + \} + patterns + + + captures + + 1 + + name + keyword.other.sublimecommands + + 2 + + name + string.attached.command.name.sublimecommands + + + match + "(command)":\s*"([^"]+)" + + + include + #args + + + + + scopeName + source.sublimemacro + uuid + f56e1baa-51fc-4791-a9d9-21301f2e3a01 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Settings.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.JSON-tmLanguage new file mode 100644 index 0000000..36dab9c --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.JSON-tmLanguage @@ -0,0 +1,22 @@ +{ "name": "Sublime Settings", + "scopeName": "source.sublime-settings", + "fileTypes": ["sublime-settings"], + "patterns": [ + { "name": "comment.single.line.sublime-settings", + "match": "//.*" + }, + { "name": "comment.block.sublime-settings", + "begin": "/\\*", + "end": "\\*/" + }, + { "match": "\"([a-z0-9_.-]+)\"\\s*?:", + "captures": { + "1": { "name": "keyword.other.name.sublime-settings" } + } + }, + + { "include": "source.jsongenericarray" }, + { "include": "source.jsongenericarrayelements" } + ], + "uuid": "dd6dce14-1f27-4128-9c85-7e30c137ae30" +} diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Settings.sublime-settings b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.sublime-settings new file mode 100644 index 0000000..e03a085 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.sublime-settings @@ -0,0 +1,3 @@ +{ + "extensions": ["sublime-settings"] +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Settings.tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.tmLanguage new file mode 100644 index 0000000..4d6bbe7 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Settings.tmLanguage @@ -0,0 +1,53 @@ + + + + + fileTypes + + sublime-settings + + name + Sublime Settings + patterns + + + match + //.* + name + comment.single.line.sublime-settings + + + begin + /\* + end + \*/ + name + comment.block.sublime-settings + + + captures + + 1 + + name + keyword.other.name.sublime-settings + + + match + "([a-z0-9_.-]+)"\s*?: + + + include + source.jsongenericarray + + + include + source.jsongenericarrayelements + + + scopeName + source.sublime-settings + uuid + dd6dce14-1f27-4128-9c85-7e30c137ae30 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).JSON-tmLanguage new file mode 100644 index 0000000..6962db3 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).JSON-tmLanguage @@ -0,0 +1,79 @@ +{ + "name": "Sublime Text Snippet (Raw)", + "scopeName": "source.sublimesnippetraw", + + "patterns": [ + { "name": "entity.other.attribute-name.environment.sublimesnippetraw", + "match": "(\\$)(PARAM(\\d)|TM_SELECTED_TEXT|USER_NAME|SELECTION)", + "captures": { + "1": { "name": "keyword.other.sublimesnippetraw" }, + "2": { "name": "variable.storage.name.sublimesnippetraw" }, + "3": { "name": "support.constant.numeric.sublimesnippetraw" } + } + }, + + { "name": "variable.field.numbered.sublimesnippetraw", + "match": "(\\$)(\\d+)", + "captures": { + "1": { "name": "keyword.other.sublimesnippetraw" }, + "2": { "name": "support.constant.numeric.name.sublimesnippetraw" } + } + }, + + { "name": "meta.definition.substitution.sublimesnippetraw", + "begin": "(\\$)\\{(\\d+)(?=\/)", + "beginCaptures": { + "1": { "name": "keyword.other.sublimesnippetraw" }, + "2": { "name": "support.constant.numeric.sublimesnippetraw" } + }, + "end": "\\}", + "patterns": [ + { "match": "(?:)", + "captures": { + "1": { "name": "support.constant.numeric.sublimesnippetraw" } + } + }, + { "name": "entity.other.attribute-name.variable.storage.known.name.sublimesnippetraw", + "match": "\\b(packages)\\b" + }, + { "include": "$self" }, + { "name": "string.sublimesnippetraw", + "match": "." + } + ] + } + ], + + "uuid": "9c9f9b3c-0e97-4423-a995-14d6412613d3" +} diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).tmLanguage new file mode 100644 index 0000000..12dbf2b --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Snippet (Raw).tmLanguage @@ -0,0 +1,183 @@ + + + + + name + Sublime Text Snippet (Raw) + patterns + + + captures + + 1 + + name + keyword.other.sublimesnippetraw + + 2 + + name + variable.storage.name.sublimesnippetraw + + 3 + + name + support.constant.numeric.sublimesnippetraw + + + match + (\$)(PARAM(\d)|TM_SELECTED_TEXT|USER_NAME|SELECTION) + name + entity.other.attribute-name.environment.sublimesnippetraw + + + captures + + 1 + + name + keyword.other.sublimesnippetraw + + 2 + + name + support.constant.numeric.name.sublimesnippetraw + + + match + (\$)(\d+) + name + variable.field.numbered.sublimesnippetraw + + + begin + (\$)\{(\d+)(?=/) + beginCaptures + + 1 + + name + keyword.other.sublimesnippetraw + + 2 + + name + support.constant.numeric.sublimesnippetraw + + + end + \} + name + meta.definition.substitution.sublimesnippetraw + patterns + + + captures + + 1 + + name + punctuation.definition.substitution.sublimesnippetraw + + + match + (?<!\\)(/) + + + include + source.regexp + + + match + . + name + string.sublimesnippetraw + + + + + captures + + 1 + + name + keyword.other.sublimesnippetraw + + 2 + + name + entity.other.attribute-name.variable.storage.known.name.sublimesnippetraw + + 3 + + name + variable.storage.name.sublimesnippetraw + + + match + (\$)(?:(packages)|([a-zA-Z0-9_]+)) + name + variable.field.sublimesnippetraw + + + begin + (\$)\{ + beginCaptures + + 1 + + name + keyword.other.sublimesnippetraw + + + end + (\}) + endCaptures + + 1 + + name + meta.definition.variable.complex.sublimesnippetraw + + + name + meta.definition.variable.complex.sublimesnippetraw + patterns + + + captures + + 1 + + name + support.constant.numeric.sublimesnippetraw + + + match + (?<=\{)(\d+)(?>:) + + + match + \b(packages)\b + name + entity.other.attribute-name.variable.storage.known.name.sublimesnippetraw + + + include + $self + + + match + . + name + string.sublimesnippetraw + + + + + scopeName + source.sublimesnippetraw + uuid + 9c9f9b3c-0e97-4423-a995-14d6412613d3 + + diff --git a/sublime/Packages/AAAPackageDev/Support/Sublime Text Build System.JSON-tmLanguage b/sublime/Packages/AAAPackageDev/Support/Sublime Text Build System.JSON-tmLanguage new file mode 100644 index 0000000..12d2a28 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/Support/Sublime Text Build System.JSON-tmLanguage @@ -0,0 +1,197 @@ +{ "name": "Sublime Text Build System", + "scopeName": "source.sublimebuild", + "fileTypes": ["sublime-build"], + "patterns": [ + { "begin": "(\\{)", + "beginCaptures": { + "1": { "name": "punctuation.definition.options.start.sublimebuild" } + }, + "end": "(\\})", + "endCaptures": { + "1": { "name": "punctuation.definition.options.end.sublimebuild" } + }, + + "patterns": [ + { "include": "#cmd" }, + { "include": "#env" }, + { "include": "#simpleOptions" }, + { "include": "#errorRegex" }, + { "include": "#encoding" }, + { "include": "#path" }, + { "include": "#shell" }, + { "include": "#variant" }, + { "include": "source.jsongenericobject" }, + { "match": "(?$\\s+\\])", + "comment": "XXX" + } + ], + "contentName": "meta.options.sublimebuild" + } + ], + "repository": { + "cmd": { + "begin": "\"(cmd)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.sublimebuild"} + }, + "end": "(?<=\\])", + "name": "meta.definition.command.sublimebuild", + "patterns": [ + { "include": "source.jsongenericarray" + }, + { "match": "\"([a-zA-Z0-9_]+)\"\\s*:", + "captures": { + "1": { "name": "support.function.array.generic.key.sublimebuild" } + } + } + ] + }, + "name": { + "match": "\"(name)\"\\s*:\\s*\"(.+?)\"", + "captures": { + "1": { "name": "keyword.other.sublimebuild" }, + "2": { "name": "string.quoted.double.sublimebuild" } + } + }, + "variant": { + "begin": "\"(variant)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.sublimebuild" } + }, + "end": "(?<=\\})", + "name": "meta.definition.variant.sublimebuild", + "patterns": [ + { "include": "#cmd" }, + { "include": "#env" }, + { "include": "#path" }, + { "include": "#name" }, + { "match": "{" }, + { "include": "source.jsongenericobject" }, + { "match": "}" } + ] + }, + "env": { + "begin": "\"(env)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.sublimebuild"} + }, + "end": "(?<=\\})", + "name": "meta.definition.environment.block.sublimebuild", + "patterns": [ + { "match": "\"([a-zA-Z0-9_]+)\"\\s*:", + "captures": { + "1": { "name": "string.variable.name.sublimebuild" } + } + }, + { "include": "#envVarString" + }, + { "match": "\\{" + } + ] + }, + "path": { + "begin": "\"(path)\"\\s*:", + "beginCaptures": { + "1": { "name": "keyword.other.path.sublimebuild"}, + "2": { "name": "punctuation.definition.path.start.sublimebuild" } + }, + "end": "(?<=\")", + "endCaptures": { + "1": { "name": "punctuation.definition.path.end.untitled" } + }, + "name": "meta.definition.path.variable.sublimebuild", + "patterns": [ + { "include": "#envVarString" } + ] + }, + "shell": { + "match": "\"(shell)\":\\s*(true|false)", + "captures": { + "1": { "name": "keyword.other.shell.sublimebuild" }, + "2": { "name": "constant.numeric.boolean.sublimebuild" } + } + }, + "simpleOptions": { + "match": "\"(working_dir|selector|target)\":\\s*\"(.*?)\"", + "comment": "Maybe make this a begin-end: paths must contain characters; cling to that.", + "captures": { + "1": { "name": "keyword.other.sublimebuild" }, + "2": { "name": "string.sublimebuild" } + } + }, + "encoding": { + "match": "\"(encoding)\":\\s*\"(.*?)\"", + "comment": "No exhaustive list of encodings for Python exist, so we cannot restrict this.", + "captures": { + "1": { "name": "keyword.other.encoding.sublimebuild" }, + "2": { "name": "string.sublimebuild" } + } + }, + "errorRegex": { + "begin": "\"(file_regex|line_regex)\"\\s*:\\s*(\")", + "beginCaptures": { + "1": { "name": "keyword.other.error.regex.sublimebuild"}, + "2": { "name": "punctuation.definition.regex.start.sublimebuild" } + }, + "end": "(? + + + + fileTypes + + sublime-build + + name + Sublime Text Build System + patterns + + + begin + (\{) + beginCaptures + + 1 + + name + punctuation.definition.options.start.sublimebuild + + + contentName + meta.options.sublimebuild + end + (\}) + endCaptures + + 1 + + name + punctuation.definition.options.end.sublimebuild + + + patterns + + + include + #cmd + + + include + #env + + + include + #simpleOptions + + + include + #errorRegex + + + include + #encoding + + + include + #path + + + include + #shell + + + include + #variant + + + include + source.jsongenericobject + + + match + (?<!\}|"|\]), + name + invalid.illegal.separator.sublimebuild + + + match + ,{2,} + name + invalid.illegal.character.sublimebuild + + + match + [^,\t\s] + name + invalid.illegal.character.sublimebuild + + + comment + XXX + match + ,(?>$\s+\]) + name + invalid.illegal.separator.sublimebuild + + + + + repository + + cmd + + begin + "(cmd)"\s*: + beginCaptures + + 1 + + name + keyword.other.sublimebuild + + + end + (?<=\]) + name + meta.definition.command.sublimebuild + patterns + + + include + source.jsongenericarray + + + captures + + 1 + + name + support.function.array.generic.key.sublimebuild + + + match + "([a-zA-Z0-9_]+)"\s*: + + + + encoding + + captures + + 1 + + name + keyword.other.encoding.sublimebuild + + 2 + + name + string.sublimebuild + + + comment + No exhaustive list of encodings for Python exist, so we cannot restrict this. + match + "(encoding)":\s*"(.*?)" + + env + + begin + "(env)"\s*: + beginCaptures + + 1 + + name + keyword.other.sublimebuild + + + end + (?<=\}) + name + meta.definition.environment.block.sublimebuild + patterns + + + captures + + 1 + + name + string.variable.name.sublimebuild + + + match + "([a-zA-Z0-9_]+)"\s*: + + + include + #envVarString + + + match + \{ + + + + envVarString + + begin + " + end + " + patterns + + + captures + + 1 + + name + constant.character.escape.sublimebuild + + + match + (\\(?:"|t|n|r)) + + + captures + + 1 + + name + support.function.sublimebuild + + 2 + + name + entity.other.attribute-name.sublimebuild + + 3 + + name + support.function.sublimebuild + + + match + (%)(.*?)(%) + name + meta.environment.variable.sublimebuild + + + captures + + 1 + + name + support.function.sublimebuild + + 2 + + name + entity.other.attribute-name.sublimebuild + + + match + (\$)([A-Z]+) + name + meta.environment.variable.sublimebuild + + + captures + + 1 + + name + support.function.sublimebuild + + 2 + + name + entity.other.attribute-name.sublimebuild + + + match + (\$){(.*?)} + name + meta.environment.variable.sublimebuild + + + match + ;|:(?!\\) + name + keyword.other.path.separator.sublimebuild + + + match + . + name + string.sublimebuild + + + + errorRegex + + begin + "(file_regex|line_regex)"\s*:\s*(") + beginCaptures + + 1 + + name + keyword.other.error.regex.sublimebuild + + 2 + + name + punctuation.definition.regex.start.sublimebuild + + + end + (?<!\\)" + name + meta.definition.error.data.sublimebuild + patterns + + + include + source.escapedregexp + + + match + " + name + punctuation.definition.regex.end.sublimebuild + + + + name + + captures + + 1 + + name + keyword.other.sublimebuild + + 2 + + name + string.quoted.double.sublimebuild + + + match + "(name)"\s*:\s*"(.+?)" + + path + + begin + "(path)"\s*: + beginCaptures + + 1 + + name + keyword.other.path.sublimebuild + + 2 + + name + punctuation.definition.path.start.sublimebuild + + + end + (?<=") + endCaptures + + 1 + + name + punctuation.definition.path.end.untitled + + + name + meta.definition.path.variable.sublimebuild + patterns + + + include + #envVarString + + + + shell + + captures + + 1 + + name + keyword.other.shell.sublimebuild + + 2 + + name + constant.numeric.boolean.sublimebuild + + + match + "(shell)":\s*(true|false) + + simpleOptions + + captures + + 1 + + name + keyword.other.sublimebuild + + 2 + + name + string.sublimebuild + + + comment + Maybe make this a begin-end: paths must contain characters; cling to that. + match + "(working_dir|selector|target)":\s*"(.*?)" + + variant + + begin + "(variant)"\s*: + beginCaptures + + 1 + + name + keyword.other.sublimebuild + + + end + (?<=\}) + name + meta.definition.variant.sublimebuild + patterns + + + include + #cmd + + + include + #env + + + include + #path + + + include + #name + + + match + { + + + include + source.jsongenericobject + + + match + } + + + + + scopeName + source.sublimebuild + uuid + 855d82a3-8501-467f-ba88-4bf91e02ea6d + + diff --git a/sublime/Packages/AAAPackageDev/bin/CleanUp.ps1 b/sublime/Packages/AAAPackageDev/bin/CleanUp.ps1 new file mode 100644 index 0000000..8db0233 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/bin/CleanUp.ps1 @@ -0,0 +1,11 @@ +$here = $MyInvocation.MyCommand.Definition +$here = split-path $here -parent +$root = resolve-path (join-path $here "..") + +push-location $root + # remove-item cmdlet doesn't work well! + get-childitem "." -recurse -filter "*.pyc" | remove-item + remove-item "dist" -recurse -force + remove-item "Doc" -recurse + remove-item "MANIFEST" +pop-location \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/bin/MakeRelease.ps1 b/sublime/Packages/AAAPackageDev/bin/MakeRelease.ps1 new file mode 100644 index 0000000..9dbdbff --- /dev/null +++ b/sublime/Packages/AAAPackageDev/bin/MakeRelease.ps1 @@ -0,0 +1,33 @@ +param([switch]$DontUpload=$False) + +$here = $MyInvocation.MyCommand.Definition +$here = split-path $here -parent +$root = resolve-path (join-path $here "..") + +push-location $root + if (-not (test-path (join-path $root "Doc"))) { + new-item -itemtype "d" -name "Doc" > $null + copy-item ".\Data\main.css" ".\Doc" + } + + # Generate docs in html from rst. + push-location ".\Doc" + get-childitem "..\*.rst" | foreach-object { + & "rst2html.py" ` + "--template" "..\data\html_template.txt" ` + "--stylesheet-path" "main.css" ` + "--link-stylesheet" ` + $_.fullname "$($_.basename).html" + } + pop-location + + # Ensure MANIFEST reflects all changes to file system. + remove-item ".\MANIFEST" -erroraction silentlycontinue + & "python" ".\setup.py" "spa" + + (get-item ".\dist\AAAPackageDev.sublime-package").fullname | clip.exe +pop-location + +if (-not $DontUpload) { + start-process "https://bitbucket.org/guillermooo/aaapackagedev/downloads" +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/build_sys_dev.py b/sublime/Packages/AAAPackageDev/build_sys_dev.py new file mode 100644 index 0000000..6701312 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/build_sys_dev.py @@ -0,0 +1,18 @@ +import sublime_plugin + +from sublime_lib.path import root_at_packages + + +BUILD_SYSTEM_SYNTAX = 'Packages/AAAPackageDev/Support/Sublime Text Build System.tmLanguage' + + +# Adding "2" to avoid name clash with shipped command. +class NewBuildSystem2Command(sublime_plugin.WindowCommand): + def run(self): + v = self.window.new_file() + v.settings().set('default_dir', root_at_packages('User')) + v.set_syntax_file(BUILD_SYSTEM_SYNTAX) + v.set_name('untitled.sublime-build') + + template = """{\n\t"cmd": ["${0:make}"]\n}""" + v.run_command("insert_snippet", {"contents": template}) diff --git a/sublime/Packages/AAAPackageDev/commands_file_dev.py b/sublime/Packages/AAAPackageDev/commands_file_dev.py new file mode 100644 index 0000000..5829799 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/commands_file_dev.py @@ -0,0 +1,20 @@ +import sublime_plugin + +from sublime_lib import path + + +tpl = """[ + { "caption": "${1:My Caption for the Comand Palette}", "command": "${2:my_command}" }$0 +]""" + +SYNTAX_DEF = 'Packages/AAAPackageDev/Support/Sublime Commands.tmLanguage' + + +class NewCommandsFileCommand(sublime_plugin.WindowCommand): + def run(self): + v = self.window.new_file() + v.run_command('insert_snippet', {'contents': tpl}) + v.settings().set('default_dir', path.root_at_packages('User')) + v.set_syntax_file(SYNTAX_DEF) + + diff --git a/sublime/Packages/AAAPackageDev/completions_dev.py b/sublime/Packages/AAAPackageDev/completions_dev.py new file mode 100644 index 0000000..02d61bc --- /dev/null +++ b/sublime/Packages/AAAPackageDev/completions_dev.py @@ -0,0 +1,21 @@ +import sublime, sublime_plugin + +from sublime_lib.path import root_at_packages + + +COMPLETIONS_SYNTAX_DEF = "Packages/AAAPackageDev/Support/Sublime Completions.tmLanguage" +TPL = """{ + "scope": "source.${1:off}", + + "completions": [ + { "trigger": "${2:some_trigger}", "contents": "${3:Hint: Use f, ff and fff plus Tab inside here.}" }$0 + ] +}""" + + +class NewCompletionsCommand(sublime_plugin.WindowCommand): + def run(self): + v = self.window.new_file() + v.run_command('insert_snippet', {"contents": TPL}) + v.settings().set('syntax', COMPLETIONS_SYNTAX_DEF) + v.settings().set('default_dir', root_at_packages('User')) diff --git a/sublime/Packages/AAAPackageDev/data/README.rst b/sublime/Packages/AAAPackageDev/data/README.rst new file mode 100644 index 0000000..43dcccb --- /dev/null +++ b/sublime/Packages/AAAPackageDev/data/README.rst @@ -0,0 +1,35 @@ +================ +%(package_name)s +================ + +
+ + +The Problem +=========== + + + + +Getting Started +=============== + +- Install `%(package_name)s`_ + +.. _%(package_name)s: https:// + +If you're running a full installation of Sublime Text, simply doublelick on the +``.sublime-package`` file. If you're running a portable installation, you need +to perform an `installation by hand`_. + +.. _installation by hand: http://sublimetext.info/docs/extensibility/packages.html#installation-of-packages-with-sublime-package-archives + +Once installed, run the following command from the Python console (``Ctrl+```):: + + view.run_command("COMMAND") + +Alternatively, you can define a new key binding for this command. + +How to Use +========== + diff --git a/sublime/Packages/AAAPackageDev/data/html_template.txt b/sublime/Packages/AAAPackageDev/data/html_template.txt new file mode 100644 index 0000000..3ded0e8 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/data/html_template.txt @@ -0,0 +1,9 @@ +%(head_prefix)s + +%(head)s +%(stylesheet)s +%(body_prefix)s +%(body_pre_docinfo)s +%(docinfo)s +%(body)s +%(body_suffix)s \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/data/main.css b/sublime/Packages/AAAPackageDev/data/main.css new file mode 100644 index 0000000..8e1b6e7 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/data/main.css @@ -0,0 +1,37 @@ +body { + font-family: 'Calibri', 'Helvetica', 'Arial', sans-serif; + font-size: 14pt; + text-align: center; + background-color: #F5F5F5; +} + +div.document { + width: 50%; + margin-left: auto; + margin-right: auto; + text-align: left; +} + + +h1 { + font-family: 'Calibri', 'Helvetica', sans-serif; + font-size: 1.5em; + color: #546473; + word-spacing: -0.08em; +} + +h2 { + font-size: 1.25em; + color: #546473; +} + +span.pre { + font-family: 'Consolas', 'Monaco', 'Courier New', 'Courier'; + background-color: #D1DCE6; + font-weight: normal; +} + +tt.literal { + font-family: 'Consolas', 'Monaco', 'Courier New', 'Courier'; + font-weight: bold; +} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/manifest.in b/sublime/Packages/AAAPackageDev/manifest.in new file mode 100644 index 0000000..4fae179 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/manifest.in @@ -0,0 +1,19 @@ +global-include *.sublime-* +global-exclude *.sublime-project +global-exclude *.cache + +global-exclude _*.txt +exclude html_template.txt + +global-include *.py +exclude sublime_inspect.py +exclude setup.py + +graft Support +graft Snippets +graft Doc +# recursive-include Lib *.py + +prune PackageDev +prune dist +prune tests \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/package-metadata.json b/sublime/Packages/AAAPackageDev/package-metadata.json new file mode 100644 index 0000000..f131482 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/package-metadata.json @@ -0,0 +1 @@ +{"url": "https://github.com/SublimeText/AAAPackageDev", "version": "2012.09.05.17.25.48", "description": "Tools to ease the creation of snippets, syntax definitions, etc. for Sublime Text."} \ No newline at end of file diff --git a/sublime/Packages/AAAPackageDev/package_dev.py b/sublime/Packages/AAAPackageDev/package_dev.py new file mode 100644 index 0000000..6df3825 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/package_dev.py @@ -0,0 +1,136 @@ +import sublime +import sublime_plugin + +import plistlib +import json + +import glob +import os +import sys + +# Makes sublime_lib package available for all packages. +if not os.path.join(sublime.packages_path(), "AAAPackageDev/Lib") in sys.path: + sys.path.append(os.path.join(sublime.packages_path(), "AAAPackageDev/Lib")) + +from sublime_lib.path import root_at_packages + + +DEBUG = 1 +THIS_PACKAGE = "AAAPackageDev" + +status = sublime.status_message +error = sublime.error_message +join_path = os.path.join +path_exists = os.path.exists + +DEFAULT_DIRS = ( + "Snippets", + "Support", + "Docs", + "Macros", + "bin", + "data" + ) + +# name, default template +DEFAULT_FILES = ( + ("LICENSE.txt", None), + ("README.rst", root_at_packages(THIS_PACKAGE, "data/README.rst")), + (".hgignore", root_at_packages(THIS_PACKAGE, "data/hgignore.txt")), + (".gitignore", root_at_packages(THIS_PACKAGE, "data/gitignore.txt")), + ("bin/MakeRelease.ps1", root_at_packages(THIS_PACKAGE, "data/MakeRelease.ps1")), + ("bin/CleanUp.ps1", root_at_packages(THIS_PACKAGE, "data/CleanUp.ps1")), + ("data/html_template.txt", root_at_packages(THIS_PACKAGE, "data/html_template.txt")), + ("data/main.css", root_at_packages(THIS_PACKAGE, "data/main.css")), + ("setup.py", root_at_packages(THIS_PACKAGE, "data/setup.py")), +) + + +class NewPackageCommand(sublime_plugin.WindowCommand): + + def on_done(self, pkg_name): + pam = PackageManager() + if pam.exists(pkg_name): + error(" NewPackage -- Error\n\n" + " Package '" + pkg_name + "' already exists.\n" + " You cannot overwrite an existing package." + ) + return + + pam.create_new(pkg_name) + + + def on_cancel(self): + status('on_cancel') + + def on_changed(self): + status('on_changed') + + def run(self): + self.window.show_input_panel( + "New Package Name", '', self.on_done, None, None) + + +class DeletePackageCommand(sublime_plugin.WindowCommand): + def run(self): + pam = PackageManager() + pam.browse() + + +class PackageManager(object): + + def is_installed(self, name): + raise NotImplemented + + def exists(self, name): + return path_exists(root_at_packages(name)) + + def browse(self): + # Let user choose. + sublime.active_window().run_command("open_dir", + {"dir": sublime.packages_path()}) + + def create_new(self, name): + print "[NewPackage] Creating new package...", + print root_at_packages(name) + + if self.dry_run: + msg = "[NewPackage] ** Nothing done. This was a test. **" + print msg + status(msg) + return + + # Create top folder, default folders, default files. + map(os.makedirs, [root_at_packages(name, d) for d in DEFAULT_DIRS]) + + for f, template in [(root_at_packages(name, fname), template) + for fname, template in DEFAULT_FILES]: + with open(f, 'w') as fh: + if template: + try: + content = "".join(open(template, 'r').readlines()) % \ + {"package_name": name} + except: + pass + finally: + content = "".join(open(template, 'r').readlines()) + + fh.write(content) + + msg = "[NewPackage] Created new package '%s'." % name + print msg + status(msg) + + def __init__(self, dry_run=False): + self.dry_run = dry_run + + +class PlistToJson(sublime_plugin.TextCommand): + def is_enabled(self ): + return self.view.file_name().endswith('.tmLanguage') + + def run(self, edit): + plist_data = plistlib.readPlist(self.view.file_name()) + v = self.view.window().new_file() + v.insert(edit, 0, json.dumps(plist_data, indent=4)) + v.set_syntax_file('Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.tmLanguage') diff --git a/sublime/Packages/AAAPackageDev/settings_dev.py b/sublime/Packages/AAAPackageDev/settings_dev.py new file mode 100644 index 0000000..d677cdd --- /dev/null +++ b/sublime/Packages/AAAPackageDev/settings_dev.py @@ -0,0 +1,17 @@ +import sublime, sublime_plugin + +from sublime_lib.path import root_at_packages + + +SETTINGS_SYNTAX = 'Packages/AAAPackageDev/Support/Sublime Settings.tmLanguage' + + +TPL = """{$0}""" + + +class NewSettingsCommand(sublime_plugin.WindowCommand): + def run(self): + v = self.window.new_file() + v.settings().set('default_dir', root_at_packages('User')) + v.settings().set('syntax', SETTINGS_SYNTAX) + v.run_command('insert_snippet', {'contents': TPL}) diff --git a/sublime/Packages/AAAPackageDev/setup.py b/sublime/Packages/AAAPackageDev/setup.py new file mode 100644 index 0000000..bc845d9 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/setup.py @@ -0,0 +1,589 @@ +# encoding: utf-8 + +"""Commands to build and manage .sublime-package archives with distutils.""" + +import sys +import os, string +from types import * +from glob import glob +from distutils import log, dir_util, dep_util, file_util, archive_util +from distutils.core import Command +from distutils.core import setup +from distutils.text_file import TextFile +from distutils.filelist import FileList +from distutils.errors import * +from distutils.spawn import spawn +from distutils.dir_util import mkpath +import subprocess + + +def make_zipfile (base_name, base_dir, verbose=0, dry_run=0): + """Create a zip file from all the files under 'base_dir'. The output + zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" + Python module (if available) or the InfoZIP "zip" utility (if installed + and found on the default search path). If neither tool is available, + raises DistutilsExecError. Returns the name of the output zip file. + """ + try: + import zipfile + except ImportError: + zipfile = None + + zip_filename = base_name + ".sublime-package" + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + + # If zipfile module is not available, try spawning an external + # 'zip' command. + if zipfile is None: + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + + try: + spawn(["zip", zipoptions, zip_filename, base_dir], + dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise DistutilsExecError, \ + ("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename + + else: + log.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + z = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + arcname = path[len(base_dir):] + # if dirpath == base_dir: + # arcname = name + # else: + # arcname = path[len(base_dir):] + # print arcname + if os.path.isfile(path): + z.write(path, arcname) + log.info("adding '%s'" % path) + z.close() + + return zip_filename + + +def show_formats (): + """Print all possible values for the 'formats' option (used by + the "--help-formats" command-line option). + """ + from distutils.fancy_getopt import FancyGetopt + from distutils.archive_util import ARCHIVE_FORMATS + formats=[] + for format in ARCHIVE_FORMATS.keys(): + formats.append(("formats=" + format, None, + ARCHIVE_FORMATS[format][2])) + formats.sort() + pretty_printer = FancyGetopt(formats) + pretty_printer.print_help( + "List of available source distribution formats:") + +class spa (Command): + + description = "create a source distribution (tarball, zip file, etc.)" + + user_options = [ + ('template=', 't', + "name of manifest template file [default: MANIFEST.in]"), + ('manifest=', 'm', + "name of manifest file [default: MANIFEST]"), + ('use-defaults', None, + "include the default file set in the manifest " + "[default; disable with --no-defaults]"), + ('no-defaults', None, + "don't include the default file set"), + ('prune', None, + "specifically exclude files/directories that should not be " + "distributed (build tree, RCS/CVS dirs, etc.) " + "[default; disable with --no-prune]"), + ('no-prune', None, + "don't automatically exclude anything"), + ('manifest-only', 'o', + "just regenerate the manifest and then stop " + "(implies --force-manifest)"), + ('force-manifest', 'f', + "forcibly regenerate the manifest and carry on as usual"), + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ] + + boolean_options = ['use-defaults', 'prune', + 'manifest-only', 'force-manifest', + 'keep-temp'] + + help_options = [ + ('help-formats', None, + "list available distribution formats", show_formats), + ] + + negative_opt = {'no-defaults': 'use-defaults', + 'no-prune': 'prune' } + + default_format = { 'posix': 'gztar', + 'nt': 'zip' } + + def initialize_options (self): + # 'template' and 'manifest' are, respectively, the names of + # the manifest template and manifest file. + self.template = None + self.manifest = None + + # 'use_defaults': if true, we will include the default file set + # in the manifest + self.use_defaults = 1 + self.prune = 1 + + self.manifest_only = 0 + self.force_manifest = 0 + + self.formats = None + self.keep_temp = 0 + self.dist_dir = None + + self.archive_files = None + + + def finalize_options (self): + if self.manifest is None: + self.manifest = "MANIFEST" + if self.template is None: + self.template = "MANIFEST.in" + + self.ensure_string_list('formats') + if self.formats is None: + try: + self.formats = [self.default_format[os.name]] + except KeyError: + raise DistutilsPlatformError, \ + "don't know how to create source distributions " + \ + "on platform %s" % os.name + + bad_format = archive_util.check_archive_formats(self.formats) + if bad_format: + raise DistutilsOptionError, \ + "unknown archive format '%s'" % bad_format + + if self.dist_dir is None: + self.dist_dir = "dist" + + + def run (self): + + # 'filelist' contains the list of files that will make up the + # manifest + self.filelist = FileList() + + # Ensure that all required meta-data is given; warn if not (but + # don't die, it's not *that* serious!) + self.check_metadata() + + # Do whatever it takes to get the list of files to process + # (process the manifest template, read an existing manifest, + # whatever). File list is accumulated in 'self.filelist'. + self.get_file_list() + + # If user just wanted us to regenerate the manifest, stop now. + if self.manifest_only: + return + + # Otherwise, go ahead and create the source distribution tarball, + # or zipfile, or whatever. + self.make_distribution() + + + def check_metadata (self): + """Ensure that all required elements of meta-data (name, version, + URL, (author and author_email) or (maintainer and + maintainer_email)) are supplied by the Distribution object; warn if + any are missing. + """ + metadata = self.distribution.metadata + + missing = [] + for attr in ('name', 'version', 'url'): + if not (hasattr(metadata, attr) and getattr(metadata, attr)): + missing.append(attr) + + if missing: + self.warn("missing required meta-data: " + + string.join(missing, ", ")) + + if metadata.author: + if not metadata.author_email: + self.warn("missing meta-data: if 'author' supplied, " + + "'author_email' must be supplied too") + elif metadata.maintainer: + if not metadata.maintainer_email: + self.warn("missing meta-data: if 'maintainer' supplied, " + + "'maintainer_email' must be supplied too") + else: + self.warn("missing meta-data: either (author and author_email) " + + "or (maintainer and maintainer_email) " + + "must be supplied") + + # check_metadata () + + + def get_file_list (self): + """Figure out the list of files to include in the source + distribution, and put it in 'self.filelist'. This might involve + reading the manifest template (and writing the manifest), or just + reading the manifest, or just using the default file set -- it all + depends on the user's options and the state of the filesystem. + """ + + # If we have a manifest template, see if it's newer than the + # manifest; if so, we'll regenerate the manifest. + template_exists = os.path.isfile(self.template) + if template_exists: + template_newer = dep_util.newer(self.template, self.manifest) + + # The contents of the manifest file almost certainly depend on the + # setup script as well as the manifest template -- so if the setup + # script is newer than the manifest, we'll regenerate the manifest + # from the template. (Well, not quite: if we already have a + # manifest, but there's no template -- which will happen if the + # developer elects to generate a manifest some other way -- then we + # can't regenerate the manifest, so we don't.) + self.debug_print("checking if %s newer than %s" % + (self.distribution.script_name, self.manifest)) + setup_newer = dep_util.newer(self.distribution.script_name, + self.manifest) + + # cases: + # 1) no manifest, template exists: generate manifest + # (covered by 2a: no manifest == template newer) + # 2) manifest & template exist: + # 2a) template or setup script newer than manifest: + # regenerate manifest + # 2b) manifest newer than both: + # do nothing (unless --force or --manifest-only) + # 3) manifest exists, no template: + # do nothing (unless --force or --manifest-only) + # 4) no manifest, no template: generate w/ warning ("defaults only") + + manifest_outofdate = (template_exists and + (template_newer or setup_newer)) + force_regen = self.force_manifest or self.manifest_only + manifest_exists = os.path.isfile(self.manifest) + neither_exists = (not template_exists and not manifest_exists) + + # Regenerate the manifest if necessary (or if explicitly told to) + if manifest_outofdate or neither_exists or force_regen: + if not template_exists: + self.warn(("manifest template '%s' does not exist " + + "(using default file list)") % + self.template) + self.filelist.findall() + + if self.use_defaults: + self.add_defaults() + if template_exists: + self.read_template() + if self.prune: + self.prune_file_list() + + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + # Don't regenerate the manifest, just read it in. + else: + self.read_manifest() + + # get_file_list () + + + def add_defaults (self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + + standards = [('README', 'README.txt'), self.distribution.script_name] + for fn in standards: + # XXX + if fn == 'setup.py': continue # We don't want setup.py + if type(fn) is TupleType: + alts = fn + got_it = 0 + for fn in alts: + if os.path.exists(fn): + got_it = 1 + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + string.join(alts, ', ')) + else: + if os.path.exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + if files: + self.filelist.extend(files) + + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + self.filelist.extend(build_py.get_source_files()) + + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + # add_defaults () + + + def read_template (self): + """Read and parse manifest template file named by self.template. + + (usually "MANIFEST.in") The parsing and processing is done by + 'self.filelist', which updates itself accordingly. + """ + log.info("reading manifest template '%s'", self.template) + template = TextFile(self.template, + strip_comments=1, + skip_blanks=1, + join_lines=1, + lstrip_ws=1, + rstrip_ws=1, + collapse_join=1) + + while 1: + line = template.readline() + if line is None: # end of file + break + + try: + self.filelist.process_template_line(line) + except DistutilsTemplateError, msg: + self.warn("%s, line %d: %s" % (template.filename, + template.current_line, + msg)) + + # read_template () + + + def prune_file_list (self): + """Prune off branches that might slip into the file list as created + by 'read_template()', but really don't belong there: + * the build tree (typically "build") + * the release tree itself (only an issue if we ran "spa" + previously with --keep-temp, or it aborted) + * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories + """ + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + base_dir = self.distribution.get_name() + + self.filelist.exclude_pattern(None, prefix=build.build_base) + self.filelist.exclude_pattern(None, prefix=base_dir) + + # pruning out vcs directories + # both separators are used under win32 + if sys.platform == 'win32': + seps = r'/|\\' + else: + seps = '/' + + vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', + '_darcs'] + vcs_ptrn = r'(^|%s)(%s)(%s).*' % (seps, '|'.join(vcs_dirs), seps) + self.filelist.exclude_pattern(vcs_ptrn, is_regex=1) + + def write_manifest (self): + """Write the file list in 'self.filelist' (presumably as filled in + by 'add_defaults()' and 'read_template()') to the manifest file + named by 'self.manifest'. + """ + self.execute(file_util.write_file, + (self.manifest, self.filelist.files), + "writing manifest file '%s'" % self.manifest) + + # write_manifest () + + + def read_manifest (self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + manifest = open(self.manifest) + while 1: + line = manifest.readline() + if line == '': # end of file + break + if line[-1] == '\n': + line = line[0:-1] + self.filelist.append(line) + manifest.close() + + # read_manifest () + + + def make_release_tree (self, base_dir, files): + """Create the directory tree that will become the source + distribution archive. All directories implied by the filenames in + 'files' are created under 'base_dir', and then we hard link or copy + (if hard linking is unavailable) those files into place. + Essentially, this duplicates the developer's source tree, but in a + directory named after the distribution, containing only the files + to be distributed. + """ + # Create all the directories under 'base_dir' necessary to + # put 'files' there; the 'mkpath()' is just so we don't die + # if the manifest happens to be empty. + self.mkpath(base_dir) + dir_util.create_tree(base_dir, files, dry_run=self.dry_run) + + # And walk over the list of files, either making a hard link (if + # os.link exists) to each one that doesn't already exist in its + # corresponding location under 'base_dir', or copying each file + # that's out-of-date in 'base_dir'. (Usually, all files will be + # out-of-date, because by default we blow away 'base_dir' when + # we're done making the distribution archives.) + + if hasattr(os, 'link'): # can make hard links on this system + link = 'hard' + msg = "making hard links in %s..." % base_dir + else: # nope, have to copy + link = None + msg = "copying files to %s..." % base_dir + + if not files: + log.warn("no files to distribute -- empty manifest?") + else: + log.info(msg) + for file in files: + if not os.path.isfile(file): + log.warn("'%s' not a regular file -- skipping" % file) + else: + dest = os.path.join(base_dir, file) + self.copy_file(file, dest, link=link) + + self.distribution.metadata.write_pkg_info(base_dir) + + # make_release_tree () + + def make_distribution (self): + """Create the source distribution(s). First, we create the release + tree with 'make_release_tree()'; then, we create all required + archive files (according to 'self.formats') from the release tree. + Finally, we clean up by blowing away the release tree (unless + 'self.keep_temp' is true). The list of archive files created is + stored so it can be retrieved later by 'get_archive_files()'. + """ + # Don't warn about missing meta-data here -- should be (and is!) + # done elsewhere. + base_dir = self.distribution.get_fullname() + base_dir = self.distribution.get_name() + # XXX + # base_dir = "TEST" + base_name = os.path.join(self.dist_dir, base_dir) + + + self.make_release_tree(base_dir, self.filelist.files) + archive_files = [] # remember names of files we create + # tar archive must be created last to avoid overwrite and remove + if 'tar' in self.formats: + self.formats.append(self.formats.pop(self.formats.index('tar'))) + + for fmt in self.formats: + # file = self.make_archive(base_name, fmt, base_dir=base_dir) + file = make_zipfile(base_name, base_dir=base_dir) + archive_files.append(file) + self.distribution.dist_files.append(('spa', '', file)) + + self.archive_files = archive_files + + if not self.keep_temp: + dir_util.remove_tree(base_dir, dry_run=self.dry_run) + + def get_archive_files (self): + """Return the list of archive files created when the command + was run, or None if the command hasn't run yet. + """ + return self.archive_files + +# class spa + + +class install(Command): + """Does it make sense?""" + + user_options = [('aa', 'a', 'aa')] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + print NotImplementedError("Command not implemented yet.") + + +class test(Command): + """Does it make sense?""" + + user_options = [('aa', 'a', 'aa')] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.name == 'nt': + subprocess.call(["py.test.exe"]) + + + +setup(cmdclass={'spa': spa, 'install': install, 'test': test}, + name='AAAPackageDev', + version='0.6', + description='Sublime Text Dev Tools for Packages.', + author='Guillermo López-Anglada', + author_email='guillermo@sublimetext.info', + url='http://sublimetext.info', + ) diff --git a/sublime/Packages/AAAPackageDev/snippet_dev.py b/sublime/Packages/AAAPackageDev/snippet_dev.py new file mode 100644 index 0000000..59bcdc2 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/snippet_dev.py @@ -0,0 +1,71 @@ +import sublime, sublime_plugin + +from sublime_lib.view import has_file_ext +from sublime_lib.path import root_at_packages + +from xml.etree import ElementTree as ET +import os + + +RAW_SNIPPETS_SYNTAX = 'Packages/AAAPackageDev/Support/Sublime Snippet (Raw).tmLanguage' + + +TPL = """ + + ${2:tab_trigger} + ${3:source.name} +""" + + +class NewRawSnippetCommand(sublime_plugin.WindowCommand): + def run(self): + v = self.window.new_file() + v.settings().set('default_dir', root_at_packages('User')) + v.settings().set('syntax', RAW_SNIPPETS_SYNTAX) + v.set_scratch(True) + + +class GenerateSnippetFromRawSnippetCommand(sublime_plugin.TextCommand): + def is_enabled(self): + return self.view.match_selector(0, 'source.sublimesnippetraw') + + def run(self, edit): + # XXX: sublime_lib: new whole_content(view) function? + content = self.view.substr(sublime.Region(0, self.view.size())) + self.view.replace(edit, sublime.Region(0, self.view.size()), '') + self.view.run_command('insert_snippet', { 'contents': TPL }) + self.view.settings().set('syntax', 'Packages/XML/XML.tmLanguage') + # Insert existing contents into CDATA section. We rely on the fact + # that Sublime will place the first selection in the first field of + # the newly inserted snippet. + self.view.insert(edit, self.view.sel()[0].begin(), content) + + +class NewRawSnippetFromSnippetCommand(sublime_plugin.TextCommand): + def is_enabled(self): + return has_file_ext(self.view, 'sublime-snippet') + + def run(self, edit): + snippet = self.view.substr(sublime.Region(0, self.view.size())) + contents = ET.fromstring(snippet).findtext(".//content") + v = self.view.window().new_file() + v.insert(edit, 0, contents) + v.settings().set('syntax', RAW_SNIPPETS_SYNTAX) + + +class CopyAndInsertRawSnippetCommand(sublime_plugin.TextCommand): + """Inserts the raw snippet contents into the first selection of + the previous view in the stack. + + Allows a workflow where you're creating snippets for a .sublime-completions + file, for example, and you don't want to store them as .sublime-snippet + files. + """ + def is_enabled(self): + return self.view.match_selector(0, 'source.sublimesnippetraw') + + def run(self, edit): + snip = self.view.substr(sublime.Region(0, self.view.size())) + self.view.window().run_command('close') + target = sublime.active_window().active_view() + target.replace(edit, target.sel()[0], snip) diff --git a/sublime/Packages/AAAPackageDev/sublime_inspect.py b/sublime/Packages/AAAPackageDev/sublime_inspect.py new file mode 100644 index 0000000..f0545a8 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/sublime_inspect.py @@ -0,0 +1,57 @@ +import sublime, sublime_plugin + +import sublime_lib + +import os +import json + + +class SublimeInspect(sublime_plugin.WindowCommand): + def on_done(self, s): + rep = Report(s) + rep.show() + + def run(self): + self.window.show_input_panel("Search String:", '', self.on_done, None, None) + + +class Report(object): + def __init__(self, s): + self.s = s + + def collect_info(self): + try: + atts = dir(eval(self.s, {"sublime": sublime, "sublime_plugin": sublime_plugin})) + except NameError, e: + atts = e + + self.data = atts + + def show(self): + self.collect_info() + v = sublime.active_window().new_file() + v.insert(v.begin_edit(), 0, '\n'.join(self.data)) + v.set_scratch(True) + v.set_name("SublimeInspect - Report") + + +class OpenSublimeSessionCommand(sublime_plugin.WindowCommand): + def run(self): + session_file = os.path.join(sublime.packages_path(), "..", "Settings", "Session.sublime_session") + self.window.open_file(session_file) + + +def to_json_type(v): + """"Convert string value to proper JSON type. + """ + try: + if v.lower() in ("false", "true"): + v = (True if v.lower() == "true" else False) + elif v.isdigit(): + v = int(v) + elif v.replace(".", "").isdigit(): + v = float(v) + except AttributeError: + raise ValueError("Conversion to JSON failed for: %s" % v) + + return v diff --git a/sublime/Packages/AAAPackageDev/syntax_def_dev.py b/sublime/Packages/AAAPackageDev/syntax_def_dev.py new file mode 100644 index 0000000..39f46c9 --- /dev/null +++ b/sublime/Packages/AAAPackageDev/syntax_def_dev.py @@ -0,0 +1,228 @@ +import json +import os +import plistlib +import xml.parsers.expat +import uuid +import re + +import sublime_plugin + +from sublime_lib.path import root_at_packages +from sublime_lib.view import (in_one_edit, coorded_substr) + + +JSON_TMLANGUAGE_SYNTAX = 'Packages/AAAPackageDev/Support/Sublime JSON Syntax Definition.tmLanguage' + + +# XXX: Move this to a txt file. Let user define his own under User too. +def get_syntax_def_boilerplate(): + JSON_TEMPLATE = """{ "name": "${1:Syntax Name}", + "scopeName": "source.${2:syntax_name}", + "fileTypes": ["$3"], + "patterns": [$0 + ], + "uuid": "%s" +}""" + + actual_tmpl = JSON_TEMPLATE % str(uuid.uuid4()) + return actual_tmpl + + +class NewSyntaxDefCommand(sublime_plugin.WindowCommand): + """Creates a new syntax definition file for Sublime Text in JSON format + with some boilerplate text. + """ + def run(self): + target = self.window.new_file() + + target.settings().set('default_dir', root_at_packages('User')) + target.settings().set('syntax', JSON_TMLANGUAGE_SYNTAX) + + target.run_command('insert_snippet', + {'contents': get_syntax_def_boilerplate()}) + + +class NewSyntaxDefFromBufferCommand(sublime_plugin.TextCommand): + """Inserts boilerplate text for syntax defs into current view. + """ + def is_enabled(self): + # Don't mess up a non-empty buffer. + return self.view.size() == 0 + + def run(self, edit): + self.view.settings().set('default_dir', root_at_packages('User')) + self.view.settings().set('syntax', JSON_TMLANGUAGE_SYNTAX) + + with in_one_edit(self.view): + self.view.run_command('insert_snippet', + {'contents': get_syntax_def_boilerplate()}) + + +# XXX: Why is this a WindowCommand? Wouldn't it work otherwise in build-systems? +class JsonToPlistCommand(sublime_plugin.WindowCommand): + """ + Parses ``.json`` files and writes them into corresponding ``.plist``. + Source file ``.JSON-XXX`` will generate a plist file named ``.XXX``. + Pretty useful with ``.JSON-tmLanguage`` but works with almost any other name. + """ + ext_regexp = re.compile(r'\.json(?:-([^\.]+))?$', flags=re.I) + + def is_enabled(self): + v = self.window.active_view() + return (v and (self.get_file_ext(v.file_name()) is not None)) + + def get_file_ext(self, file_name): + ret = self.ext_regexp.search(file_name) + if ret is None: + return None + return '.' + (ret.group(1) or 'plist') + + def run(self, **kwargs): + v = self.window.active_view() + path = v.file_name() + ext = self.get_file_ext(path) + if not os.path.exists(path): + print "[AAAPackageDev] File does not exists. (%s)" % path + return + if ext is None: + print "[AAAPackageDev] Not a valid JSON file, please check extension. (%s)" % path + return + + self.json_to_plist(path, ext) + + def json_to_plist(self, json_file, new_ext): + path, fname = os.path.split(json_file) + fbase, old_ext = os.path.splitext(fname) + file_regex = r"Error parsing JSON:\s+'(.*?)'\s+.*?\s+line\s+(\d+)\s+column\s+(\d+)" + + if not hasattr(self, 'output_view'): + # Try not to call get_output_panel until the regexes are assigned + self.output_view = self.window.get_output_panel("aaa_package_dev") + + # FIXME: Can't get error navigation to work. + self.output_view.settings().set("result_file_regex", file_regex) + self.output_view.settings().set("result_base_dir", path) + + # Call get_output_panel a second time after assigning the above + # settings, so that it'll be picked up as a result buffer + self.window.get_output_panel("aaa_package_dev") + + with in_one_edit(self.output_view) as edit: + try: + with open(json_file) as json_content: + tmlanguage = json.load(json_content) + except ValueError, e: + self.output_view.insert(edit, 0, "Error parsing JSON: '%s' %s" % (json_file, str(e))) + else: + target = os.path.join(path, fbase + new_ext) + self.output_view.insert(edit, 0, "Writing plist... (%s)" % target) + plistlib.writePlist(tmlanguage, target) + + self.window.run_command("show_panel", {"panel": "output.aaa_package_dev"}) + + +class PlistToJsonCommand(sublime_plugin.WindowCommand): + """ + Parses ``.plist`` files and writes them into corresponding ``.json``. + A source file has `` or , they + result in unpredictable behavior! + - Floats of or tend to lose precision when being cast into Python + data types. ``32.1`` (plist) will likely result in ``32.100000000000001`` (json). + """ + DOCTYPE = " + + + + name + Comments + scope + source.css.less + settings + + shellVariables + + + name + TM_COMMENT_START + value + // + + + name + TM_COMMENT_START_2 + value + /* + + + name + TM_COMMENT_END_2 + value + */ + + + name + TM_COMMENT_DISABLE_INDENT + value + no + + + + uuid + 375CF370-8A7B-450A-895C-FD18B47957E2 + + diff --git a/sublime/Packages/LESS/LESS.tmLanguage b/sublime/Packages/LESS/LESS.tmLanguage new file mode 100644 index 0000000..ede5024 --- /dev/null +++ b/sublime/Packages/LESS/LESS.tmLanguage @@ -0,0 +1,492 @@ + + + + + comment + LESS + fileTypes + + less + css + + + foldingStartMarker + /\*\*(?!\*)|\{\s*($|/\*(?!.*?\*/.*\S)) + foldingStopMarker + (?<!\*)\*\*/|^\s*\} + keyEquivalent + ^~L + name + LESS + patterns + + + match + \b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|datalist|dd|del|details|dfn|dialog|div|dl|dt|em|eventsource|fieldset|figure|figcaption|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|samp|script|section|select|small|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\b + name + keyword.control.html.elements + + + begin + " + end + " + name + string.quoted.double.css + patterns + + + match + \\. + name + constant.character.escaped.css + + + + + begin + ' + end + ' + name + string.quoted.single.css + patterns + + + match + \\. + name + constant.character.escaped.css + + + + + begin + ` + end + ` + name + string.quoted.single.css markup.raw + patterns + + + match + \\. + name + constant.character.escaped.css + + + + + captures + + 1 + + name + entity.other.less.mixin + + + match + (\.(?![0-9])[a-zA-Z0-9_-]+(?=\()) + + + captures + + 1 + + name + entity.other.attribute-name.class.css + + + match + (\.(?![0-9])[a-zA-Z0-9_-]+) + + + begin + (url)(\()(\') + contentName + string.quoted.variable.parameter.url + end + (\')(\)) + beginCaptures + + 1 + + name + support.function.any-method.builtin.css + + 2 + + name + meta.brace.round.js + + 3 + + name + string.quoted.variable.parameter.url + + + endCaptures + + 1 + + name + string.quoted.variable.parameter.url + + 2 + + name + meta.brace.round.js + + + + + begin + (url)(\()(\") + contentName + string.quoted.variable.parameter.url + end + (\")(\)) + beginCaptures + + 1 + + name + support.function.any-method.builtin.css + + 2 + + name + meta.brace.round.js + + 3 + + name + string.quoted.variable.parameter.url + + + endCaptures + + 1 + + name + string.quoted.variable.parameter.url + + 2 + + name + meta.brace.round.js + + + + + begin + (url)(\() + contentName + string.quoted.variable.parameter.url + end + (\)) + beginCaptures + + 1 + + name + support.function.any-method.builtin.css + + 2 + + name + meta.brace.round.js + + + endCaptures + + 1 + + name + meta.brace.round.js + + + + + match + (#)([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b + name + constant.other.rgb-value.css + + + captures + + 0 + + name + entity.other.attribute-name.id + + + match + #[a-zA-Z0-9_-]+ + name + meta.selector.css + + + begin + /\* + end + \*/ + name + comment.block.css + + + match + (-|\+)?\s*[0-9]+(\.[0-9]+)? + name + constant.numeric.css + + + match + (?<=[\d])(px|pt|cm|mm|in|em|ex|pc|rem|deg|ms|s)\b|% + name + keyword.unit.css + + + captures + + 1 + + name + punctuation.definition.entity.css + + + match + (:+)\b(not|after|before|disabled|empty|enabled|first-child|first-letter|first-line|first-of-type|invalid|last-of-type|last-child|only-child|only-of-type|selection|target|valid|required|nth-child)\b + name + entity.other.attribute-name.pseudo-element.css + + + captures + + 1 + + name + punctuation.definition.entity.css + + + match + (:)\b(active|hover|link|visited|focus)\b + name + entity.other.attribute-name.pseudo-class.css + + + captures + + 1 + + name + punctuation.definition.entity.css + + 2 + + name + entity.other.attribute-name.attribute.css + + 3 + + name + punctuation.separator.operator.css keyword.operator.less + + 4 + + name + string.unquoted.attribute-value.css + + 5 + + name + string.quoted.double.attribute-value.css + + 6 + + name + punctuation.definition.string.begin.css + + 7 + + name + punctuation.definition.string.end.css + + + match + (?i)(\[)\s*(-?[_a-z\\[[:^ascii:]]][_a-z0-9\-\\[[:^ascii:]]]*)(?:\s*([~|^$*]?=)\s*(?:(-?[_a-z\\[[:^ascii:]]][_a-z0-9\-\\[[:^ascii:]]]*)|((?>(['"])(?:[^\\]|\\.)*?(\6)))))?\s*(\]) + name + meta.attribute-selector.css + + + captures + + 1 + + name + keyword.control.at-rule.import.css + + 2 + + name + punctuation.definition.keyword.css + + + match + ^\s*((@)import\b) + name + meta.at-rule.import.css + + + captures + + 1 + + name + support.type.property-name.css.vendor + + + match + (-(?:webkit|moz|khtml|o|ms|icab)-(?:text-overflow|hyphens|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|backface-visibility|background-clip|background-origin|background-size|border-image|border-radius-topleft|border-radius-bottomleft|border-radius-topright|border-radius-bottomright|border-radius|box-align|box-shadow|box-sizing|column-count|column-gap|columns|font-smoothing|min-device-pixel-ratio|opacity|perspective-origin-x|perspective-origin-y|perspective-origin|perspective|tap-highlight-color|text-size-adjust|text-stroke|transform-origin-x|transform-origin-y|transform-origin-z|transform-style|transform-origin|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|input-placeholder|placeholder|inline-stack|border-top-left-radius|border-top-right-radius|border-bottom-left-radius|border-bottom-right-radius|focus-inner|margin-top-collapse|focus-ring-color|user-select|touch-callout|filter))\s*(?:) + + + captures + + 1 + + name + support.type.property-name.css + + + match + \s*\b(hyphens|backface-visibility|text-overflow|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|background-attachment|background-color|background-clip|background-image|background-origin|background-position|background-repeat|background-size|background|behavior|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom-left-radius|border-bottom-right-radius|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top-left-radius|border-top-right-radius|border-top|border-width|border-image|border-radius-topleft|border-radius-bottomleft|border-radius-topright|border-radius-bottomright|border-radius|border-box|border|box-align|box-shadow|box-sizing|bottom|caption-side|clear|clip|color-stop|color|column-count|column-gap|columns|content-box|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-device-pixel-ratio|min-height|min-width|opacity|orientation|orphans|outline-offset|outline-color|outline-style|outline-width|outline|overflow(-[xy])?|padding-bottom|padding-left|padding-right|padding-top|padding-box|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|perspective-origin|perspective-origin-x|perspective-origin-y|perspective|pitch-range|pitch|play-during|position|quotes|resize|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|transform-origin|transform-origin-x|transform-origin-y|transform-origin-z|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|word-wrap|z-index|zoom|filter|word-break|user-select|text-rendering)\s*(?:) + + + match + \s*\b(grab|grabbing|antialiased|absolute|all-scroll|all|always|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|col-resize|collapse|content-box|crosshair|dashed|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in-out|ease-in|ease-out|ease|ellipsis|fixed|groove|hand|help|hidden|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|keep-all|landscape|left|lighter|line-edge|line-through|line|linear-gradient|linear|list-item|loose|lower-alpha|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|cover|contain|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|padding-box|pointer-events|pointer|portrait|pre-wrap|progress|relative|repeat-x|repeat-y|repeat|right|ridge|rotate|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-roman|uppercase|vertical-ideographic|vertical-text|vertical|visible|w-resize|wait|whitespace|initial|radial|bicubic|textfield|table-cell)\b + name + support.constant.property-value.css + + + match + (\b(?i:arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace|monaco|menlo|consolas)\b) + name + support.constant.font-name.css + + + comment + http://www.w3.org/TR/CSS21/syndata.html#value-def-color + match + \b(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)(?!\()\b + name + support.constant.color.w3c-standard-color-name.css + + + comment + Moar colors.. this is about colors after all. + match + \b(indianred|lightcoral|salmon|darksalmon|lightsalmon|crimson|red|firebrick|darkred|pink|lightpink|hotpink|deeppink|mediumvioletred|palevioletred|lightsalmon|coral|tomato|orangered|darkorange|orange|gold|yellow|lightyellow|lemonchiffon|lightgoldenrodyellow|papayawhip|moccasin|peachpuff|palegoldenrod|khaki|darkkhaki|lavender|thistle|plum|violet|orchid|fuchsia|magenta|mediumorchid|mediumpurple|blueviolet|darkviolet|darkorchid|darkmagenta|purple|indigo|slateblue|darkslateblue|mediumslateblue|greenyellow|chartreuse|lawngreen|lime|limegreen|palegreen|lightgreen|mediumspringgreen|springgreen|mediumseagreen|seagreen|forestgreen|green|darkgreen|yellowgreen|olivedrab|olive|darkolivegreen|mediumaquamarine|darkseagreen|lightseagreen|darkcyan|teal|aqua|cyan|lightcyan|paleturquoise|aquamarine|turquoise|mediumturquoise|darkturquoise|cadetblue|steelblue|lightsteelblue|powderblue|lightblue|skyblue|lightskyblue|deepskyblue|dodgerblue|cornflowerblue|mediumslateblue|royalblue|blue|mediumblue|darkblue|navy|midnightblue|cornsilk|blanchedalmond|bisque|navajowhite|wheat|burlywood|tan|rosybrown|sandybrown|goldenrod|darkgoldenrod|peru|chocolate|saddlebrown|sienna|brown|maroon|white|snow|honeydew|mintcream|azure|aliceblue|ghostwhite|whitesmoke|seashell|beige|oldlace|floralwhite|ivory|antiquewhite|linen|lavenderblush|mistyrose|gainsboro|lightgrey|silver|darkgray|gray|dimgray|lightslategray|slategray|darkslategray|black|grey)(?!\()\b + name + support.constant.color.extra + + + match + \b(argb|blur|color|saturate|desaturate|lighten|darken|grayscale|fade|fadein|fadeout|spin|mix|hue|saturation|lightness|alpha|round|ceil|floor|percentage|translate|rotate|scale|skew|skewX|skewY|matrix|matrix3d|translate3d|translateX|translateY|translateZ|scale3d|scaleX|scaleY|scaleZ|rotate3d|rotateX|rotateY|rotateZ|perspective|greyscale|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem|contrast|red|green|blue|luma)\b + name + support.function.any-method.builtin.less + + + match + \b(rgb|rgba|hsl|hsla|url|format|src|cubic-bezier)\b + name + support.function.any-method.builtin.css + + + captures + + 1 + + name + support.function.any-method.vendor.css + + + match + (-(?:webkit|moz|khtml|o|ms|icab)-(?:linear-gradient|gradient|radial-gradient|interpolation-mode|search-decoration|search-cancel-button)) + + + match + \b(color-stop|from|to)\b + name + support.function.any-method.webkit.gradient.css + + + captures + + 1 + + name + support.function.less + + + match + (\.[a-zA-Z0-9_-]+)\s*(;|\() + + + begin + // + end + $\n? + name + comment.line.double-slash.less + + + match + (?>@[a-zA-Z0-9_-][\w-]*+)(?!:) + name + variable.other.less + + + match + @[a-zA-Z0-9_-][\w-]* + name + variable.declaration.less + + + match + @{[a-zA-Z0-9_-][\w-]*} + name + variable.interpolation.less + + + match + !important|$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|(?<!\()/=|%=|\+=|\-=|&=|when\b + name + keyword.operator.less + + + match + \{|\} + name + meta.brace.curly.js + + + match + \(|\) + name + meta.brace.round.js + + + match + \[|\] + name + meta.brace.square.js + + + scopeName + source.css.less + uuid + 9343D324-75A1-4733-A5C0-5D1D4B6182D0 + + \ No newline at end of file diff --git a/sublime/Packages/LESS/Symbol List.tmPreferences b/sublime/Packages/LESS/Symbol List.tmPreferences new file mode 100644 index 0000000..2019e0f --- /dev/null +++ b/sublime/Packages/LESS/Symbol List.tmPreferences @@ -0,0 +1,17 @@ + + + + + name + Symbol List + scope + entity.other.less.mixin, entity.other.attribute-name.class.css, entity.other.attribute-name.id, keyword.control.html.elements + settings + + showInSymbolList + 1 + + uuid + 0A0DA1FC-59DE-4FD9-9A2C-63C6811A3C39 + + diff --git a/sublime/Packages/LESS/package-metadata.json b/sublime/Packages/LESS/package-metadata.json new file mode 100644 index 0000000..dabc41b --- /dev/null +++ b/sublime/Packages/LESS/package-metadata.json @@ -0,0 +1 @@ +{"url": "https://github.com/danro/LESS-sublime", "version": "2013.01.30.14.26.17", "description": "LESS syntax highlighting for Sublime Text 2."} \ No newline at end of file diff --git a/sublime/Packages/LESS/readme.md b/sublime/Packages/LESS/readme.md new file mode 100644 index 0000000..e0da2f3 --- /dev/null +++ b/sublime/Packages/LESS/readme.md @@ -0,0 +1,87 @@ +# LESS syntax package for Sublime Text 2 + +Provides syntax highlighting for `.less` files + support for comment-toggle commands. + +## Installing + +**With the Package Control plugin:** The easiest way to install this package is through Package Control, which can be found at this site: [http://wbond.net/sublime_packages/package_control](http://wbond.net/sublime_packages/package_control) + +Once you install Package Control, restart ST2 and bring up the Command Palette (Command+Shift+p on OS X, Control+Shift+p on Linux/Windows). Select "Package Control: Install Package", wait while Package Control fetches the latest package list, then select `LESS` when the list appears. + +**Without Git:** Download the latest source zip from [github](https://github.com/danro/LESS-sublime/zipball/master) and extract the files to your Sublime Text "Packages" directory, into a new directory named `LESS`. + +**With Git:** Clone the repository in your Sublime Text "Packages" directory: + + git clone git://github.com/danro/LESS-sublime.git LESS + +The "Packages" directory is located at: + +* OS X: + `~/Library/Application Support/Sublime Text 2/Packages/` +* Linux: + `~/.Sublime Text 2/Packages/` +* Windows: + `%APPDATA%/Sublime Text 2/Packages/` + +## Color Scheme + +Some snippets to use in your favorite `.tmTheme` file. + +```xml + + name + css.id + scope + meta.selector.css entity.other.attribute-name.id + settings + + foreground + #E5D56D + + + + name + css.class + scope + entity.other.attribute-name.class + settings + + foreground + #A0C25F + + + + name + less.mixin + scope + entity.other.less.mixin + settings + + foreground + #98E124 + + + + name + css.element + scope + keyword.control.html.elements + settings + + foreground + #DA4632 + + + + name + css.string + scope + meta.attribute-selector.css string + settings + + foreground + #FF950A + + +``` +[Copied from my Sublime theme](https://github.com/danro/refined-theme/blob/master/Color%20Schemes/Danro.tmTheme) \ No newline at end of file diff --git a/sublime/Packages/LESS/tests.less b/sublime/Packages/LESS/tests.less new file mode 100644 index 0000000..6e830dd --- /dev/null +++ b/sublime/Packages/LESS/tests.less @@ -0,0 +1,231 @@ + +/* LESS syntax coloring tests */ + +// -------------------------------------------------- +// Functions + +rgb(200, 200, 200); +rgba(200, 200, 200, 0.5); +hsl(50%, 45%, 90%); +hsla(50%, 45%, 90%, 50%); + +saturate(@color, 10%); +desaturate(@color, 10%); +lighten(@color, 10%); +darken(@color, 10%); +greyscale(@color, 10%); + +fadein(@color, 10%); +fadeout(@color, 10%); +fade(@color, 50%); + +spin(@color, 10); +mix(@color1, @color2, @weight); +contrast(@color1, @darkcolor, @lightcolor); + +argb(@color); +hue(@color); +saturation(@color); +lightness(@color); +red(@color); +green(@color); +blue(@color); +alpha(@color); +luma(@color); +@new: hsl(hue(@old), 45%, 90%); +@color: green; + +round(1.67); +ceil(2.4); +floor(2.6); +percentage(0.5); + +background: url("/images/some/place/nice.jpg"); +background: url('/images/some/place/nice.jpg'); +background: url(/images/some/place/nice.jpg); + +// -------------------------------------------------- +// Strings / Interpolation + +@base-url: "http://assets.fnord.com"; +background-image: url("@{base-url}/images/bg.png"); + +.class { + filter: ~"ms:alwaysHasItsOwnSyntax.For.Stuff()"; +} + +@name: blocked; +.@{name} { + color: black; +} + +@str: "hello"; +@var: ~`"@{str}".toUpperCase() + '!'`; +@color: color(`window.colors.baseColor`); +@darkcolor: darken(@color, 10%); + +.svg-url-test { + border-image: url('data:image/svg+xml,') 30.76923% 29.16667% repeat; + border-width: 0 0 8px; + border-style: solid; +} + +// -------------------------------------------------- +// Imports +@import "library"; +@import "typo.css"; + +// -------------------------------------------------- +// Variables + +@nice-blue: #5B83AD; +@light-blue: @nice-blue + #111; + +#header { color: @light-blue; } + +// -------------------------------------------------- +// Nesting + +body { + .navigation { + color: red; + } +} + +#header { + color: black; + + .navigation { + font-size: 12px; + } + .logo { + width: 300px; + } +} + +.clearfix { + display: block; + zoom: 1; + + &:after { + content: " "; + display: block; + font-size: 0; + height: 0; + clear: both; + visibility: hidden; + } +} + +.child, .sibling { + .parent & { + color: black; + } + & + & { + color: red; + } +} + +// -------------------------------------------------- +// Mixins + +.bordered { + border-top: dotted 1px black; + border-bottom: solid 2px black; +} + +#menu a { + color: #111; + .bordered; +} + +.post a { + color: red; + .bordered; +} + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} +.box-shadow(2px, 5px); + +.mixin (dark, @color) { + color: darken(@color, 10%); +} +.mixin (light, @color) { + color: lighten(@color, 10%); +} +.mixin (@_, @color) { + display: block; +} + +.mixin (@a) when (lightness(@a) >= 50%) { + background-color: black; +} +.mixin (@a) when (lightness(@a) < 50%) { + background-color: white; +} +.mixin (@a) { + color: @a; +} + +.mixin (@a, @b: 0) when (isnumber(@b)) { ... } +.mixin (@a, @b: black) when (iscolor(@b)) { ... } + +// -------------------------------------------------- +// Operations + +@base: 5%; +@filler: @base * 2; +@other: @base + @filler; + +color: #888 / 4; +background-color: @base-color + #111; +height: 100% / 2 + @filler; + +// -------------------------------------------------- +// Namespaces & Accessors + +#bundle { + .button { + display: block; + border: 1px solid black; + background-color: grey; + &:hover { background-color: magenta } + } + .tab { } + .citation { } +} + +#header a { + color: orange; + #bundle > .button; +} + +#defaults { + @width: 960px; + @color: black; +} + +.article { color: #294366; } + +.comment { + width: #defaults[@width]; + color: .article['color']; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +// -------------------------------------------------- +// Media queries + +@media (min-width: 768px) and (max-width: 979px) { + #grid > .core(@gridColumnWidth768, @gridGutterWidth768); + border-width: 0 0 8px; + border-style: solid; +} diff --git a/sublime/Packages/LineEndings/.gitignore b/sublime/Packages/LineEndings/.gitignore new file mode 100644 index 0000000..a1ba83b --- /dev/null +++ b/sublime/Packages/LineEndings/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.cache +*.sublime-project \ No newline at end of file diff --git a/sublime/Packages/LineEndings/Commands.sublime-commands b/sublime/Packages/LineEndings/Commands.sublime-commands new file mode 100644 index 0000000..a12b928 --- /dev/null +++ b/sublime/Packages/LineEndings/Commands.sublime-commands @@ -0,0 +1,65 @@ +[ + + { + "args": { + "type": "cr" + }, + "caption": "Line Ending: Mac OS 9", + "checkbox": true, + "command": "set_line_ending" + }, + { + "args": { + "type": "windows" + }, + "caption": "Line Ending: Windows", + "checkbox": true, + "command": "set_line_ending" + }, + { + "args": { + "type": "unix" + }, + "caption": "Line Ending: Unix", + "checkbox": true, + "command": "set_line_ending" + }, + + { + "args": { + "type": "cr" + }, + "caption": "Line Ending to all views on window: Mac OS 9", + "command": "set_line_ending_window" + }, + { + "args": { + "type": "windows" + }, + "caption": "Line Ending to all views on window: Windows", + "command": "set_line_ending_window" + }, + { + "args": { + "type": "unix" + }, + "caption": "Line Ending to all views on window: Unix", + "command": "set_line_ending_window" + }, + + { + "args": { + "type": "spaces" + }, + "caption": "Indentation: Convert to all views on window to Spaces", + "command": "convert_indentation_window" + }, + { + "args": { + "type": "tabs" + }, + "caption": "Indentation: Convert to all views on window to Tabs", + "command": "convert_indentation_window" + } + +] \ No newline at end of file diff --git a/sublime/Packages/LineEndings/Indentation.sublime-menu b/sublime/Packages/LineEndings/Indentation.sublime-menu new file mode 100644 index 0000000..e9944a2 --- /dev/null +++ b/sublime/Packages/LineEndings/Indentation.sublime-menu @@ -0,0 +1,13 @@ +[ + { "caption": "-" }, + { "command": "convert_indentation_window", "args": {"type": "spaces"}, "caption": "Convert Indentation to all views on window to Spaces"}, + { "command": "convert_indentation_window", "args": {"type": "tabs"}, "caption": "Convert Indentation to all views on window to Tabs" }, + { "caption": "-" }, + { "command": "set_line_ending_window", "args": {"type": "cr"}, "caption": "Line Ending to all views on window: Mac OS 9"}, + { "command": "set_line_ending_window", "args": {"type": "windows"}, "caption": "Line Ending to all views on window: Windows" }, + { "command": "set_line_ending_window", "args": {"type": "unix"}, "caption": "Line Ending to all views on window: Unix" }, + {"caption":"-"}, + { "command": "set_line_ending", "args": {"type": "cr"}, "caption": "Line Ending: Mac OS 9", "checkbox": true }, + { "command": "set_line_ending", "args": {"type": "windows"}, "caption": "Line Ending: Windows", "checkbox": true }, + { "command": "set_line_ending", "args": {"type": "unix"}, "caption": "Line Ending: Unix", "checkbox": true } +] \ No newline at end of file diff --git a/sublime/Packages/LineEndings/LineEndings.py b/sublime/Packages/LineEndings/LineEndings.py new file mode 100644 index 0000000..85f8434 --- /dev/null +++ b/sublime/Packages/LineEndings/LineEndings.py @@ -0,0 +1,67 @@ +import sublime, sublime_plugin + +s = sublime.load_settings('LineEndings.sublime-settings') +class Pref: + def load(self): + Pref.show_line_endings_on_status_bar = s.get('show_line_endings_on_status_bar', True) + Pref.alert_when_line_ending_is = s.get('alert_when_line_ending_is', []) + Pref.auto_convert_line_endings_to = s.get('auto_convert_line_endings_to', '') + +Pref = Pref() +Pref.load() +s.add_on_change('reload', lambda:Pref.load()) + +class StatusBarLineEndings(sublime_plugin.EventListener): + + def on_load(self, view): + if view.line_endings() in Pref.alert_when_line_ending_is: + sublime.message_dialog(u''+view.line_endings()+' line endings detected on file:\n\n'+view.file_name()); + if Pref.auto_convert_line_endings_to != '' and view.line_endings() != Pref.auto_convert_line_endings_to: + view.run_command('set_line_ending', {"type":Pref.auto_convert_line_endings_to}) + if Pref.show_line_endings_on_status_bar: + self.show(view) + + def on_activated(self, view): + if Pref.show_line_endings_on_status_bar: + self.show(view) + + def on_post_save(self, view): + if Pref.show_line_endings_on_status_bar: + self.show(view) + + def show(self, view): + if view is not None: + if view.is_loading(): + sublime.set_timeout(lambda:self.show(view), 100) + else: + view.set_status('line_endings', view.line_endings()) + sublime.set_timeout(lambda:view.set_status('line_endings', view.line_endings()), 400) + +class SetLineEndingWindowCommand(sublime_plugin.TextCommand): + + def run(self, view, type): + active_view = sublime.active_window().active_view() + for view in sublime.active_window().views(): + sublime.active_window().focus_view(view); + view.run_command('set_line_ending', {"type":type}) + view.set_status('line_endings', view.line_endings()) + sublime.active_window().focus_view(active_view); + + def is_enabled(self): + return len(sublime.active_window().views()) + +class ConvertIndentationWindowCommand(sublime_plugin.TextCommand): + + def run(self, view, type): + active_view = sublime.active_window().active_view() + for view in sublime.active_window().views(): + sublime.active_window().focus_view(view); + if type == 'spaces': + view.run_command('expand_tabs', {"set_translate_tabs":True}) + else: + view.run_command('unexpand_tabs', {"set_translate_tabs":True}) + sublime.active_window().focus_view(active_view); + + + def is_enabled(self): + return len(sublime.active_window().views()) \ No newline at end of file diff --git a/sublime/Packages/LineEndings/LineEndings.sublime-settings b/sublime/Packages/LineEndings/LineEndings.sublime-settings new file mode 100644 index 0000000..6300539 --- /dev/null +++ b/sublime/Packages/LineEndings/LineEndings.sublime-settings @@ -0,0 +1,12 @@ +{ + // To show line endings type on status bar + "show_line_endings_on_status_bar" : true, + + // show an alert when the line ending is on the list. + "alert_when_line_ending_is" : [], + //example: "alert_when_line_ending_is":["Windows","Unix","CR"] + + // auto convert line endings onload to: + "auto_convert_line_endings_to" : "" + +} \ No newline at end of file diff --git a/sublime/Packages/LineEndings/Main.sublime-menu b/sublime/Packages/LineEndings/Main.sublime-menu new file mode 100644 index 0000000..ee4d541 --- /dev/null +++ b/sublime/Packages/LineEndings/Main.sublime-menu @@ -0,0 +1,35 @@ +[ + { + "caption": "Preferences", + "mnemonic": "n", + "id": "preferences", + "children": + [ + { + "caption": "Package Settings", + "mnemonic": "P", + "id": "package-settings", + "children": + [ + { + "caption": "LineEndings", + "children": + [ + { + "command": "open_file", + "args": {"file": "${packages}/LineEndings/LineEndings.sublime-settings"}, + "caption": "Settings – Default" + }, + { + "command": "open_file", + "args": {"file": "${packages}/User/LineEndings.sublime-settings"}, + "caption": "Settings – User" + }, + { "caption": "-" } + ] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/sublime/Packages/LineEndings/license.txt b/sublime/Packages/LineEndings/license.txt new file mode 100644 index 0000000..ed95cfe --- /dev/null +++ b/sublime/Packages/LineEndings/license.txt @@ -0,0 +1,19 @@ +"None are so hopelessly enslaved as those who falsely believe they are free." + Johann Wolfgang von Goethe + +Copyright (C) 2012 Tito Bouzout + +This license apply to all the files inside this program unless noted +different for some files or portions of code inside these files. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation. http://www.gnu.org/licenses/gpl.html + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see http://www.gnu.org/licenses/gpl.html \ No newline at end of file diff --git a/sublime/Packages/LineEndings/package-metadata.json b/sublime/Packages/LineEndings/package-metadata.json new file mode 100644 index 0000000..ab85b4a --- /dev/null +++ b/sublime/Packages/LineEndings/package-metadata.json @@ -0,0 +1 @@ +{"url": "https://github.com/SublimeText/LineEndings", "version": "2013.02.23.18.50.15", "description": "On statusbar and on command palete."} \ No newline at end of file diff --git a/sublime/Packages/LineEndings/readme.md b/sublime/Packages/LineEndings/readme.md new file mode 100644 index 0000000..35fb387 --- /dev/null +++ b/sublime/Packages/LineEndings/readme.md @@ -0,0 +1,25 @@ +# Description + + +Provides line endings and convert indentation shortcuts for Sublime Text 2. See: http://www.sublimetext.com/ + +Allows to: + +* Show the current "line ending" on status bar. +* Change line endings from the command palette. +* Change line endings from the "tab size" menu of the statusbar. +* Display an alert when the line_ending is not some you expect. +* Convert indentation to spaces or tabs for all views on current window +* Convert line endings for all views on current window + +# Todo + +Show mixed line endings. + +# Installation + +Install this repository via "Package Control" http://wbond.net/sublime_packages/package_control + +# Contributors + + * polyvertex \ No newline at end of file diff --git a/sublime/Packages/Package Control/Default.sublime-commands b/sublime/Packages/Package Control/Default.sublime-commands new file mode 100644 index 0000000..7d823ee --- /dev/null +++ b/sublime/Packages/Package Control/Default.sublime-commands @@ -0,0 +1,64 @@ +[ + { + "caption": "Package Control: Add Repository", + "command": "add_repository" + }, + { + "caption": "Package Control: Add Channel", + "command": "add_repository_channel" + }, + { + "caption": "Package Control: Create Binary Package File", + "command": "create_binary_package" + }, + { + "caption": "Package Control: Create Package File", + "command": "create_package" + }, + { + "caption": "Package Control: Disable Package", + "command": "disable_package" + }, + { + "caption": "Package Control: Discover Packages", + "command": "discover_packages" + }, + { + "caption": "Package Control: Enable Package", + "command": "enable_package" + }, + { + "caption": "Package Control: Install Package", + "command": "install_package" + }, + { + "caption": "Package Control: List Packages", + "command": "list_packages" + }, + { + "caption": "Package Control: Remove Package", + "command": "remove_package" + }, + { + "caption": "Package Control: Upgrade Package", + "command": "upgrade_package" + }, + { + "caption": "Package Control: Upgrade/Overwrite All Packages", + "command": "upgrade_all_packages" + }, + { + "caption": "Preferences: Package Control Settings – Default", + "command": "open_file", "args": + { + "file": "${packages}/Package Control/Package Control.sublime-settings" + } + }, + { + "caption": "Preferences: Package Control Settings – User", + "command": "open_file", "args": + { + "file": "${packages}/User/Package Control.sublime-settings" + } + } +] diff --git a/sublime/Packages/Package Control/Main.sublime-menu b/sublime/Packages/Package Control/Main.sublime-menu new file mode 100644 index 0000000..cbe83d1 --- /dev/null +++ b/sublime/Packages/Package Control/Main.sublime-menu @@ -0,0 +1,45 @@ +[ + { + "caption": "Preferences", + "mnemonic": "n", + "id": "preferences", + "children": + [ + { + "caption": "Package Settings", + "mnemonic": "P", + "id": "package-settings", + "children": + [ + { + "caption": "Package Control", + "children": + [ + { + "command": "open_file", "args": + { + "file": "${packages}/Package Control/Package Control.sublime-settings" + }, + "caption": "Settings – Default" + }, + { + "command": "open_file", "args": + { + "file": "${packages}/User/Package Control.sublime-settings" + }, + "caption": "Settings – User" + }, + { "caption": "-" } + ] + } + ] + }, + { + "caption": "Package Control", + "mnemonic": "C", + "command": "show_overlay", + "args": {"overlay": "command_palette", "text": "Package Control: "} + } + ] + } +] diff --git a/sublime/Packages/Package Control/Package Control.py b/sublime/Packages/Package Control/Package Control.py new file mode 100644 index 0000000..515159a --- /dev/null +++ b/sublime/Packages/Package Control/Package Control.py @@ -0,0 +1,4810 @@ +# coding=utf-8 +import sublime +import sublime_plugin +import os +import sys +import subprocess +import zipfile +import urllib +import urllib2 +import json +from fnmatch import fnmatch +import re +import threading +import datetime +import time +import shutil +import tempfile +import httplib +import socket +import hashlib +import base64 +import locale +import urlparse +import gzip +import StringIO +import zlib + + +if os.name == 'nt': + from ctypes import windll, create_unicode_buffer + + +def add_to_path(path): + # Python 2.x on Windows can't properly import from non-ASCII paths, so + # this code added the DOC 8.3 version of the lib folder to the path in + # case the user's username includes non-ASCII characters + if os.name == 'nt': + buf = create_unicode_buffer(512) + if windll.kernel32.GetShortPathNameW(path, buf, len(buf)): + path = buf.value + + if path not in sys.path: + sys.path.append(path) + + +lib_folder = os.path.join(sublime.packages_path(), 'Package Control', 'lib') +add_to_path(os.path.join(lib_folder, 'all')) + + +import semver + + +if os.name == 'nt': + add_to_path(os.path.join(lib_folder, 'windows')) + from ntlm import ntlm + + +def unicode_from_os(e): + # This is needed as some exceptions coming from the OS are + # already encoded and so just calling unicode(e) will result + # in an UnicodeDecodeError as the string isn't in ascii form. + try: + # Sublime Text on OS X does not seem to report the correct encoding + # so we hard-code that to UTF-8 + encoding = 'UTF-8' if os.name == 'darwin' else locale.getpreferredencoding() + return unicode(str(e), encoding) + + # If the "correct" encoding did not work, try some defaults, and then just + # obliterate characters that we can't seen to decode properly + except UnicodeDecodeError: + encodings = ['utf-8', 'cp1252'] + for encoding in encodings: + try: + return unicode(str(e), encoding, errors='strict') + except: + pass + return unicode(str(e), errors='replace') + + +def create_cmd(args, basename_binary=False): + 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) + + +# Monkey patch AbstractBasicAuthHandler to prevent infinite recursion +def non_recursive_http_error_auth_reqed(self, authreq, host, req, headers): + authreq = headers.get(authreq, None) + + if not hasattr(self, 'retried'): + self.retried = 0 + + if self.retried > 5: + raise urllib2.HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + + if authreq: + mo = urllib2.AbstractBasicAuthHandler.rx.search(authreq) + if mo: + scheme, quote, realm = mo.groups() + if scheme.lower() == 'basic': + return self.retry_http_basic_auth(host, req, realm) + +urllib2.AbstractBasicAuthHandler.http_error_auth_reqed = non_recursive_http_error_auth_reqed + + +class DebuggableHTTPResponse(httplib.HTTPResponse): + """ + A custom HTTPResponse that formats debugging info for Sublime Text + """ + + _debug_protocol = 'HTTP' + + def __init__(self, sock, debuglevel=0, strict=0, method=None): + # We have to use a positive debuglevel to get it passed to here, + # however we don't want to use it because by default debugging prints + # to the stdout and we can't capture it, so we use a special -1 value + if debuglevel == 5: + debuglevel = -1 + httplib.HTTPResponse.__init__(self, sock, debuglevel, strict, method) + + def begin(self): + return_value = httplib.HTTPResponse.begin(self) + if self.debuglevel == -1: + print '%s: Urllib2 %s Debug Read' % (__name__, self._debug_protocol) + headers = self.msg.headers + versions = { + 9: 'HTTP/0.9', + 10: 'HTTP/1.0', + 11: 'HTTP/1.1' + } + status_line = versions[self.version] + ' ' + str(self.status) + ' ' + self.reason + headers.insert(0, status_line) + for line in headers: + print u" %s" % line.rstrip() + return return_value + + def read(self, *args): + try: + return httplib.HTTPResponse.read(self, *args) + except (httplib.IncompleteRead) as (e): + return e.partial + + +class DebuggableHTTPSResponse(DebuggableHTTPResponse): + """ + A version of DebuggableHTTPResponse that sets the debug protocol to HTTPS + """ + + _debug_protocol = 'HTTPS' + + +class DebuggableHTTPConnection(httplib.HTTPConnection): + """ + A custom HTTPConnection that formats debugging info for Sublime Text + """ + + response_class = DebuggableHTTPResponse + _debug_protocol = 'HTTP' + + def __init__(self, host, port=None, strict=None, + timeout=socket._GLOBAL_DEFAULT_TIMEOUT, **kwargs): + self.passwd = kwargs.get('passwd') + + # Python 2.6.1 on OS X 10.6 does not include these + self._tunnel_host = None + self._tunnel_port = None + self._tunnel_headers = {} + + httplib.HTTPConnection.__init__(self, host, port, strict, timeout) + + def connect(self): + if self.debuglevel == -1: + print '%s: Urllib2 %s Debug General' % (__name__, self._debug_protocol) + print u" Connecting to %s on port %s" % (self.host, self.port) + httplib.HTTPConnection.connect(self) + + def send(self, string): + # We have to use a positive debuglevel to get it passed to the + # HTTPResponse object, however we don't want to use it because by + # default debugging prints to the stdout and we can't capture it, so + # we temporarily set it to -1 for the standard httplib code + reset_debug = False + if self.debuglevel == 5: + reset_debug = 5 + self.debuglevel = -1 + httplib.HTTPConnection.send(self, string) + if reset_debug or self.debuglevel == -1: + if len(string.strip()) > 0: + print '%s: Urllib2 %s Debug Write' % (__name__, self._debug_protocol) + for line in string.strip().splitlines(): + print ' ' + line + if reset_debug: + self.debuglevel = reset_debug + + def request(self, method, url, body=None, headers={}): + original_headers = headers.copy() + + # Handles the challenge request response cycle before the real request + proxy_auth = headers.get('Proxy-Authorization') + if os.name == 'nt' and proxy_auth and proxy_auth.lstrip()[0:4] == 'NTLM': + # The default urllib2.AbstractHTTPHandler automatically sets the + # Connection header to close because of urllib.addinfourl(), but in + # this case we are going to do some back and forth first for the NTLM + # proxy auth + headers['Connection'] = 'Keep-Alive' + self._send_request(method, url, body, headers) + + response = self.getresponse() + + content_length = int(response.getheader('content-length', 0)) + if content_length: + response._safe_read(content_length) + + proxy_authenticate = response.getheader('proxy-authenticate', None) + if not proxy_authenticate: + raise URLError('Invalid NTLM proxy authentication response') + ntlm_challenge = re.sub('^\s*NTLM\s+', '', proxy_authenticate) + + if self.host.find(':') != -1: + host_port = self.host + else: + host_port = "%s:%s" % (self.host, self.port) + username, password = self.passwd.find_user_password(None, host_port) + domain = '' + user = username + if username.find('\\') != -1: + domain, user = username.split('\\', 1) + + challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_challenge) + new_proxy_authorization = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user, + domain, password, negotiate_flags) + original_headers['Proxy-Authorization'] = new_proxy_authorization + response.close() + + httplib.HTTPConnection.request(self, method, url, body, original_headers) + + +class DebuggableHTTPHandler(urllib2.HTTPHandler): + """ + A custom HTTPHandler that formats debugging info for Sublime Text + """ + + def __init__(self, debuglevel=0, debug=False, **kwargs): + # This is a special value that will not trigger the standard debug + # functionality, but custom code where we can format the output + if debug: + self._debuglevel = 5 + else: + self._debuglevel = debuglevel + self.passwd = kwargs.get('passwd') + + def http_open(self, req): + def http_class_wrapper(host, **kwargs): + kwargs['passwd'] = self.passwd + return DebuggableHTTPConnection(host, **kwargs) + + return self.do_open(http_class_wrapper, req) + + +class RateLimitException(httplib.HTTPException, urllib2.URLError): + """ + An exception for when the rate limit of an API has been exceeded. + """ + + def __init__(self, host, limit): + httplib.HTTPException.__init__(self) + self.host = host + self.limit = limit + + def __str__(self): + return ('Rate limit of %s exceeded for %s' % (self.limit, self.host)) + + +if os.name == 'nt': + class ProxyNtlmAuthHandler(urllib2.BaseHandler): + + handler_order = 300 + auth_header = 'Proxy-Authorization' + + def __init__(self, password_manager=None): + if password_manager is None: + password_manager = HTTPPasswordMgr() + self.passwd = password_manager + self.retried = 0 + + def http_error_407(self, req, fp, code, msg, headers): + proxy_authenticate = headers.get('proxy-authenticate') + if os.name != 'nt' or proxy_authenticate[0:4] != 'NTLM': + return None + + type1_flags = ntlm.NTLM_TYPE1_FLAGS + + if req.host.find(':') != -1: + host_port = req.host + else: + host_port = "%s:%s" % (req.host, req.port) + username, password = self.passwd.find_user_password(None, host_port) + if not username: + return None + + if username.find('\\') == -1: + type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied + + negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username, type1_flags) + auth = 'NTLM %s' % negotiate_message + if req.headers.get(self.auth_header, None) == auth: + return None + req.add_unredirected_header(self.auth_header, auth) + return self.parent.open(req, timeout=req.timeout) + + +# The following code is wrapped in a try because the Linux versions of Sublime +# Text do not include the ssl module due to the fact that different distros +# have different versions +try: + import ssl + + class InvalidCertificateException(httplib.HTTPException, urllib2.URLError): + """ + An exception for when an SSL certification is not valid for the URL + it was presented for. + """ + + def __init__(self, host, cert, reason): + httplib.HTTPException.__init__(self) + self.host = host + self.cert = cert + self.reason = reason + + def __str__(self): + return ('Host %s returned an invalid certificate (%s) %s\n' % + (self.host, self.reason, self.cert)) + + + class ValidatingHTTPSConnection(DebuggableHTTPConnection): + """ + A custom HTTPConnection class that validates SSL certificates, and + allows proxy authentication for HTTPS connections. + """ + + default_port = httplib.HTTPS_PORT + + response_class = DebuggableHTTPSResponse + _debug_protocol = 'HTTPS' + + def __init__(self, host, port=None, key_file=None, cert_file=None, + ca_certs=None, strict=None, **kwargs): + passed_args = {} + if 'timeout' in kwargs: + passed_args['timeout'] = kwargs['timeout'] + DebuggableHTTPConnection.__init__(self, host, port, strict, **passed_args) + + self.passwd = kwargs.get('passwd') + self.key_file = key_file + self.cert_file = cert_file + self.ca_certs = ca_certs + if 'user_agent' in kwargs: + self.user_agent = kwargs['user_agent'] + if self.ca_certs: + self.cert_reqs = ssl.CERT_REQUIRED + else: + self.cert_reqs = ssl.CERT_NONE + + def get_valid_hosts_for_cert(self, cert): + """ + Returns a list of valid hostnames for an SSL certificate + + :param cert: A dict from SSLSocket.getpeercert() + + :return: An array of hostnames + """ + + if 'subjectAltName' in cert: + return [x[1] for x in cert['subjectAltName'] + if x[0].lower() == 'dns'] + else: + return [x[0][1] for x in cert['subject'] + if x[0][0].lower() == 'commonname'] + + def validate_cert_host(self, cert, hostname): + """ + Checks if the cert is valid for the hostname + + :param cert: A dict from SSLSocket.getpeercert() + + :param hostname: A string hostname to check + + :return: A boolean if the cert is valid for the hostname + """ + + hosts = self.get_valid_hosts_for_cert(cert) + for host in hosts: + host_re = host.replace('.', '\.').replace('*', '[^.]*') + if re.search('^%s$' % (host_re,), hostname, re.I): + return True + return False + + def _tunnel(self, ntlm_follow_up=False): + """ + This custom _tunnel method allows us to read and print the debug + log for the whole response before throwing an error, and adds + support for proxy authentication + """ + + self._proxy_host = self.host + self._proxy_port = self.port + self._set_hostport(self._tunnel_host, self._tunnel_port) + + self._tunnel_headers['Host'] = u"%s:%s" % (self.host, self.port) + self._tunnel_headers['User-Agent'] = self.user_agent + self._tunnel_headers['Proxy-Connection'] = 'Keep-Alive' + + request = "CONNECT %s:%d HTTP/1.1\r\n" % (self.host, self.port) + for header, value in self._tunnel_headers.iteritems(): + request += "%s: %s\r\n" % (header, value) + self.send(request + "\r\n") + + response = self.response_class(self.sock, strict=self.strict, + method=self._method) + (version, code, message) = response._read_status() + + status_line = u"%s %s %s" % (version, code, message.rstrip()) + headers = [status_line] + + if self.debuglevel in [-1, 5]: + print '%s: Urllib2 %s Debug Read' % (__name__, self._debug_protocol) + print u" %s" % status_line + + content_length = 0 + close_connection = False + while True: + line = response.fp.readline() + if line == '\r\n': break + + headers.append(line.rstrip()) + + parts = line.rstrip().split(': ', 1) + name = parts[0].lower() + value = parts[1].lower().strip() + if name == 'content-length': + content_length = int(value) + + if name in ['connection', 'proxy-connection'] and value == 'close': + close_connection = True + + if self.debuglevel in [-1, 5]: + print u" %s" % line.rstrip() + + # Handle proxy auth for SSL connections since regular urllib2 punts on this + if code == 407 and self.passwd and ('Proxy-Authorization' not in self._tunnel_headers or ntlm_follow_up): + if content_length: + response._safe_read(content_length) + + supported_auth_methods = {} + for line in headers: + parts = line.split(': ', 1) + if parts[0].lower() != 'proxy-authenticate': + continue + details = parts[1].split(' ', 1) + supported_auth_methods[details[0].lower()] = details[1] if len(details) > 1 else '' + + username, password = self.passwd.find_user_password(None, "%s:%s" % ( + self._proxy_host, self._proxy_port)) + + do_ntlm_follow_up = False + + if 'digest' in supported_auth_methods: + response_value = self.build_digest_response( + supported_auth_methods['digest'], username, password) + if response_value: + self._tunnel_headers['Proxy-Authorization'] = u"Digest %s" % response_value + + elif 'basic' in supported_auth_methods: + response_value = u"%s:%s" % (username, password) + response_value = base64.b64encode(response_value).strip() + self._tunnel_headers['Proxy-Authorization'] = u"Basic %s" % response_value + + elif 'ntlm' in supported_auth_methods and os.name == 'nt': + ntlm_challenge = supported_auth_methods['ntlm'] + if not len(ntlm_challenge): + type1_flags = ntlm.NTLM_TYPE1_FLAGS + if username.find('\\') == -1: + type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied + + negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username, type1_flags) + self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % negotiate_message + do_ntlm_follow_up = True + else: + domain = '' + user = username + if username.find('\\') != -1: + domain, user = username.split('\\', 1) + + challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_challenge) + self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user, + domain, password, negotiate_flags) + + if 'Proxy-Authorization' in self._tunnel_headers: + self.host = self._proxy_host + self.port = self._proxy_port + + # If the proxy wanted the connection closed, we need to make a new connection + if close_connection: + self.sock.close() + self.sock = socket.create_connection((self.host, self.port), self.timeout) + + return self._tunnel(do_ntlm_follow_up) + + if code != 200: + self.close() + raise socket.error("Tunnel connection failed: %d %s" % (code, + message.strip())) + + def build_digest_response(self, fields, username, password): + """ + Takes a Proxy-Authenticate: Digest header and creates a response + header + + :param fields: + The string portion of the Proxy-Authenticate header after + "Digest " + + :param username: + The username to use for the response + + :param password: + The password to use for the response + + :return: + None if invalid Proxy-Authenticate header, otherwise the + string of fields for the Proxy-Authorization: Digest header + """ + + fields = urllib2.parse_keqv_list(urllib2.parse_http_list(fields)) + + realm = fields.get('realm') + nonce = fields.get('nonce') + qop = fields.get('qop') + algorithm = fields.get('algorithm') + if algorithm: + algorithm = algorithm.lower() + opaque = fields.get('opaque') + + if algorithm in ['md5', None]: + def hash(string): + return hashlib.md5(string).hexdigest() + elif algorithm == 'sha': + def hash(string): + return hashlib.sha1(string).hexdigest() + else: + return None + + host_port = u"%s:%s" % (self.host, self.port) + + a1 = "%s:%s:%s" % (username, realm, password) + a2 = "CONNECT:%s" % host_port + ha1 = hash(a1) + ha2 = hash(a2) + + if qop == None: + response = hash(u"%s:%s:%s" % (ha1, nonce, ha2)) + elif qop == 'auth': + nc = '00000001' + cnonce = hash(urllib2.randombytes(8))[:8] + response = hash(u"%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2)) + else: + return None + + response_fields = { + 'username': username, + 'realm': realm, + 'nonce': nonce, + 'response': response, + 'uri': host_port + } + if algorithm: + response_fields['algorithm'] = algorithm + if qop == 'auth': + response_fields['nc'] = nc + response_fields['cnonce'] = cnonce + response_fields['qop'] = qop + if opaque: + response_fields['opaque'] = opaque + + return ', '.join([u"%s=\"%s\"" % (field, response_fields[field]) for field in response_fields]) + + def connect(self): + """ + Adds debugging and SSL certification validation + """ + + if self.debuglevel == -1: + print '%s: Urllib2 HTTPS Debug General' % __name__ + print u" Connecting to %s on port %s" % (self.host, self.port) + + self.sock = socket.create_connection((self.host, self.port), self.timeout) + if self._tunnel_host: + self._tunnel() + + if self.debuglevel == -1: + print u"%s: Urllib2 HTTPS Debug General" % __name__ + print u" Connecting to %s on port %s" % (self.host, self.port) + print u" CA certs file at %s" % (self.ca_certs) + + self.sock = ssl.wrap_socket(self.sock, keyfile=self.key_file, + certfile=self.cert_file, cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs) + + if self.debuglevel == -1: + print u" Successfully upgraded connection to %s:%s with SSL" % ( + self.host, self.port) + + # This debugs and validates the SSL certificate + if self.cert_reqs & ssl.CERT_REQUIRED: + cert = self.sock.getpeercert() + + if self.debuglevel == -1: + subjectMap = { + 'organizationName': 'O', + 'commonName': 'CN', + 'organizationalUnitName': 'OU', + 'countryName': 'C', + 'serialNumber': 'serialNumber', + 'commonName': 'CN', + 'localityName': 'L', + 'stateOrProvinceName': 'S' + } + subject_list = list(cert['subject']) + subject_list.reverse() + subject_parts = [] + for pair in subject_list: + if pair[0][0] in subjectMap: + field_name = subjectMap[pair[0][0]] + else: + field_name = pair[0][0] + subject_parts.append(field_name + '=' + pair[0][1]) + + print u" Server SSL certificate:" + print u" subject: " + ','.join(subject_parts) + if 'subjectAltName' in cert: + print u" common name: " + cert['subjectAltName'][0][1] + if 'notAfter' in cert: + print u" expire date: " + cert['notAfter'] + + hostname = self.host.split(':', 0)[0] + + if not self.validate_cert_host(cert, hostname): + if self.debuglevel == -1: + print u" Certificate INVALID" + + raise InvalidCertificateException(hostname, cert, + 'hostname mismatch') + + if self.debuglevel == -1: + print u" Certificate validated for %s" % hostname + + if hasattr(urllib2, 'HTTPSHandler'): + class ValidatingHTTPSHandler(urllib2.HTTPSHandler): + """ + A urllib2 handler that validates SSL certificates for HTTPS requests + """ + + def __init__(self, **kwargs): + # This is a special value that will not trigger the standard debug + # functionality, but custom code where we can format the output + self._debuglevel = 0 + if 'debug' in kwargs and kwargs['debug']: + self._debuglevel = 5 + elif 'debuglevel' in kwargs: + self._debuglevel = kwargs['debuglevel'] + self._connection_args = kwargs + + def https_open(self, req): + def http_class_wrapper(host, **kwargs): + full_kwargs = dict(self._connection_args) + full_kwargs.update(kwargs) + return ValidatingHTTPSConnection(host, **full_kwargs) + + try: + return self.do_open(http_class_wrapper, req) + except urllib2.URLError, e: + if type(e.reason) == ssl.SSLError and e.reason.args[0] == 1: + raise InvalidCertificateException(req.host, '', + e.reason.args[1]) + raise + + https_request = urllib2.AbstractHTTPHandler.do_request_ + +except (ImportError): + pass + + +def preferences_filename(): + """:return: The appropriate settings filename based on the version of Sublime Text""" + + if int(sublime.version()) >= 2174: + return 'Preferences.sublime-settings' + return 'Global.sublime-settings' + + +class ThreadProgress(): + """ + Animates an indicator, [= ], in the status area while a thread runs + + :param thread: + The thread to track for activity + + :param message: + The message to display next to the activity indicator + + :param success_message: + The message to display once the thread is complete + """ + + def __init__(self, thread, message, success_message): + self.thread = thread + self.message = message + self.success_message = success_message + self.addend = 1 + self.size = 8 + sublime.set_timeout(lambda: self.run(0), 100) + + def run(self, i): + if not self.thread.is_alive(): + if hasattr(self.thread, 'result') and not self.thread.result: + sublime.status_message('') + return + sublime.status_message(self.success_message) + return + + before = i % self.size + after = (self.size - 1) - before + + sublime.status_message('%s [%s=%s]' % \ + (self.message, ' ' * before, ' ' * after)) + + if not after: + self.addend = -1 + if not before: + self.addend = 1 + i += self.addend + + sublime.set_timeout(lambda: self.run(i), 100) + + +class PlatformComparator(): + def get_best_platform(self, platforms): + ids = [sublime.platform() + '-' + sublime.arch(), sublime.platform(), + '*'] + + for id in ids: + if id in platforms: + return id + + return None + + +class ChannelProvider(PlatformComparator): + """ + Retrieves a channel and provides an API into the information + + The current channel/repository infrastructure caches repository info into + the channel to improve the Package Control client performance. This also + has the side effect of lessening the load on the GitHub and BitBucket APIs + and getting around not-infrequent HTTP 503 errors from those APIs. + + :param channel: + The URL of the channel + + :param package_manager: + An instance of :class:`PackageManager` used to download the file + """ + + def __init__(self, channel, package_manager): + self.channel_info = None + self.channel = channel + self.package_manager = package_manager + self.unavailable_packages = [] + + def match_url(self): + """Indicates if this provider can handle the provided channel""" + + return True + + def fetch_channel(self): + """Retrieves and loads the JSON for other methods to use""" + + if self.channel_info != None: + return + + channel_json = self.package_manager.download_url(self.channel, + 'Error downloading channel.') + if channel_json == False: + self.channel_info = False + return + + try: + channel_info = json.loads(channel_json) + except (ValueError): + print '%s: Error parsing JSON from channel %s.' % (__name__, + self.channel) + channel_info = False + + self.channel_info = channel_info + + def get_name_map(self): + """:return: A dict of the mapping for URL slug -> package name""" + + self.fetch_channel() + if self.channel_info == False: + return False + return self.channel_info.get('package_name_map', {}) + + def get_renamed_packages(self): + """:return: A dict of the packages that have been renamed""" + + self.fetch_channel() + if self.channel_info == False: + return False + return self.channel_info.get('renamed_packages', {}) + + def get_repositories(self): + """:return: A list of the repository URLs""" + + self.fetch_channel() + if self.channel_info == False: + return False + return self.channel_info['repositories'] + + def get_certs(self): + """ + Provides a secure way for distribution of SSL CA certificates + + Unfortunately Python does not include a bundle of CA certs with urllib2 + to perform SSL certificate validation. To circumvent this issue, + Package Control acts as a distributor of the CA certs for all HTTPS + URLs of package downloads. + + The default channel scrapes and caches info about all packages + periodically, and in the process it checks the CA certs for all of + the HTTPS URLs listed in the repositories. The contents of the CA cert + files are then hashed, and the CA cert is stored in a filename with + that hash. This is a fingerprint to ensure that Package Control has + the appropriate CA cert for a domain name. + + Next, the default channel file serves up a JSON object of the domain + names and the hashes of their current CA cert files. If Package Control + does not have the appropriate hash for a domain, it may retrieve it + from the channel server. To ensure that Package Control is talking to + a trusted authority to get the CA certs from, the CA cert for + sublime.wbond.net is bundled with Package Control. Then when downloading + the channel file, Package Control can ensure that the channel file's + SSL certificate is valid, thus ensuring the resulting CA certs are + legitimate. + + As a matter of optimization, the distribution of Package Control also + includes the current CA certs for all known HTTPS domains that are + included in the channel, as of the time when Package Control was + last released. + + :return: A dict of {'Domain Name': ['cert_file_hash', 'cert_file_download_url']} + """ + + self.fetch_channel() + if self.channel_info == False: + return False + return self.channel_info.get('certs', {}) + + def get_packages(self, repo): + """ + Provides access to the repository info that is cached in a channel + + :param repo: + The URL of the repository to get the cached info of + + :return: + A dict in the format: + { + 'Package Name': { + # Package details - see example-packages.json for format + }, + ... + } + or False if there is an error + """ + + self.fetch_channel() + if self.channel_info == False: + return False + if self.channel_info.get('packages', False) == False: + return False + if self.channel_info['packages'].get(repo, False) == False: + return False + + output = {} + for package in self.channel_info['packages'][repo]: + copy = package.copy() + + platforms = copy['platforms'].keys() + best_platform = self.get_best_platform(platforms) + + if not best_platform: + self.unavailable_packages.append(copy['name']) + continue + + copy['downloads'] = copy['platforms'][best_platform] + + del copy['platforms'] + + copy['url'] = copy['homepage'] + del copy['homepage'] + + output[copy['name']] = copy + + return output + + def get_unavailable_packages(self): + """ + Provides a list of packages that are unavailable for the current + platform/architecture that Sublime Text is running on. + + This list will be empty unless get_packages() is called first. + + :return: A list of package names + """ + + return self.unavailable_packages + + +# The providers (in order) to check when trying to download a channel +_channel_providers = [ChannelProvider] + + +class PackageProvider(PlatformComparator): + """ + Generic repository downloader that fetches package info + + With the current channel/repository architecture where the channel file + caches info from all includes repositories, these package providers just + serve the purpose of downloading packages not in the default channel. + + The structure of the JSON a repository should contain is located in + example-packages.json. + + :param repo: + The URL of the package repository + + :param package_manager: + An instance of :class:`PackageManager` used to download the file + """ + def __init__(self, repo, package_manager): + self.repo_info = None + self.repo = repo + self.package_manager = package_manager + self.unavailable_packages = [] + + def match_url(self): + """Indicates if this provider can handle the provided repo""" + + return True + + def fetch_repo(self): + """Retrieves and loads the JSON for other methods to use""" + + if self.repo_info != None: + return + + repository_json = self.package_manager.download_url(self.repo, + 'Error downloading repository.') + if repository_json == False: + self.repo_info = False + return + + try: + self.repo_info = json.loads(repository_json) + except (ValueError): + print '%s: Error parsing JSON from repository %s.' % (__name__, + self.repo) + self.repo_info = False + + def get_packages(self): + """ + Provides access to the repository info that is cached in a channel + + :return: + A dict in the format: + { + 'Package Name': { + # Package details - see example-packages.json for format + }, + ... + } + or False if there is an error + """ + + self.fetch_repo() + if self.repo_info == False: + return False + + output = {} + + for package in self.repo_info['packages']: + + platforms = package['platforms'].keys() + best_platform = self.get_best_platform(platforms) + + if not best_platform: + self.unavailable_packages.append(package['name']) + continue + + # Rewrites the legacy "zipball" URLs to the new "zip" format + downloads = package['platforms'][best_platform] + rewritten_downloads = [] + for download in downloads: + download['url'] = re.sub( + '^(https://nodeload.github.com/[^/]+/[^/]+/)zipball(/.*)$', + '\\1zip\\2', download['url']) + rewritten_downloads.append(download) + + info = { + 'name': package['name'], + 'description': package.get('description'), + 'url': package.get('homepage', self.repo), + 'author': package.get('author'), + 'last_modified': package.get('last_modified'), + 'downloads': rewritten_downloads + } + + output[package['name']] = info + + return output + + def get_renamed_packages(self): + """:return: A dict of the packages that have been renamed""" + + return self.repo_info.get('renamed_packages', {}) + + def get_unavailable_packages(self): + """ + Provides a list of packages that are unavailable for the current + platform/architecture that Sublime Text is running on. + + This list will be empty unless get_packages() is called first. + + :return: A list of package names + """ + + return self.unavailable_packages + + +class NonCachingProvider(): + """ + Base for package providers that do not need to cache the JSON + """ + + def fetch_json(self, url): + """ + Retrieves and parses the JSON from a URL + + :return: A dict or list from the JSON, or False on error + """ + + repository_json = self.package_manager.download_url(url, + 'Error downloading repository.') + if repository_json == False: + return False + try: + return json.loads(repository_json) + except (ValueError): + print '%s: Error parsing JSON from repository %s.' % (__name__, + url) + return False + + def get_unavailable_packages(self): + """ + Method for compatibility with PackageProvider class. These providers + are based on API calls, and thus do not support different platform + downloads, making it impossible for there to be unavailable packages. + + :return: An empty list + """ + + return [] + + +class GitHubPackageProvider(NonCachingProvider): + """ + Allows using a public GitHub repository as the source for a single package + + :param repo: + The public web URL to the GitHub repository. Should be in the format + `https://github.com/user/package` for the master branch, or + `https://github.com/user/package/tree/{branch_name}` for any other + branch. + + :param package_manager: + An instance of :class:`PackageManager` used to access the API + """ + + def __init__(self, repo, package_manager): + # Clean off the trailing .git to be more forgiving + self.repo = re.sub('\.git$', '', repo) + self.package_manager = package_manager + + def match_url(self): + """Indicates if this provider can handle the provided repo""" + + master = re.search('^https?://github.com/[^/]+/[^/]+/?$', self.repo) + branch = re.search('^https?://github.com/[^/]+/[^/]+/tree/[^/]+/?$', + self.repo) + return master != None or branch != None + + def get_packages(self): + """Uses the GitHub API to construct necessary info for a package""" + + branch = 'master' + branch_match = re.search( + '^https?://github.com/[^/]+/[^/]+/tree/([^/]+)/?$', self.repo) + if branch_match != None: + branch = branch_match.group(1) + + api_url = re.sub('^https?://github.com/([^/]+)/([^/]+)($|/.*$)', + 'https://api.github.com/repos/\\1/\\2', self.repo) + + repo_info = self.fetch_json(api_url) + if repo_info == False: + return False + + # In addition to hitting the main API endpoint for this repo, we + # also have to list the commits to get the timestamp of the last + # commit since we use that to generate a version number + commit_api_url = api_url + '/commits?' + \ + urllib.urlencode({'sha': branch, 'per_page': 1}) + + commit_info = self.fetch_json(commit_api_url) + if commit_info == False: + return False + + # We specifically use nodeload.github.com here because the download + # URLs all redirect there, and some of the downloaders don't follow + # HTTP redirect headers + download_url = 'https://nodeload.github.com/' + \ + repo_info['owner']['login'] + '/' + \ + repo_info['name'] + '/zip/' + urllib.quote(branch) + + commit_date = commit_info[0]['commit']['committer']['date'] + timestamp = datetime.datetime.strptime(commit_date[0:19], + '%Y-%m-%dT%H:%M:%S') + utc_timestamp = timestamp.strftime( + '%Y.%m.%d.%H.%M.%S') + + homepage = repo_info['homepage'] + if not homepage: + homepage = repo_info['html_url'] + + package = { + 'name': repo_info['name'], + 'description': repo_info['description'] if \ + repo_info['description'] else 'No description provided', + 'url': homepage, + 'author': repo_info['owner']['login'], + 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), + 'downloads': [ + { + 'version': utc_timestamp, + 'url': download_url + } + ] + } + return {package['name']: package} + + def get_renamed_packages(self): + """For API-compatibility with :class:`PackageProvider`""" + + return {} + + +class GitHubUserProvider(NonCachingProvider): + """ + Allows using a GitHub user/organization as the source for multiple packages + + :param repo: + The public web URL to the GitHub user/org. Should be in the format + `https://github.com/user`. + + :param package_manager: + An instance of :class:`PackageManager` used to access the API + """ + + def __init__(self, repo, package_manager): + self.repo = repo + self.package_manager = package_manager + + def match_url(self): + """Indicates if this provider can handle the provided repo""" + + return re.search('^https?://github.com/[^/]+/?$', self.repo) != None + + def get_packages(self): + """Uses the GitHub API to construct necessary info for all packages""" + + user_match = re.search('^https?://github.com/([^/]+)/?$', self.repo) + user = user_match.group(1) + + api_url = 'https://api.github.com/users/%s/repos?per_page=100' % user + + repo_info = self.fetch_json(api_url) + if repo_info == False: + return False + + packages = {} + for package_info in repo_info: + # All packages for the user are made available, and always from + # the master branch. Anything else requires a custom packages.json + commit_api_url = ('https://api.github.com/repos/%s/%s/commits' + \ + '?sha=master&per_page=1') % (user, package_info['name']) + + commit_info = self.fetch_json(commit_api_url) + if commit_info == False: + return False + + commit_date = commit_info[0]['commit']['committer']['date'] + timestamp = datetime.datetime.strptime(commit_date[0:19], + '%Y-%m-%dT%H:%M:%S') + utc_timestamp = timestamp.strftime( + '%Y.%m.%d.%H.%M.%S') + + homepage = package_info['homepage'] + if not homepage: + homepage = package_info['html_url'] + + package = { + 'name': package_info['name'], + 'description': package_info['description'] if \ + package_info['description'] else 'No description provided', + 'url': homepage, + 'author': package_info['owner']['login'], + 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), + 'downloads': [ + { + 'version': utc_timestamp, + # We specifically use nodeload.github.com here because + # the download URLs all redirect there, and some of the + # downloaders don't follow HTTP redirect headers + 'url': 'https://nodeload.github.com/' + \ + package_info['owner']['login'] + '/' + \ + package_info['name'] + '/zip/master' + } + ] + } + packages[package['name']] = package + return packages + + def get_renamed_packages(self): + """For API-compatibility with :class:`PackageProvider`""" + + return {} + + +class BitBucketPackageProvider(NonCachingProvider): + """ + Allows using a public BitBucket repository as the source for a single package + + :param repo: + The public web URL to the BitBucket repository. Should be in the format + `https://bitbucket.org/user/package`. + + :param package_manager: + An instance of :class:`PackageManager` used to access the API + """ + + def __init__(self, repo, package_manager): + self.repo = repo + self.package_manager = package_manager + + def match_url(self): + """Indicates if this provider can handle the provided repo""" + + return re.search('^https?://bitbucket.org', self.repo) != None + + def get_packages(self): + """Uses the BitBucket API to construct necessary info for a package""" + + api_url = re.sub('^https?://bitbucket.org/', + 'https://api.bitbucket.org/1.0/repositories/', self.repo) + api_url = api_url.rstrip('/') + + repo_info = self.fetch_json(api_url) + if repo_info == False: + return False + + # Since HG allows for arbitrary main branch names, we have to hit + # this URL just to get that info + main_branch_url = api_url + '/main-branch/' + main_branch_info = self.fetch_json(main_branch_url) + if main_branch_info == False: + return False + + # Grabbing the changesets is necessary because we construct the + # version number from the last commit timestamp + changeset_url = api_url + '/changesets/' + main_branch_info['name'] + last_commit = self.fetch_json(changeset_url) + if last_commit == False: + return False + + commit_date = last_commit['timestamp'] + timestamp = datetime.datetime.strptime(commit_date[0:19], + '%Y-%m-%d %H:%M:%S') + utc_timestamp = timestamp.strftime( + '%Y.%m.%d.%H.%M.%S') + + homepage = repo_info['website'] + if not homepage: + homepage = self.repo + package = { + 'name': repo_info['name'], + 'description': repo_info['description'] if \ + repo_info['description'] else 'No description provided', + 'url': homepage, + 'author': repo_info['owner'], + 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), + 'downloads': [ + { + 'version': utc_timestamp, + 'url': self.repo + '/get/' + \ + last_commit['node'] + '.zip' + } + ] + } + return {package['name']: package} + + def get_renamed_packages(self): + """For API-compatibility with :class:`PackageProvider`""" + + return {} + + +# The providers (in order) to check when trying to download repository info +_package_providers = [BitBucketPackageProvider, GitHubPackageProvider, + GitHubUserProvider, PackageProvider] + + +class BinaryNotFoundError(Exception): + """If a necessary executable is not found in the PATH on the system""" + + pass + + +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) + + +class NonHttpError(Exception): + """If a downloader had a non-clean exit, but it was not due to an HTTP error""" + + pass + + +class Downloader(): + """ + A base downloader that actually performs downloading URLs + + The SSL module is not included with the bundled Python for Linux + users of Sublime Text, so Linux machines will fall back to using curl + or wget for HTTPS URLs. + """ + + 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 + + :return: + The CA cert bundle path on success, or False on error + """ + + cert_match = False + + certs_list = self.settings.get('certs', {}) + certs_dir = os.path.join(sublime.packages_path(), 'Package Control', + 'certs') + ca_bundle_path = os.path.join(certs_dir, 'ca-bundle.crt') + + cert_info = certs_list.get(domain) + if cert_info: + cert_match = self.locate_cert(certs_dir, cert_info[0], cert_info[1]) + + wildcard_info = certs_list.get('*') + if wildcard_info: + cert_match = self.locate_cert(certs_dir, wildcard_info[0], wildcard_info[1]) or cert_match + + if not cert_match: + print '%s: No CA certs available for %s.' % (__name__, domain) + return False + + return ca_bundle_path + + def locate_cert(self, certs_dir, cert_id, location): + """ + Makes sure the SSL cert specified has been added to the CA cert + bundle that is present on the machine + + :param certs_dir: + The path of the folder that contains the cert files + + :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) + + :return: + If the cert specified (by cert_id) is present on the machine and + part of the ca-bundle.crt file in the certs_dir + """ + + cert_path = os.path.join(certs_dir, cert_id) + if not os.path.exists(cert_path): + if str(location) != '': + if re.match('^https?://', location): + contents = self.download_cert(cert_id, location) + else: + contents = self.load_cert(cert_id, location) + if contents: + self.save_cert(certs_dir, cert_id, contents) + return True + return False + return True + + def download_cert(self, cert_id, url): + """ + 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) + + :return: + The contents of the CA cert(s) + """ + + cert_downloader = self.__class__(self.settings) + return cert_downloader.download(url, + 'Error downloading CA certs for %s.' % (domain), timeout, 1) + + def load_cert(self, cert_id, path): + """ + 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) + + :return: + The contents of the CA cert(s) + """ + + if os.path.exists(path): + with open(path, 'rb') as f: + return f.read() + + def save_cert(self, certs_dir, cert_id, contents): + """ + Saves CA cert(s) to the certs_dir (and ca-bundle.crt file) + + :param certs_dir: + The path of the folder that contains the cert files + + :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(certs_dir, 'ca-bundle.crt') + cert_path = os.path.join(certs_dir, cert_id) + with open(cert_path, 'wb') as f: + f.write(contents) + with open(ca_bundle_path, 'ab') as f: + f.write("\n" + contents) + + def decode_response(self, encoding, response): + if encoding == 'gzip': + return gzip.GzipFile(fileobj=StringIO.StringIO(response)).read() + elif encoding == 'deflate': + decompresser = zlib.decompressobj(-zlib.MAX_WBITS) + return decompresser.decompress(response) + decompresser.flush() + return response + + +class CliDownloader(Downloader): + """ + 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 + """ + + for dir in os.environ['PATH'].split(os.pathsep): + 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'): + print u"%s: Trying to execute command %s" % ( + __name__, create_cmd(args)) + + 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 + + +class UrlLib2Downloader(Downloader): + """ + A downloader that uses the Python urllib2 module + + :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 download(self, url, error_message, timeout, tries): + """ + Downloads a URL and returns the contents + + Uses the proxy settings from the Package Control.sublime-settings file, + however there seem to be a decent number of proxies that this code + does not work with. Patches welcome! + + :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 + + :return: + The string contents of the URL, or False on error + """ + + http_proxy = self.settings.get('http_proxy') + https_proxy = self.settings.get('https_proxy') + if http_proxy or https_proxy: + proxies = {} + if http_proxy: + proxies['http'] = http_proxy + if https_proxy: + proxies['https'] = https_proxy + proxy_handler = urllib2.ProxyHandler(proxies) + else: + proxy_handler = urllib2.ProxyHandler() + + password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() + proxy_username = self.settings.get('proxy_username') + proxy_password = self.settings.get('proxy_password') + if proxy_username and proxy_password: + if http_proxy: + password_manager.add_password(None, http_proxy, proxy_username, + proxy_password) + if https_proxy: + password_manager.add_password(None, https_proxy, proxy_username, + proxy_password) + + handlers = [proxy_handler] + if os.name == 'nt': + ntlm_auth_handler = ProxyNtlmAuthHandler(password_manager) + handlers.append(ntlm_auth_handler) + + basic_auth_handler = urllib2.ProxyBasicAuthHandler(password_manager) + digest_auth_handler = urllib2.ProxyDigestAuthHandler(password_manager) + handlers.extend([digest_auth_handler, basic_auth_handler]) + + debug = self.settings.get('debug') + + if debug: + print u"%s: Urllib2 Debug Proxy" % __name__ + print u" http_proxy: %s" % http_proxy + print u" https_proxy: %s" % https_proxy + print u" proxy_username: %s" % proxy_username + print u" proxy_password: %s" % proxy_password + + 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) + if not bundle_path: + return False + bundle_path = bundle_path.encode(sys.getfilesystemencoding()) + handlers.append(ValidatingHTTPSHandler(ca_certs=bundle_path, + debug=debug, passwd=password_manager, + user_agent=self.settings.get('user_agent'))) + else: + handlers.append(DebuggableHTTPHandler(debug=debug, + passwd=password_manager)) + urllib2.install_opener(urllib2.build_opener(*handlers)) + + while tries > 0: + tries -= 1 + try: + request = urllib2.Request(url, headers={ + "User-Agent": self.settings.get('user_agent'), + # 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. + "Accept-Encoding": "gzip,deflate"}) + http_file = urllib2.urlopen(request, timeout=timeout) + self.handle_rate_limit(http_file, url) + result = http_file.read() + encoding = http_file.headers.get('Content-Encoding') + return self.decode_response(encoding, result) + + except (httplib.HTTPException) as (e): + print '%s: %s HTTP exception %s (%s) downloading %s.' % ( + __name__, error_message, e.__class__.__name__, + unicode_from_os(e), url) + + except (urllib2.HTTPError) as (e): + # Make sure we obey Github's rate limiting headers + self.handle_rate_limit(e, url) + + # Bitbucket and Github return 503 a decent amount + if unicode_from_os(e.code) == '503': + print ('%s: Downloading %s was rate limited, ' + + 'trying again') % (__name__, url) + continue + print '%s: %s HTTP error %s downloading %s.' % (__name__, + error_message, unicode_from_os(e.code), url) + + except (urllib2.URLError) as (e): + + # Bitbucket and Github timeout a decent amount + if unicode_from_os(e.reason) == 'The read operation timed out' \ + or unicode_from_os(e.reason) == 'timed out': + print (u'%s: Downloading %s timed out, trying ' + + u'again') % (__name__, url) + continue + print u'%s: %s URL error %s downloading %s.' % (__name__, + error_message, unicode_from_os(e.reason), url) + break + return False + + def handle_rate_limit(self, response, url): + """ + Checks the headers of a respone object to make sure we are obeying the + rate limit + + :param response: + The response object that has a headers dict + + :param url: + The URL that was requested + + :raises: + RateLimitException when the rate limit has been hit + """ + + limit_remaining = response.headers.get('X-RateLimit-Remaining', 1) + if str(limit_remaining) == '0': + hostname = urlparse.urlparse(url).hostname + limit = response.headers.get('X-RateLimit-Limit', 1) + raise RateLimitException(hostname, limit) + + +class WgetDownloader(CliDownloader): + """ + A downloader that uses the command line program wget + + :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 + self.debug = settings.get('debug') + self.wget = self.find_binary('wget') + + def download(self, url, error_message, timeout, tries): + """ + 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 + + :return: + The string contents of the URL, or False on error + """ + + if not self.wget: + return False + + self.tmp_file = tempfile.NamedTemporaryFile().name + command = [self.wget, '--connect-timeout=' + str(int(timeout)), '-o', + self.tmp_file, '-O', '-', '-U', + self.settings.get('user_agent'), '--header', + # 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. + 'Accept-Encoding: gzip,deflate'] + + 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) + if not bundle_path: + return False + command.append(u'--ca-certificate=' + bundle_path) + + if self.debug: + command.append('-d') + else: + command.append('-S') + + 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 proxy_username: + command.append(u"--proxy-user=%s" % proxy_username) + if proxy_password: + command.append(u"--proxy-password=%s" % proxy_password) + + if self.debug: + print u"%s: Wget Debug Proxy" % __name__ + print u" http_proxy: %s" % http_proxy + print u" https_proxy: %s" % https_proxy + print u" proxy_username: %s" % proxy_username + print u" proxy_password: %s" % proxy_password + + command.append(url) + + if http_proxy: + os.putenv('http_proxy', http_proxy) + if https_proxy: + os.putenv('https_proxy', https_proxy) + + while tries > 0: + tries -= 1 + try: + result = self.execute(command) + + general, headers = self.parse_output() + encoding = headers.get('content-encoding') + if encoding: + result = self.decode_response(encoding, result) + + return result + + except (NonCleanExitError) as (e): + + try: + general, headers = self.parse_output() + self.handle_rate_limit(headers, url) + + if general['status'] == '503': + # GitHub and BitBucket seem to rate limit via 503 + print ('%s: Downloading %s was rate limited' + + ', trying again') % (__name__, url) + continue + + error_string = 'HTTP error %s %s' % (general['status'], + general['message']) + + except (NonHttpError) as (e): + + error_string = unicode_from_os(e) + + # GitHub and BitBucket seem to time out a lot + if error_string.find('timed out') != -1: + print ('%s: Downloading %s timed out, ' + + 'trying again') % (__name__, url) + continue + + print (u'%s: %s %s downloading %s.' % (__name__, error_message, + error_string, url)).encode('UTF-8') + + break + return False + + def parse_output(self): + with open(self.tmp_file, 'r') as f: + output = f.read().splitlines() + self.clean_tmp_file() + + error = None + header_lines = [] + if self.debug: + section = 'General' + last_section = None + for line in output: + if section == 'General': + if self.skippable_line(line): + continue + + # Skip blank lines + if line.strip() == '': + continue + + # Error lines + if line[0:5] == 'wget:': + error = line[5:].strip() + if line[0:7] == 'failed:': + error = line[7:].strip() + + if line == '---request begin---': + section = 'Write' + continue + elif line == '---request end---': + section = 'General' + continue + elif line == '---response begin---': + section = 'Read' + continue + elif line == '---response end---': + section = 'General' + continue + + if section != last_section: + print "%s: Wget HTTP Debug %s" % (__name__, section) + + if section == 'Read': + header_lines.append(line) + + print ' ' + line + last_section = section + + else: + for line in output: + if self.skippable_line(line): + continue + + # Check the resolving and connecting to lines for errors + if re.match('(Resolving |Connecting to )', line): + failed_match = re.search(' failed: (.*)$', line) + if failed_match: + error = failed_match.group(1).strip() + + # Error lines + if line[0:5] == 'wget:': + error = line[5:].strip() + if line[0:7] == 'failed:': + error = line[7:].strip() + + if line[0:2] == ' ': + header_lines.append(line.lstrip()) + + if error: + raise NonHttpError(error) + + return self.parse_headers(header_lines) + + def skippable_line(self, line): + # Skip date lines + if re.match('--\d{4}-\d{2}-\d{2}', line): + return True + if re.match('\d{4}-\d{2}-\d{2}', line): + return True + # Skip HTTP status code lines since we already have that info + if re.match('\d{3} ', line): + return True + # Skip Saving to and progress lines + if re.match('(Saving to:|\s*\d+K)', line): + return True + # Skip notice about ignoring body on HTTP error + if re.match('Skipping \d+ byte', line): + return True + + def parse_headers(self, output=None): + if not output: + with open(self.tmp_file, 'r') as f: + output = f.read().splitlines() + self.clean_tmp_file() + + general = { + 'version': '0.9', + 'status': '200', + 'message': 'OK' + } + headers = {} + for line in output: + # When using the -S option, headers have two spaces before them, + # additionally, valid headers won't have spaces, so this is always + # a safe operation to perform + line = line.lstrip() + if line.find('HTTP/') == 0: + match = re.match('HTTP/(\d\.\d)\s+(\d+)\s+(.*)$', line) + general['version'] = match.group(1) + general['status'] = match.group(2) + general['message'] = match.group(3) + else: + name, value = line.split(':', 1) + headers[name.lower()] = value.strip() + + return (general, headers) + + def handle_rate_limit(self, headers, url): + limit_remaining = headers.get('x-ratelimit-remaining', '1') + limit = headers.get('x-ratelimit-limit', '1') + + if str(limit_remaining) == '0': + hostname = urlparse.urlparse(url).hostname + raise RateLimitException(hostname, limit) + + +class CurlDownloader(CliDownloader): + """ + 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. + """ + + def __init__(self, settings): + self.settings = settings + self.curl = self.find_binary('curl') + + def download(self, url, error_message, timeout, tries): + """ + 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 + + :return: + The string contents of the URL, or False on error + """ + + if not self.curl: + return False + + 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] + + 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) + if not bundle_path: + return False + 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: + print u"%s: Curl Debug Proxy" % __name__ + print u" http_proxy: %s" % http_proxy + print u" https_proxy: %s" % https_proxy + print u" proxy_username: %s" % proxy_username + print 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) + + while tries > 0: + tries -= 1 + try: + output = self.execute(command) + + with open(self.tmp_file, 'r') as f: + headers = f.read() + self.clean_tmp_file() + + limit = 1 + limit_remaining = 1 + status = '200 OK' + for header in headers.splitlines(): + if header[0:5] == 'HTTP/': + status = re.sub('^HTTP/\d\.\d\s+', '', header) + if header.lower()[0:22] == 'x-ratelimit-remaining:': + limit_remaining = header.lower()[22:].strip() + if header.lower()[0:18] == 'x-ratelimit-limit:': + limit = header.lower()[18:].strip() + + if debug: + self.print_debug(self.stderr) + + if str(limit_remaining) == '0': + hostname = urlparse.urlparse(url).hostname + raise RateLimitException(hostname, limit) + + if status != '200 OK': + e = NonCleanExitError(22) + e.stderr = status + raise e + + 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'): + 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': + # GitHub and BitBucket seem to rate limit via 503 + print ('%s: Downloading %s was rate limited' + + ', trying again') % (__name__, url) + continue + error_string = 'HTTP error ' + code + elif e.returncode == 6: + error_string = 'URL error host not found' + elif e.returncode == 28: + # GitHub and BitBucket seem to time out a lot + print ('%s: Downloading %s timed out, trying ' + + 'again') % (__name__, url) + continue + else: + error_string = e.stderr.rstrip() + + print '%s: %s %s downloading %s.' % (__name__, error_message, + error_string, url) + break + + return False + + def print_debug(self, string): + section = 'General' + last_section = None + + output = '' + + for line in string.splitlines(): + # Placeholder for body of request + if line and line[0:2] == '{ ': + 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 + continue + + if line.strip() == '': + continue + + if section != last_section: + print "%s: Curl HTTP Debug %s" % (__name__, section) + + print ' ' + line + last_section = section + + return output + + +# 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 = {} + + +class RepositoryDownloader(threading.Thread): + """ + Downloads information about a repository in the background + + :param package_manager: + An instance of :class:`PackageManager` used to download files + + :param name_map: + The dict of name mapping for URL slug -> package name + + :param repo: + The URL of the repository to download info about + """ + + def __init__(self, package_manager, name_map, repo): + self.package_manager = package_manager + self.repo = repo + self.packages = {} + self.name_map = name_map + threading.Thread.__init__(self) + + def run(self): + for provider_class in _package_providers: + provider = provider_class(self.repo, self.package_manager) + if provider.match_url(): + break + packages = provider.get_packages() + if packages == False: + self.packages = False + return + + mapped_packages = {} + for package in packages.keys(): + mapped_package = self.name_map.get(package, package) + mapped_packages[mapped_package] = packages[package] + mapped_packages[mapped_package]['name'] = mapped_package + packages = mapped_packages + + self.packages = packages + self.renamed_packages = provider.get_renamed_packages() + self.unavailable_packages = provider.get_unavailable_packages() + + +class VcsUpgrader(): + """ + Base class for updating packages that are a version control repository on local disk + + :param vcs_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. + + :param update_command: + The command to pass to the version control executable to update the + repository. + + :param working_copy: + The local path to the working copy/package directory + + :param cache_length: + The lenth of time to cache if incoming changesets are available + """ + + def __init__(self, vcs_binary, update_command, working_copy, cache_length, debug): + self.binary = vcs_binary + self.update_command = update_command + self.working_copy = working_copy + self.cache_length = cache_length + self.debug = debug + + def execute(self, args, dir): + """ + Creates a subprocess with the executable/args + + :param args: + A list of the executable path and all arguments to it + + :param dir: + The directory in which to run the executable + + :return: A string of the executable output + """ + + startupinfo = None + if os.name == 'nt': + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + + if self.debug: + print u"%s: Trying to execute command %s" % ( + __name__, create_cmd(args)) + proc = subprocess.Popen(args, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + startupinfo=startupinfo, cwd=dir) + + return proc.stdout.read().replace('\r\n', '\n').rstrip(' \n\r') + + 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: + print u"%s: Using \"%s_binary\" from settings \"%s\"" % ( + __name__, self.vcs_type, self.binary) + 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: + print u"%s: Found %s at \"%s\"" % (__name__, self.vcs_type, + path) + 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: + dirs = ['/usr/local/git/bin'] + + for dir in dirs: + path = os.path.join(dir, name) + if os.path.exists(path): + if self.debug: + print u"%s: Found %s at \"%s\"" % (__name__, self.vcs_type, + path) + return path + + if self.debug: + print u"%s: Could not find %s on your machine" % (__name__, + self.vcs_type) + return None + + +class GitUpgrader(VcsUpgrader): + """ + Allows upgrading a local git-repository-based package + """ + + vcs_type = 'git' + + def retrieve_binary(self): + """ + Returns the path to the git executable + + :return: The string path to the executable or False on error + """ + + name = 'git' + 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: + sublime.error_message(('%s: Unable to find %s. ' + + 'Please set the git_binary setting by accessing the ' + + 'Preferences > Package Settings > %s > ' + + u'Settings – User menu entry. The Settings – Default entry ' + + 'can be used for reference, but changes to that will be ' + + 'overwritten upon next upgrade.') % (__name__, name, __name__)) + return False + + if os.name == 'nt': + tortoise_plink = self.find_binary('TortoisePlink.exe') + if tortoise_plink: + os.environ.setdefault('GIT_SSH', tortoise_plink) + return binary + + def run(self): + """ + Updates the repository with remote changes + + :return: False or error, or True on success + """ + + binary = self.retrieve_binary() + if not binary: + return False + args = [binary] + args.extend(self.update_command) + self.execute(args, self.working_copy) + return True + + def incoming(self): + """:return: bool if remote revisions are available""" + + cache_key = self.working_copy + '.incoming' + working_copy_cache = _channel_repository_cache.get(cache_key) + if working_copy_cache and working_copy_cache.get('time') > \ + time.time(): + return working_copy_cache.get('data') + + binary = self.retrieve_binary() + if not binary: + return False + self.execute([binary, 'fetch'], self.working_copy) + args = [binary, 'log'] + args.append('..' + '/'.join(self.update_command[-2:])) + output = self.execute(args, self.working_copy) + incoming = len(output) > 0 + + _channel_repository_cache[cache_key] = { + 'time': time.time() + self.cache_length, + 'data': incoming + } + return incoming + + +class HgUpgrader(VcsUpgrader): + """ + Allows upgrading a local mercurial-repository-based package + """ + + vcs_type = 'hg' + + def retrieve_binary(self): + """ + Returns the path to the hg executable + + :return: The string path to the executable or False on error + """ + + name = 'hg' + 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: + sublime.error_message(('%s: Unable to find %s. ' + + 'Please set the hg_binary setting by accessing the ' + + 'Preferences > Package Settings > %s > ' + + u'Settings – User menu entry. The Settings – Default entry ' + + 'can be used for reference, but changes to that will be ' + + 'overwritten upon next upgrade.') % (__name__, name, __name__)) + return False + return binary + + def run(self): + """ + Updates the repository with remote changes + + :return: False or error, or True on success + """ + + binary = self.retrieve_binary() + if not binary: + return False + args = [binary] + args.extend(self.update_command) + self.execute(args, self.working_copy) + return True + + def incoming(self): + """:return: bool if remote revisions are available""" + + cache_key = self.working_copy + '.incoming' + working_copy_cache = _channel_repository_cache.get(cache_key) + if working_copy_cache and working_copy_cache.get('time') > \ + time.time(): + return working_copy_cache.get('data') + + binary = self.retrieve_binary() + if not binary: + return False + args = [binary, 'in', '-q'] + args.append(self.update_command[-1]) + output = self.execute(args, self.working_copy) + incoming = len(output) > 0 + + _channel_repository_cache[cache_key] = { + 'time': time.time() + self.cache_length, + 'data': incoming + } + return incoming + + +def clear_directory(directory, ignore_paths=None): + 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) as (e): + was_exception = True + + return not was_exception + + + +class PackageManager(): + """ + Allows downloading, creating, installing, upgrading, and deleting packages + + Delegates metadata retrieval to the _channel_providers and + _package_providers classes. Uses VcsUpgrader-based classes for handling + git and hg repositories in the Packages folder. Downloader classes are + utilized to fetch contents of URLs. + + Also handles displaying package messaging, and sending usage information to + the usage server. + """ + + def __init__(self): + # Here we manually copy the settings since sublime doesn't like + # code accessing settings from threads + self.settings = {} + settings = sublime.load_settings(__name__ + '.sublime-settings') + for setting in ['timeout', 'repositories', 'repository_channels', + 'package_name_map', 'dirs_to_ignore', 'files_to_ignore', + 'package_destination', 'cache_length', 'auto_upgrade', + 'files_to_ignore_binary', 'files_to_keep', 'dirs_to_keep', + 'git_binary', 'git_update_command', 'hg_binary', + 'hg_update_command', 'http_proxy', 'https_proxy', + 'auto_upgrade_ignore', 'auto_upgrade_frequency', + 'submit_usage', 'submit_url', 'renamed_packages', + 'files_to_include', 'files_to_include_binary', 'certs', + 'ignore_vcs_packages', 'proxy_username', 'proxy_password', + 'debug', 'user_agent']: + if settings.get(setting) == None: + continue + self.settings[setting] = settings.get(setting) + + # https_proxy will inherit from http_proxy unless it is set to a + # string value or false + no_https_proxy = self.settings.get('https_proxy') in ["", None] + if no_https_proxy and self.settings.get('http_proxy'): + self.settings['https_proxy'] = self.settings.get('http_proxy') + if self.settings['https_proxy'] == False: + self.settings['https_proxy'] = '' + + self.settings['platform'] = sublime.platform() + self.settings['version'] = sublime.version() + + def compare_versions(self, version1, version2): + """ + Compares to version strings to see which is greater + + Date-based version numbers (used by GitHub and BitBucket providers) + are automatically pre-pended with a 0 so they are always less than + version 1.0. + + :return: + -1 if version1 is less than version2 + 0 if they are equal + 1 if version1 is greater than version2 + """ + + def date_compat(v): + # We prepend 0 to all date-based version numbers so that developers + # may switch to explicit versioning from GitHub/BitBucket + # versioning based on commit dates + date_match = re.match('(\d{4})\.(\d{2})\.(\d{2})\.(\d{2})\.(\d{2})\.(\d{2})$', v) + if date_match: + v = '0.%s.%s.%s.%s.%s.%s' % date_match.groups() + return v + + def semver_compat(v): + # When translating dates into semver, the way to get each date + # segment into the version is to treat the year and month as + # minor and patch, and then the rest as a numeric build version + # with four different parts. The result looks like: + # 0.2012.11+10.31.23.59 + date_match = re.match('(\d{4}(?:\.\d{2}){2})\.(\d{2}(?:\.\d{2}){3})$', v) + if date_match: + v = '%s+%s' % (date_match.group(1), date_match.group(2)) + + # Semver must have major, minor, patch + elif re.match('^\d+$', v): + v += '.0.0' + elif re.match('^\d+\.\d+$', v): + v += '.0' + return v + + def cmp_compat(v): + return [int(x) for x in re.sub(r'(\.0+)*$', '', v).split(".")] + + version1 = date_compat(version1) + version2 = date_compat(version2) + try: + return semver.compare(semver_compat(version1), semver_compat(version2)) + except (ValueError): + return cmp(cmp_compat(version1), cmp_compat(version2)) + + def download_url(self, url, error_message): + """ + 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 + + :return: + The string contents of the URL, or False on error + """ + + has_ssl = 'ssl' in sys.modules and hasattr(urllib2, 'HTTPSHandler') + is_ssl = re.search('^https://', url) != None + downloader = None + + if (is_ssl and has_ssl) or not is_ssl: + downloader = UrlLib2Downloader(self.settings) + else: + for downloader_class in [CurlDownloader, WgetDownloader]: + try: + downloader = downloader_class(self.settings) + break + except (BinaryNotFoundError): + pass + + if not downloader: + sublime.error_message(('%s: Unable to download %s due to no ' + + 'ssl module available and no capable program found. Please ' + + 'install curl or wget.') % (__name__, url)) + return False + + url = url.replace(' ', '%20') + hostname = urlparse.urlparse(url).hostname.lower() + timeout = self.settings.get('timeout', 3) + + rate_limited_cache = _channel_repository_cache.get('rate_limited_domains', {}) + if rate_limited_cache.get('time') and rate_limited_cache.get('time') > time.time(): + rate_limited_domains = rate_limited_cache.get('data', []) + else: + rate_limited_domains = [] + + if self.settings.get('debug'): + try: + ip = socket.gethostbyname(hostname) + except (socket.gaierror) as (e): + ip = unicode_from_os(e) + + print u"%s: Download Debug" % __name__ + print u" URL: %s" % url + print u" Resolved IP: %s" % ip + print u" Timeout: %s" % str(timeout) + + if hostname in rate_limited_domains: + if self.settings.get('debug'): + print u" Skipping due to hitting rate limit for %s" % hostname + return False + + try: + return downloader.download(url, error_message, timeout, 3) + except (RateLimitException) as (e): + + rate_limited_domains.append(hostname) + _channel_repository_cache['rate_limited_domains'] = { + 'data': rate_limited_domains, + 'time': time.time() + self.settings.get('cache_length', + 300) + } + + print ('%s: Hit rate limit of %s for %s, skipping all futher ' + + 'download requests for this domain') % (__name__, + e.limit, e.host) + return False + + def get_metadata(self, package): + """ + Returns the package metadata for an installed package + + :return: + A dict with the keys: + version + url + description + or an empty dict on error + """ + + metadata_filename = os.path.join(self.get_package_dir(package), + 'package-metadata.json') + if os.path.exists(metadata_filename): + with open(metadata_filename) as f: + try: + return json.load(f) + except (ValueError): + return {} + return {} + + def list_repositories(self): + """ + Returns a master list of all repositories pulled from all sources + + These repositories come from the channels specified in the + "repository_channels" setting, plus any repositories listed in the + "repositories" setting. + + :return: + A list of all available repositories + """ + + repositories = self.settings.get('repositories') + repository_channels = self.settings.get('repository_channels') + for channel in repository_channels: + channel = channel.strip() + + channel_repositories = None + + # Caches various info from channels for performance + cache_key = channel + '.repositories' + repositories_cache = _channel_repository_cache.get(cache_key) + if repositories_cache and repositories_cache.get('time') > \ + time.time(): + channel_repositories = repositories_cache.get('data') + + name_map_cache_key = channel + '.package_name_map' + name_map_cache = _channel_repository_cache.get( + name_map_cache_key) + if name_map_cache and name_map_cache.get('time') > \ + time.time(): + name_map = name_map_cache.get('data') + name_map.update(self.settings.get('package_name_map', {})) + self.settings['package_name_map'] = name_map + + renamed_cache_key = channel + '.renamed_packages' + renamed_cache = _channel_repository_cache.get( + renamed_cache_key) + if renamed_cache and renamed_cache.get('time') > \ + time.time(): + renamed_packages = renamed_cache.get('data') + renamed_packages.update(self.settings.get('renamed_packages', + {})) + self.settings['renamed_packages'] = renamed_packages + + unavailable_cache_key = channel + '.unavailable_packages' + unavailable_cache = _channel_repository_cache.get( + unavailable_cache_key) + if unavailable_cache and unavailable_cache.get('time') > \ + time.time(): + unavailable_packages = unavailable_cache.get('data') + unavailable_packages.extend(self.settings.get('unavailable_packages', + [])) + self.settings['unavailable_packages'] = unavailable_packages + + certs_cache_key = channel + '.certs' + certs_cache = _channel_repository_cache.get(certs_cache_key) + if certs_cache and certs_cache.get('time') > time.time(): + certs = self.settings.get('certs', {}) + certs.update(certs_cache.get('data')) + self.settings['certs'] = certs + + # If any of the info was not retrieved from the cache, we need to + # grab the channel to get it + if channel_repositories == None or \ + self.settings.get('package_name_map') == None or \ + self.settings.get('renamed_packages') == None: + + for provider_class in _channel_providers: + provider = provider_class(channel, self) + if provider.match_url(): + break + + channel_repositories = provider.get_repositories() + + if channel_repositories == False: + continue + _channel_repository_cache[cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': channel_repositories + } + + for repo in channel_repositories: + if provider.get_packages(repo) == False: + continue + packages_cache_key = repo + '.packages' + _channel_repository_cache[packages_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': provider.get_packages(repo) + } + + # Have the local name map override the one from the channel + name_map = provider.get_name_map() + name_map.update(self.settings.get('package_name_map', {})) + self.settings['package_name_map'] = name_map + _channel_repository_cache[name_map_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': name_map + } + + renamed_packages = provider.get_renamed_packages() + _channel_repository_cache[renamed_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': renamed_packages + } + if renamed_packages: + self.settings['renamed_packages'] = self.settings.get( + 'renamed_packages', {}) + self.settings['renamed_packages'].update(renamed_packages) + + unavailable_packages = provider.get_unavailable_packages() + _channel_repository_cache[unavailable_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': unavailable_packages + } + if unavailable_packages: + self.settings['unavailable_packages'] = self.settings.get( + 'unavailable_packages', []) + self.settings['unavailable_packages'].extend(unavailable_packages) + + certs = provider.get_certs() + _channel_repository_cache[certs_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': certs + } + if certs: + self.settings['certs'] = self.settings.get('certs', {}) + self.settings['certs'].update(certs) + + repositories.extend(channel_repositories) + return [repo.strip() for repo in repositories] + + def list_available_packages(self): + """ + Returns a master list of every available package from all sources + + :return: + A dict in the format: + { + 'Package Name': { + # Package details - see example-packages.json for format + }, + ... + } + """ + + repositories = self.list_repositories() + packages = {} + downloaders = [] + grouped_downloaders = {} + + # Repositories are run in reverse order so that the ones first + # on the list will overwrite those last on the list + for repo in repositories[::-1]: + repository_packages = None + + cache_key = repo + '.packages' + packages_cache = _channel_repository_cache.get(cache_key) + if packages_cache and packages_cache.get('time') > \ + time.time(): + repository_packages = packages_cache.get('data') + packages.update(repository_packages) + + if repository_packages == None: + downloader = RepositoryDownloader(self, + self.settings.get('package_name_map', {}), repo) + domain = re.sub('^https?://[^/]*?(\w+\.\w+)($|/.*$)', '\\1', + repo) + + # downloaders are grouped by domain so that multiple can + # be run in parallel without running into API access limits + if not grouped_downloaders.get(domain): + grouped_downloaders[domain] = [] + grouped_downloaders[domain].append(downloader) + + # Allows creating a separate named function for each downloader + # delay. Not having this contained in a function causes all of the + # schedules to reference the same downloader.start() + def schedule(downloader, delay): + downloader.has_started = False + + def inner(): + downloader.start() + downloader.has_started = True + sublime.set_timeout(inner, delay) + + # Grabs every repo grouped by domain and delays the start + # of each download from that domain by a fixed amount + for domain_downloaders in grouped_downloaders.values(): + for i in range(len(domain_downloaders)): + downloader = domain_downloaders[i] + downloaders.append(downloader) + schedule(downloader, i * 150) + + complete = [] + + # Wait for all of the downloaders to finish + while downloaders: + downloader = downloaders.pop() + if downloader.has_started: + downloader.join() + complete.append(downloader) + else: + downloaders.insert(0, downloader) + + # Grabs the results and stuff if all in the cache + for downloader in complete: + repository_packages = downloader.packages + if repository_packages == False: + continue + cache_key = downloader.repo + '.packages' + _channel_repository_cache[cache_key] = { + 'time': time.time() + self.settings.get('cache_length', 300), + 'data': repository_packages + } + packages.update(repository_packages) + + renamed_packages = downloader.renamed_packages + if renamed_packages == False: + continue + renamed_cache_key = downloader.repo + '.renamed_packages' + _channel_repository_cache[renamed_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', 300), + 'data': renamed_packages + } + if renamed_packages: + self.settings['renamed_packages'] = self.settings.get( + 'renamed_packages', {}) + self.settings['renamed_packages'].update(renamed_packages) + + unavailable_packages = downloader.unavailable_packages + unavailable_cache_key = downloader.repo + '.unavailable_packages' + _channel_repository_cache[unavailable_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', 300), + 'data': unavailable_packages + } + if unavailable_packages: + self.settings['unavailable_packages'] = self.settings.get( + 'unavailable_packages', []) + self.settings['unavailable_packages'].extend(unavailable_packages) + + return packages + + def list_packages(self): + """ :return: A list of all installed, non-default, package names""" + + package_names = os.listdir(sublime.packages_path()) + package_names = [path for path in package_names if + os.path.isdir(os.path.join(sublime.packages_path(), path))] + + # Ignore things to be deleted + ignored = [] + for package in package_names: + cleanup_file = os.path.join(sublime.packages_path(), package, + 'package-control.cleanup') + if os.path.exists(cleanup_file): + ignored.append(package) + + packages = list(set(package_names) - set(ignored) - + set(self.list_default_packages())) + packages = sorted(packages, key=lambda s: s.lower()) + + return packages + + def list_all_packages(self): + """ :return: A list of all installed package names, including default packages""" + + packages = os.listdir(sublime.packages_path()) + packages = sorted(packages, key=lambda s: s.lower()) + return packages + + def list_default_packages(self): + """ :return: A list of all default package names""" + + files = os.listdir(os.path.join(os.path.dirname( + sublime.packages_path()), 'Pristine Packages')) + files = list(set(files) - set(os.listdir( + sublime.installed_packages_path()))) + packages = [file.replace('.sublime-package', '') for file in files] + packages = sorted(packages, key=lambda s: s.lower()) + return packages + + def get_package_dir(self, package): + """:return: The full filesystem path to the package directory""" + + return os.path.join(sublime.packages_path(), package) + + def get_mapped_name(self, package): + """:return: The name of the package after passing through mapping rules""" + + return self.settings.get('package_name_map', {}).get(package, package) + + def create_package(self, package_name, package_destination, + binary_package=False): + """ + Creates a .sublime-package file from the running Packages directory + + :param package_name: + The package to create a .sublime-package file for + + :param package_destination: + The full filesystem path of the directory to save the new + .sublime-package file in. + + :param binary_package: + If the created package should follow the binary package include/ + exclude patterns from the settings. These normally include a setup + to exclude .py files and include .pyc files, but that can be + changed via settings. + + :return: bool if the package file was successfully created + """ + + package_dir = self.get_package_dir(package_name) + '/' + + if not os.path.exists(package_dir): + sublime.error_message(('%s: The folder for the package name ' + + 'specified, %s, does not exist in %s') % + (__name__, package_name, sublime.packages_path())) + return False + + package_filename = package_name + '.sublime-package' + package_path = os.path.join(package_destination, + package_filename) + + if not os.path.exists(sublime.installed_packages_path()): + os.mkdir(sublime.installed_packages_path()) + + if os.path.exists(package_path): + os.remove(package_path) + + try: + package_file = zipfile.ZipFile(package_path, "w", + compression=zipfile.ZIP_DEFLATED) + except (OSError, IOError) as (exception): + sublime.error_message(('%s: An error occurred creating the ' + + 'package file %s in %s. %s') % (__name__, package_filename, + package_destination, unicode_from_os(exception))) + return False + + dirs_to_ignore = self.settings.get('dirs_to_ignore', []) + if not binary_package: + files_to_ignore = self.settings.get('files_to_ignore', []) + files_to_include = self.settings.get('files_to_include', []) + else: + files_to_ignore = self.settings.get('files_to_ignore_binary', []) + files_to_include = self.settings.get('files_to_include_binary', []) + + package_dir_regex = re.compile('^' + re.escape(package_dir)) + for root, dirs, files in os.walk(package_dir): + [dirs.remove(dir) for dir in dirs if dir in dirs_to_ignore] + paths = dirs + paths.extend(files) + for path in paths: + full_path = os.path.join(root, path) + relative_path = re.sub(package_dir_regex, '', full_path) + + ignore_matches = [fnmatch(relative_path, p) for p in files_to_ignore] + include_matches = [fnmatch(relative_path, p) for p in files_to_include] + if any(ignore_matches) and not any(include_matches): + continue + + if os.path.isdir(full_path): + continue + package_file.write(full_path, relative_path) + + package_file.close() + + return True + + def install_package(self, package_name): + """ + Downloads and installs (or upgrades) a package + + Uses the self.list_available_packages() method to determine where to + retrieve the package file from. + + The install process consists of: + + 1. Finding the package + 2. Downloading the .sublime-package/.zip file + 3. Extracting the package file + 4. Showing install/upgrade messaging + 5. Submitting usage info + 6. Recording that the package is installed + + :param package_name: + The package to download and install + + :return: bool if the package was successfully installed + """ + + packages = self.list_available_packages() + + if package_name in self.settings.get('unavailable_packages', []): + print ('%s: The package "%s" is not available ' + + 'on this platform.') % (__name__, package_name) + return False + + if package_name not in packages.keys(): + sublime.error_message(('%s: The package specified, %s, is ' + + 'not available.') % (__name__, package_name)) + return False + + download = packages[package_name]['downloads'][0] + url = download['url'] + + package_filename = package_name + \ + '.sublime-package' + package_path = os.path.join(sublime.installed_packages_path(), + package_filename) + pristine_package_path = os.path.join(os.path.dirname( + sublime.packages_path()), 'Pristine Packages', package_filename) + + package_dir = self.get_package_dir(package_name) + + package_metadata_file = os.path.join(package_dir, + 'package-metadata.json') + + if os.path.exists(os.path.join(package_dir, '.git')): + if self.settings.get('ignore_vcs_packages'): + sublime.error_message(('%s: Skipping git package %s since ' + + 'the setting ignore_vcs_packages is set to true') % + (__name__, package_name)) + return False + return GitUpgrader(self.settings['git_binary'], + self.settings['git_update_command'], package_dir, + self.settings['cache_length'], self.settings['debug']).run() + elif os.path.exists(os.path.join(package_dir, '.hg')): + if self.settings.get('ignore_vcs_packages'): + sublime.error_message(('%s: Skipping hg package %s since ' + + 'the setting ignore_vcs_packages is set to true') % + (__name__, package_name)) + return False + return HgUpgrader(self.settings['hg_binary'], + self.settings['hg_update_command'], package_dir, + self.settings['cache_length'], self.settings['debug']).run() + + is_upgrade = os.path.exists(package_metadata_file) + old_version = None + if is_upgrade: + old_version = self.get_metadata(package_name).get('version') + + package_bytes = self.download_url(url, 'Error downloading package.') + if package_bytes == False: + return False + with open(package_path, "wb") as package_file: + package_file.write(package_bytes) + + if not os.path.exists(package_dir): + os.mkdir(package_dir) + + # We create a backup copy incase something was edited + else: + try: + backup_dir = os.path.join(os.path.dirname( + sublime.packages_path()), 'Backup', + datetime.datetime.now().strftime('%Y%m%d%H%M%S')) + if not os.path.exists(backup_dir): + os.makedirs(backup_dir) + package_backup_dir = os.path.join(backup_dir, package_name) + shutil.copytree(package_dir, package_backup_dir) + except (OSError, IOError) as (exception): + sublime.error_message(('%s: An error occurred while trying ' + + 'to backup the package directory for %s. %s') % + (__name__, package_name, unicode_from_os(exception))) + shutil.rmtree(package_backup_dir) + return False + + try: + package_zip = zipfile.ZipFile(package_path, 'r') + except (zipfile.BadZipfile): + sublime.error_message(('%s: An error occurred while ' + + 'trying to unzip the package file for %s. Please try ' + + 'installing the package again.') % (__name__, package_name)) + return False + + root_level_paths = [] + last_path = None + for path in package_zip.namelist(): + last_path = path + if path.find('/') in [len(path) - 1, -1]: + root_level_paths.append(path) + if path[0] == '/' or path.find('../') != -1 or path.find('..\\') != -1: + sublime.error_message(('%s: The package specified, %s, ' + + 'contains files outside of the package dir and cannot ' + + 'be safely installed.') % (__name__, package_name)) + return False + + if last_path and len(root_level_paths) == 0: + root_level_paths.append(last_path[0:last_path.find('/') + 1]) + + os.chdir(package_dir) + + overwrite_failed = False + + # Here we don’t use .extractall() since it was having issues on OS X + skip_root_dir = len(root_level_paths) == 1 and \ + root_level_paths[0].endswith('/') + extracted_paths = [] + for path in package_zip.namelist(): + dest = path + try: + if not isinstance(dest, unicode): + dest = unicode(dest, 'utf-8', 'strict') + except (UnicodeDecodeError): + dest = unicode(dest, 'cp1252', 'replace') + + if os.name == 'nt': + regex = ':|\*|\?|"|<|>|\|' + if re.search(regex, dest) != None: + print ('%s: Skipping file from package named %s due to ' + + 'an invalid filename') % (__name__, path) + continue + + # If there was only a single directory in the package, we remove + # that folder name from the paths as we extract entries + if skip_root_dir: + dest = dest[len(root_level_paths[0]):] + + if os.name == 'nt': + dest = dest.replace('/', '\\') + else: + dest = dest.replace('\\', '/') + + dest = os.path.join(package_dir, dest) + + def add_extracted_dirs(dir): + while dir not in extracted_paths: + extracted_paths.append(dir) + dir = os.path.dirname(dir) + if dir == package_dir: + break + + if path.endswith('/'): + if not os.path.exists(dest): + os.makedirs(dest) + add_extracted_dirs(dest) + else: + dest_dir = os.path.dirname(dest) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + add_extracted_dirs(dest_dir) + extracted_paths.append(dest) + try: + open(dest, 'wb').write(package_zip.read(path)) + except (IOError) as (e): + message = unicode_from_os(e) + if re.search('[Ee]rrno 13', message): + overwrite_failed = True + break + print ('%s: Skipping file from package named %s due to ' + + 'an invalid filename') % (__name__, path) + + except (UnicodeDecodeError): + print ('%s: Skipping file from package named %s due to ' + + 'an invalid filename') % (__name__, path) + package_zip.close() + + + # If upgrading failed, queue the package to upgrade upon next start + if overwrite_failed: + reinstall_file = os.path.join(package_dir, 'package-control.reinstall') + open(reinstall_file, 'w').close() + + # 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 + clear_directory(package_dir, [reinstall_file, package_metadata_file]) + + sublime.error_message(('%s: An error occurred while trying to ' + + 'upgrade %s. Please restart Sublime Text to finish the ' + + 'upgrade.') % (__name__, package_name)) + return False + + + # Here we clean out any files that were not just overwritten. It is ok + # if there is an error removing a file. The next time there is an + # upgrade, it should be cleaned out successfully then. + clear_directory(package_dir, extracted_paths) + + + self.print_messages(package_name, package_dir, is_upgrade, old_version) + + with open(package_metadata_file, 'w') as f: + metadata = { + "version": packages[package_name]['downloads'][0]['version'], + "url": packages[package_name]['url'], + "description": packages[package_name]['description'] + } + json.dump(metadata, f) + + # Submit install and upgrade info + if is_upgrade: + params = { + 'package': package_name, + 'operation': 'upgrade', + 'version': packages[package_name]['downloads'][0]['version'], + 'old_version': old_version + } + else: + params = { + 'package': package_name, + 'operation': 'install', + 'version': packages[package_name]['downloads'][0]['version'] + } + self.record_usage(params) + + # Record the install in the settings file so that you can move + # settings across computers and have the same packages installed + def save_package(): + settings = sublime.load_settings(__name__ + '.sublime-settings') + installed_packages = settings.get('installed_packages', []) + if not installed_packages: + installed_packages = [] + installed_packages.append(package_name) + installed_packages = list(set(installed_packages)) + installed_packages = sorted(installed_packages, + key=lambda s: s.lower()) + settings.set('installed_packages', installed_packages) + sublime.save_settings(__name__ + '.sublime-settings') + sublime.set_timeout(save_package, 1) + + # Here we delete the package file from the installed packages directory + # since we don't want to accidentally overwrite user changes + os.remove(package_path) + # We have to remove the pristine package too or else Sublime Text 2 + # will silently delete the package + if os.path.exists(pristine_package_path): + os.remove(pristine_package_path) + + os.chdir(sublime.packages_path()) + return True + + def print_messages(self, package, package_dir, is_upgrade, old_version): + """ + Prints out package install and upgrade messages + + The functionality provided by this allows package maintainers to + show messages to the user when a package is installed, or when + certain version upgrade occur. + + :param package: + The name of the package the message is for + + :param package_dir: + The full filesystem path to the package directory + + :param is_upgrade: + If the install was actually an upgrade + + :param old_version: + The string version of the package before the upgrade occurred + """ + + messages_file = os.path.join(package_dir, 'messages.json') + if not os.path.exists(messages_file): + return + + messages_fp = open(messages_file, 'r') + try: + message_info = json.load(messages_fp) + except (ValueError): + print '%s: Error parsing messages.json for %s' % (__name__, package) + return + messages_fp.close() + + output = '' + if not is_upgrade and message_info.get('install'): + install_messages = os.path.join(package_dir, + message_info.get('install')) + message = '\n\n%s:\n%s\n\n ' % (package, + ('-' * len(package))) + with open(install_messages, 'r') as f: + message += unicode(f.read(), 'utf-8', errors='replace').replace('\n', '\n ') + output += message + '\n' + + elif is_upgrade and old_version: + upgrade_messages = list(set(message_info.keys()) - + set(['install'])) + upgrade_messages = sorted(upgrade_messages, + cmp=self.compare_versions, reverse=True) + for version in upgrade_messages: + if self.compare_versions(old_version, version) >= 0: + break + if not output: + message = '\n\n%s:\n%s\n' % (package, + ('-' * len(package))) + output += message + upgrade_messages = os.path.join(package_dir, + message_info.get(version)) + message = '\n ' + with open(upgrade_messages, 'r') as f: + message += unicode(f.read(), 'utf-8', errors='replace').replace('\n', '\n ') + output += message + '\n' + + if not output: + return + + def print_to_panel(): + window = sublime.active_window() + + views = window.views() + view = None + for _view in views: + if _view.name() == 'Package Control Messages': + view = _view + break + + if not view: + view = window.new_file() + view.set_name('Package Control Messages') + view.set_scratch(True) + + def write(string): + edit = view.begin_edit() + view.insert(edit, view.size(), string) + view.end_edit(edit) + + if not view.size(): + view.settings().set("word_wrap", True) + write('Package Control Messages\n' + + '========================') + + write(output) + sublime.set_timeout(print_to_panel, 1) + + def remove_package(self, package_name): + """ + Deletes a package + + The deletion process consists of: + + 1. Deleting the directory (or marking it for deletion if deletion fails) + 2. Submitting usage info + 3. Removing the package from the list of installed packages + + :param package_name: + The package to delete + + :return: bool if the package was successfully deleted + """ + + installed_packages = self.list_packages() + + if package_name not in installed_packages: + sublime.error_message(('%s: The package specified, %s, is not ' + + 'installed.') % (__name__, package_name)) + return False + + os.chdir(sublime.packages_path()) + + # Give Sublime Text some time to ignore the package + time.sleep(1) + + package_filename = package_name + '.sublime-package' + package_path = os.path.join(sublime.installed_packages_path(), + package_filename) + installed_package_path = os.path.join(os.path.dirname( + sublime.packages_path()), 'Installed Packages', package_filename) + pristine_package_path = os.path.join(os.path.dirname( + sublime.packages_path()), 'Pristine Packages', package_filename) + package_dir = self.get_package_dir(package_name) + + version = self.get_metadata(package_name).get('version') + + try: + if os.path.exists(package_path): + os.remove(package_path) + except (OSError, IOError) as (exception): + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the package file for %s. %s') % (__name__, + package_name, unicode_from_os(exception))) + return False + + try: + if os.path.exists(installed_package_path): + os.remove(installed_package_path) + except (OSError, IOError) as (exception): + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the installed package file for %s. %s') % (__name__, + package_name, unicode_from_os(exception))) + return False + + try: + if os.path.exists(pristine_package_path): + os.remove(pristine_package_path) + except (OSError, IOError) as (exception): + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the pristine package file for %s. %s') % (__name__, + package_name, unicode_from_os(exception))) + return False + + # We don't delete the actual package dir immediately due to a bug + # in sublime_plugin.py + can_delete_dir = True + if not clear_directory(package_dir): + # If there is an error deleting now, we will mark it for + # cleanup the next time Sublime Text starts + open(os.path.join(package_dir, 'package-control.cleanup'), + 'w').close() + can_delete_dir = False + + params = { + 'package': package_name, + 'operation': 'remove', + 'version': version + } + self.record_usage(params) + + # Remove the package from the installed packages list + def clear_package(): + settings = sublime.load_settings('%s.sublime-settings' % __name__) + installed_packages = settings.get('installed_packages', []) + if not installed_packages: + installed_packages = [] + installed_packages.remove(package_name) + settings.set('installed_packages', installed_packages) + sublime.save_settings('%s.sublime-settings' % __name__) + sublime.set_timeout(clear_package, 1) + + if can_delete_dir: + os.rmdir(package_dir) + + return True + + def record_usage(self, params): + """ + Submits install, upgrade and delete actions to a usage server + + The usage information is currently displayed on the Package Control + community package list at http://wbond.net/sublime_packages/community + + :param params: + A dict of the information to submit + """ + + if not self.settings.get('submit_usage'): + return + params['package_control_version'] = \ + self.get_metadata('Package Control').get('version') + params['sublime_platform'] = self.settings.get('platform') + params['sublime_version'] = self.settings.get('version') + url = self.settings.get('submit_url') + '?' + urllib.urlencode(params) + + result = self.download_url(url, 'Error submitting usage information.') + if result == False: + return + + try: + result = json.loads(result) + if result['result'] != 'success': + raise ValueError() + except (ValueError): + print '%s: Error submitting usage information for %s' % (__name__, + params['package']) + + +class PackageCreator(): + """ + Abstract class for commands that create .sublime-package files + """ + + def show_panel(self): + """ + Shows a list of packages that can be turned into a .sublime-package file + """ + + self.manager = PackageManager() + self.packages = self.manager.list_packages() + if not self.packages: + sublime.error_message(('%s: There are no packages available to ' + + 'be packaged.') % (__name__)) + return + self.window.show_quick_panel(self.packages, self.on_done) + + def get_package_destination(self): + """ + Retrieves the destination for .sublime-package files + + :return: + A string - the path to the folder to save .sublime-package files in + """ + + destination = self.manager.settings.get('package_destination') + + # We check destination via an if statement instead of using + # the dict.get() method since the key may be set, but to a blank value + if not destination: + destination = os.path.join(os.path.expanduser('~'), 'Desktop') + + return destination + + +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'}) + + +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'}) + + +class PackageRenamer(): + """ + Class to handle renaming packages via the renamed_packages setting + gathered from channels and repositories. + """ + + def load_settings(self): + """ + Loads the list of installed packages from the + Package Control.sublime-settings file. + """ + + self.settings_file = '%s.sublime-settings' % __name__ + self.settings = sublime.load_settings(self.settings_file) + self.installed_packages = self.settings.get('installed_packages', []) + if not isinstance(self.installed_packages, list): + self.installed_packages = [] + + def rename_packages(self, installer): + """ + Renames any installed packages that the user has installed. + + :param installer: + An instance of :class:`PackageInstaller` + """ + + # Fetch the packages since that will pull in the renamed packages list + installer.manager.list_available_packages() + renamed_packages = installer.manager.settings.get('renamed_packages', {}) + if not renamed_packages: + renamed_packages = {} + + # These are packages that have been tracked as installed + installed_pkgs = self.installed_packages + # There are the packages actually present on the filesystem + present_packages = installer.manager.list_packages() + + # Rename directories for packages that have changed names + for package_name in renamed_packages: + package_dir = os.path.join(sublime.packages_path(), package_name) + metadata_path = os.path.join(package_dir, 'package-metadata.json') + if not os.path.exists(metadata_path): + continue + + new_package_name = renamed_packages[package_name] + new_package_dir = os.path.join(sublime.packages_path(), + new_package_name) + + changing_case = package_name.lower() == new_package_name.lower() + case_insensitive_fs = sublime.platform() in ['windows', 'osx'] + + # Since Windows and OSX use case-insensitive filesystems, we have to + # scan through the list of installed packages if the rename of the + # package is just changing the case of it. If we don't find the old + # name for it, we continue the loop since os.path.exists() will return + # true due to the case-insensitive nature of the filesystems. + if case_insensitive_fs and changing_case: + has_old = False + for present_package_name in present_packages: + if present_package_name == package_name: + has_old = True + break + if not has_old: + continue + + if not os.path.exists(new_package_dir) or (case_insensitive_fs and changing_case): + + # Windows will not allow you to rename to the same name with + # a different case, so we work around that with a temporary name + if os.name == 'nt' and changing_case: + temp_package_name = '__' + new_package_name + temp_package_dir = os.path.join(sublime.packages_path(), + temp_package_name) + os.rename(package_dir, temp_package_dir) + package_dir = temp_package_dir + + os.rename(package_dir, new_package_dir) + installed_pkgs.append(new_package_name) + + print '%s: Renamed %s to %s' % (__name__, package_name, + new_package_name) + + else: + installer.manager.remove_package(package_name) + print ('%s: Removed %s since package with new name (%s) ' + + 'already exists') % (__name__, package_name, + new_package_name) + + try: + installed_pkgs.remove(package_name) + except (ValueError): + pass + + sublime.set_timeout(lambda: self.save_packages(installed_pkgs), 10) + + def save_packages(self, installed_packages): + """ + Saves the list of installed packages (after having been appropriately + renamed) + + :param installed_packages: + The new list of installed packages + """ + + installed_packages = list(set(installed_packages)) + installed_packages = sorted(installed_packages, + key=lambda s: s.lower()) + + if installed_packages != self.installed_packages: + self.settings.set('installed_packages', installed_packages) + sublime.save_settings(self.settings_file) + + +class PackageInstaller(): + """ + Provides helper functionality related to installing packages + """ + + def __init__(self): + self.manager = PackageManager() + + def make_package_list(self, ignore_actions=[], override_action=None, + ignore_packages=[]): + """ + Creates a list of packages and what operation would be performed for + each. Allows filtering by the applicable action or package name. + Returns the information in a format suitable for displaying in the + quick panel. + + :param ignore_actions: + A list of actions to ignore packages by. Valid actions include: + `install`, `upgrade`, `downgrade`, `reinstall`, `overwrite`, + `pull` and `none`. `pull` andd `none` are for Git and Hg + repositories. `pull` is present when incoming changes are detected, + where as `none` is selected if no commits are available. `overwrite` + is for packages that do not include version information via the + `package-metadata.json` file. + + :param override_action: + A string action name to override the displayed action for all listed + packages. + + :param ignore_packages: + A list of packages names that should not be returned in the list + + :return: + A list of lists, each containing three strings: + 0 - package name + 1 - package description + 2 - action; [extra info;] package url + """ + + packages = self.manager.list_available_packages() + installed_packages = self.manager.list_packages() + + package_list = [] + for package in sorted(packages.iterkeys(), key=lambda s: s.lower()): + if ignore_packages and package in ignore_packages: + continue + package_entry = [package] + info = packages[package] + download = info['downloads'][0] + + if package in installed_packages: + installed = True + metadata = self.manager.get_metadata(package) + if metadata.get('version'): + installed_version = metadata['version'] + else: + installed_version = None + else: + installed = False + + installed_version_name = 'v' + installed_version if \ + installed and installed_version else 'unknown version' + new_version = 'v' + download['version'] + + vcs = None + package_dir = self.manager.get_package_dir(package) + settings = self.manager.settings + + if override_action: + action = override_action + extra = '' + + else: + if os.path.exists(os.path.join(sublime.packages_path(), + package, '.git')): + if settings.get('ignore_vcs_packages'): + continue + vcs = 'git' + incoming = GitUpgrader(settings.get('git_binary'), + settings.get('git_update_command'), package_dir, + settings.get('cache_length'), settings.get('debug') + ).incoming() + elif os.path.exists(os.path.join(sublime.packages_path(), + package, '.hg')): + if settings.get('ignore_vcs_packages'): + continue + vcs = 'hg' + incoming = HgUpgrader(settings.get('hg_binary'), + settings.get('hg_update_command'), package_dir, + settings.get('cache_length'), settings.get('debug') + ).incoming() + + if installed: + if not installed_version: + if vcs: + if incoming: + action = 'pull' + extra = ' with ' + vcs + else: + action = 'none' + extra = '' + else: + action = 'overwrite' + extra = ' %s with %s' % (installed_version_name, + new_version) + else: + res = self.manager.compare_versions( + installed_version, download['version']) + if res < 0: + action = 'upgrade' + extra = ' to %s from %s' % (new_version, + installed_version_name) + elif res > 0: + action = 'downgrade' + extra = ' to %s from %s' % (new_version, + installed_version_name) + else: + action = 'reinstall' + extra = ' %s' % new_version + else: + action = 'install' + extra = ' %s' % new_version + extra += ';' + + if action in ignore_actions: + continue + + description = info.get('description') + if not description: + description = 'No description provided' + package_entry.append(description) + package_entry.append(action + extra + ' ' + + re.sub('^https?://', '', info['url'])) + package_list.append(package_entry) + return package_list + + def disable_package(self, package): + """ + Disables a package before installing or upgrading to prevent errors + where Sublime Text tries to read files that no longer exist, or read a + half-written file. + + :param package: The string package name + """ + + # Don't disable Package Control so it does not get stuck disabled + if package == 'Package Control': + return False + + settings = sublime.load_settings(preferences_filename()) + ignored = settings.get('ignored_packages') + if not ignored: + ignored = [] + if not package in ignored: + ignored.append(package) + settings.set('ignored_packages', ignored) + sublime.save_settings(preferences_filename()) + return True + return False + + def reenable_package(self, package): + """ + Re-enables a package after it has been installed or upgraded + + :param package: The string package name + """ + + settings = sublime.load_settings(preferences_filename()) + ignored = settings.get('ignored_packages') + if not ignored: + return + if package in ignored: + settings.set('ignored_packages', + list(set(ignored) - set([package]))) + sublime.save_settings(preferences_filename()) + + def on_done(self, picked): + """ + Quick panel user selection handler - disables a package, installs or + 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 self.disable_package(name): + on_complete = lambda: self.reenable_package(name) + else: + on_complete = None + + thread = PackageInstallerThread(self.manager, name, on_complete) + thread.start() + ThreadProgress(thread, 'Installing package %s' % name, + 'Package %s successfully %s' % (name, self.completion_type)) + + +class PackageInstallerThread(threading.Thread): + """ + A thread to run package install/upgrade operations in so that the main + Sublime Text thread does not get blocked and freeze the UI + """ + + def __init__(self, manager, package, on_complete): + """ + :param manager: + An instance of :class:`PackageManager` + + :param package: + The string package name to install/upgrade + + :param on_complete: + A callback to run after installing/upgrading the package + """ + + self.package = package + self.manager = manager + self.on_complete = on_complete + threading.Thread.__init__(self) + + def run(self): + try: + self.result = self.manager.install_package(self.package) + finally: + if self.on_complete: + sublime.set_timeout(self.on_complete, 1) + + +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: + sublime.error_message(('%s: There are no packages ' + + 'available for installation.') % __name__) + return + self.window.show_quick_panel(self.package_list, self.on_done) + sublime.set_timeout(show_quick_panel, 10) + + +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'}) + + +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: + sublime.error_message(('%s: There are no packages ' + + 'ready for upgrade.') % __name__) + 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 self.disable_package(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)) + + +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 disabled_packages.get(info[0]): + 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(): + for info in package_list: + disabled_packages[info[0]] = self.disable_package(info[0]) + threading.Thread(target=do_upgrades).start() + + sublime.set_timeout(disable_packages, 1) + + +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 + + +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: + sublime.error_message(('%s: There are no packages ' + + 'to list.') % __name__) + 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) + + +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: + sublime.error_message(('%s: There are no packages ' + + 'that can be removed.') % __name__) + 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] + + # Don't disable Package Control so it does not get stuck disabled + if package != 'Package Control': + settings = sublime.load_settings(preferences_filename()) + ignored = settings.get('ignored_packages') + if not ignored: + ignored = [] + 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) + + +class AddRepositoryChannelCommand(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 + """ + + settings = sublime.load_settings('%s.sublime-settings' % __name__) + repository_channels = settings.get('repository_channels', []) + if not repository_channels: + repository_channels = [] + repository_channels.append(input) + settings.set('repository_channels', repository_channels) + sublime.save_settings('%s.sublime-settings' % __name__) + sublime.status_message(('Channel %s successfully ' + + 'added') % input) + + def on_change(self, input): + pass + + def on_cancel(self): + pass + + +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 + """ + + settings = sublime.load_settings('%s.sublime-settings' % __name__) + repositories = settings.get('repositories', []) + if not repositories: + repositories = [] + repositories.append(input) + settings.set('repositories', repositories) + sublime.save_settings('%s.sublime-settings' % __name__) + sublime.status_message('Repository %s successfully added' % input) + + def on_change(self, input): + pass + + def on_cancel(self): + pass + + +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: + sublime.error_message(('%s: There are no enabled packages' + + 'to disable.') % __name__) + 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) + + +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: + sublime.error_message(('%s: There are no disabled packages ' + + 'to enable.') % __name__) + 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) + + +class AutomaticUpgrader(threading.Thread): + """ + Automatically checks for updated packages and installs them. controlled + by the `auto_upgrade`, `auto_upgrade_ignore`, `auto_upgrade_frequency` and + `auto_upgrade_last_run` 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.next_run = int(time.time()) + self.last_run = None + last_run_file = os.path.join(sublime.packages_path(), 'User', + 'Package Control.last-run') + + if os.path.isfile(last_run_file): + with open(last_run_file) as fobj: + try: + self.last_run = int(fobj.read()) + except ValueError: + pass + + 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() + + # 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(): + with open(last_run_file, 'w') as fobj: + fobj.write(str(int(time.time()))) + + threading.Thread.__init__(self) + + def load_settings(self): + """ + Loads the list of installed packages from the + Package Control.sublime-settings file + """ + + self.settings_file = '%s.sublime-settings' % __name__ + 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 + + print '%s: Installing %s missing packages' % \ + (__name__, len(self.missing_packages)) + for package in self.missing_packages: + if self.installer.manager.install_package(package): + print '%s: Installed missing package %s' % \ + (__name__, package) + + 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' + print ('%s: Skipping automatic upgrade, last run at ' + + '%s, next run at %s or after') % (__name__, + last_run.strftime(date_format), next_run.strftime(date_format)) + + 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) + + packages = 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 packages: + if package[0] != __name__: + continue + + def reset_last_run(): + settings = sublime.load_settings(self.settings_file) + settings.set('auto_upgrade_last_run', None) + sublime.save_settings(self.settings_file) + sublime.set_timeout(reset_last_run, 1) + packages = [package] + break + + if not packages: + print '%s: No updated packages' % __name__ + return + + print '%s: Installing %s upgrades' % (__name__, len(packages)) + for package in packages: + self.installer.manager.install_package(package[0]) + version = re.sub('^.*?(v[\d\.]+).*?$', '\\1', package[2]) + if version == package[2] and version.find('pull with') != -1: + vcs = re.sub('^pull with (\w+).*?$', '\\1', version) + version = 'latest %s commit' % vcs + print '%s: Upgraded %s to %s' % (__name__, package[0], version) + + +class PackageCleanup(threading.Thread, PackageRenamer): + """ + Cleans up folders for packages that were removed, but that still have files + in use. + """ + + def __init__(self): + self.manager = PackageManager() + self.load_settings() + threading.Thread.__init__(self) + + def run(self): + found_pkgs = [] + installed_pkgs = self.installed_packages + for package_name in os.listdir(sublime.packages_path()): + package_dir = os.path.join(sublime.packages_path(), package_name) + metadata_path = os.path.join(package_dir, 'package-metadata.json') + + # Cleanup packages that could not be removed due to in-use files + cleanup_file = os.path.join(package_dir, 'package-control.cleanup') + if os.path.exists(cleanup_file): + try: + shutil.rmtree(package_dir) + print '%s: Removed old directory for package %s' % \ + (__name__, package_name) + except (OSError) as (e): + if not os.path.exists(cleanup_file): + open(cleanup_file, 'w').close() + print ('%s: Unable to remove old directory for package ' + + '%s - deferring until next start: %s') % (__name__, + package_name, unicode_from_os(e)) + + # Finish reinstalling packages that could not be upgraded due to + # in-use files + reinstall = os.path.join(package_dir, 'package-control.reinstall') + if os.path.exists(reinstall): + if not clear_directory(package_dir, [metadata_path]): + if not os.path.exists(reinstall): + open(reinstall, 'w').close() + # Assigning this here prevents the callback from referencing the value + # of the "package_name" variable when it is executed + restart_message = ('%s: An error occurred while trying to ' + + 'finish the upgrade of %s. You will most likely need to ' + + 'restart your computer to complete the upgrade.') % ( + __name__, package_name) + def show_still_locked(): + sublime.error_message(restart_message) + sublime.set_timeout(show_still_locked, 10) + else: + self.manager.install_package(package_name) + + # This adds previously installed packages from old versions of PC + if os.path.exists(metadata_path) and \ + package_name not in self.installed_packages: + installed_pkgs.append(package_name) + params = { + 'package': package_name, + 'operation': 'install', + 'version': \ + self.manager.get_metadata(package_name).get('version') + } + self.manager.record_usage(params) + + found_pkgs.append(package_name) + + sublime.set_timeout(lambda: self.finish(installed_pkgs, found_pkgs), 10) + + def finish(self, installed_pkgs, found_pkgs): + """ + A callback that can be run the main UI thread to perform saving of the + Package Control.sublime-settings file. Also fires off the + :class:`AutomaticUpgrader`. + + :param installed_pkgs: + A list of the string package names of all "installed" packages, + even ones that do not appear to be in the filesystem. + + :param found_pkgs: + A list of the string package names of all packages that are + currently installed on the filesystem. + """ + + self.save_packages(installed_pkgs) + AutomaticUpgrader(found_pkgs).start() + + +# Start shortly after Sublime starts so package renames don't cause errors +# with keybindings, settings, etc disappearing in the middle of parsing +sublime.set_timeout(lambda: PackageCleanup().start(), 2000) diff --git a/sublime/Packages/Package Control/Package Control.sublime-settings b/sublime/Packages/Package Control/Package Control.sublime-settings new file mode 100644 index 0000000..7008abe --- /dev/null +++ b/sublime/Packages/Package Control/Package Control.sublime-settings @@ -0,0 +1,138 @@ +{ + // 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" + ], + + // A list of URLs that contain a packages JSON file. These repositories + // are placed in order before repositories from the "repository_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. + // + // 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: + // + // "*": ["my_identifier", "https://example.com/url/of/cert_file"] + // "*": ["my_identifier_2", "/absolute/filesystem/path/to/cert_file"] + // + // 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. + // + // 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", ""] + }, + + // If debugging information for HTTP/HTTPS connections should be printed + // to the Sublime Text console + "debug": false, + + // This helps solve naming issues where a repository it not named the + // same as the package should be. This is primarily only useful for + // GitHub and BitBucket repositories. This mapping will override the + // mapping that is retrieved from the repository channels. + "package_name_map": {}, + + // If package install, upgrade and removal info should be submitted to + // the channel for aggregated statistics + "submit_usage": true, + + // 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 + "auto_upgrade": true, + + // If missing packages should be automatically installed when ST2 starts + "install_missing": true, + + // The minimum frequency in hours in which to check for automatic upgrades, + // setting this to 0 will always check for automatic upgrades + "auto_upgrade_frequency": 1, + + // Packages to not auto upgrade + "auto_upgrade_ignore": [], + + // Timeout for downloading channels, repositories and packages + "timeout": 30, + + // The number of seconds to cache repository and package info for + "cache_length": 300, + + // An HTTP proxy server to use for requests + "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. + "https_proxy": "", + + // Username and password for both http_proxy and https_proxy + "proxy_username": "", + "proxy_password": "", + + // User agent for HTTP requests + "user_agent": "Sublime Package Control", + + // 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 + // hangs + "ignore_vcs_packages": false, + + // 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"], + + "hg_binary": "", + + // Be sure to keep the remote name as the last argument + "hg_update_command": ["pull", "--update", "default"], + + // Directories to ignore when creating a package + "dirs_to_ignore": [ + ".hg", ".git", ".svn", "_darcs", "CVS" + ], + + // Files to ignore when creating a package + "files_to_ignore": [ + ".hgignore", ".gitignore", ".bzrignore", "*.pyc", "*.sublime-project", + "*.sublime-workspace", "*.tmTheme.cache" + ], + + // Files to include, even if they match a pattern in files_to_ignore + "files_to_include": [], + + // Files to ignore when creating a binary package. By default binary + // packages ship with .pyc files instead of .py files. If an __init__.py + // file exists, it will always be included, even if it matches one of + // these patterns. + "files_to_ignore_binary": [ + ".hgignore", ".gitignore", ".bzrignore", "*.py", "*.sublime-project", + "*.sublime-workspace", "*.tmTheme.cache" + ], + + // Files to include for a binary package, even if they match a pattern i + // files_to_ignore_binary + "files_to_include_binary": [ + "__init__.py" + ], + + // When a package is created, copy it to this folder - defaults to Desktop + "package_destination": "" +} \ No newline at end of file diff --git a/sublime/Packages/Package Control/certs/1c5282418e2cb4989cd6beddcdbab0b5 b/sublime/Packages/Package Control/certs/1c5282418e2cb4989cd6beddcdbab0b5 new file mode 100644 index 0000000..432b087 --- /dev/null +++ b/sublime/Packages/Package Control/certs/1c5282418e2cb4989cd6beddcdbab0b5 @@ -0,0 +1,113 @@ +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----- \ No newline at end of file diff --git a/sublime/Packages/Package Control/certs/7f4f8622b4fd001c7f648e09aae7edaa b/sublime/Packages/Package Control/certs/7f4f8622b4fd001c7f648e09aae7edaa new file mode 100644 index 0000000..cb680c1 --- /dev/null +++ b/sublime/Packages/Package Control/certs/7f4f8622b4fd001c7f648e09aae7edaa @@ -0,0 +1,165 @@ +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----- \ No newline at end of file diff --git a/sublime/Packages/Package Control/certs/897abe0b41fd2f64e9e2e351cbc36d76 b/sublime/Packages/Package Control/certs/897abe0b41fd2f64e9e2e351cbc36d76 new file mode 100644 index 0000000..591907f --- /dev/null +++ b/sublime/Packages/Package Control/certs/897abe0b41fd2f64e9e2e351cbc36d76 @@ -0,0 +1,285 @@ +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----- \ No newline at end of file diff --git a/sublime/Packages/Package Control/certs/ca-bundle.crt b/sublime/Packages/Package Control/certs/ca-bundle.crt new file mode 100644 index 0000000..1681842 --- /dev/null +++ b/sublime/Packages/Package Control/certs/ca-bundle.crt @@ -0,0 +1,563 @@ +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----- \ No newline at end of file diff --git a/sublime/Packages/Package Control/certs/d867a7b2aecc46f9c31afc4f2f50de05 b/sublime/Packages/Package Control/certs/d867a7b2aecc46f9c31afc4f2f50de05 new file mode 100644 index 0000000..4ebe436 --- /dev/null +++ b/sublime/Packages/Package Control/certs/d867a7b2aecc46f9c31afc4f2f50de05 @@ -0,0 +1,197 @@ +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----- \ No newline at end of file diff --git a/sublime/Packages/Package Control/example-messages.json b/sublime/Packages/Package Control/example-messages.json new file mode 100644 index 0000000..09c7626 --- /dev/null +++ b/sublime/Packages/Package Control/example-messages.json @@ -0,0 +1,5 @@ +{ + "install": "messages/install.txt", + "1.1.1": "messages/1.1.1.txt", + "1.2.0": "messages/1.2.0.txt" +} \ No newline at end of file diff --git a/sublime/Packages/Package Control/example-packages.json b/sublime/Packages/Package Control/example-packages.json new file mode 100644 index 0000000..96945cc --- /dev/null +++ b/sublime/Packages/Package Control/example-packages.json @@ -0,0 +1,54 @@ +{ + "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" + } +} \ No newline at end of file diff --git a/sublime/Packages/Package Control/example-repositories.json b/sublime/Packages/Package Control/example-repositories.json new file mode 100644 index 0000000..9e03b1e --- /dev/null +++ b/sublime/Packages/Package Control/example-repositories.json @@ -0,0 +1,60 @@ +{ + "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" + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/sublime/Packages/Package Control/lib/all/semver.py b/sublime/Packages/Package Control/lib/all/semver.py new file mode 100644 index 0000000..73d4ea2 --- /dev/null +++ b/sublime/Packages/Package Control/lib/all/semver.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# This code is copyright Konstantine Rybnikov , and is +# available at https://github.com/k-bx/python-semver and is licensed under the +# BSD License + +import re + +_REGEX = re.compile('^(?P[0-9]+)' + '\.(?P[0-9]+)' + '\.(?P[0-9]+)' + '(\-(?P[0-9A-Za-z]+(\.[0-9A-Za-z]+)*))?' + '(\+(?P[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 , " + "where 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 \ No newline at end of file diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/U32.py b/sublime/Packages/Package Control/lib/windows/ntlm/U32.py new file mode 100644 index 0000000..a22b61f --- /dev/null +++ b/sublime/Packages/Package Control/lib/windows/ntlm/U32.py @@ -0,0 +1,113 @@ +# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ +# Copyright 2001 Dmitry A. Rozmanov +# +# 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 or . + + +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) \ No newline at end of file diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/__init__.py b/sublime/Packages/Package Control/lib/windows/ntlm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/des.py b/sublime/Packages/Package Control/lib/windows/ntlm/des.py new file mode 100644 index 0000000..19d7a48 --- /dev/null +++ b/sublime/Packages/Package Control/lib/windows/ntlm/des.py @@ -0,0 +1,92 @@ +# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ +# Copyright 2001 Dmitry A. Rozmanov +# +# 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 or . + +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 diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/des_c.py b/sublime/Packages/Package Control/lib/windows/ntlm/des_c.py new file mode 100644 index 0000000..f5c2f77 --- /dev/null +++ b/sublime/Packages/Package Control/lib/windows/ntlm/des_c.py @@ -0,0 +1,328 @@ +# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ +# Copyright 2001 Dmitry A. Rozmanov +# +# 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 or . + +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 diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/des_data.py b/sublime/Packages/Package Control/lib/windows/ntlm/des_data.py new file mode 100644 index 0000000..8cc854d --- /dev/null +++ b/sublime/Packages/Package Control/lib/windows/ntlm/des_data.py @@ -0,0 +1,348 @@ +# This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ +# Copyright 2001 Dmitry A. Rozmanov +# +# 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 or . + +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), +] + +] \ No newline at end of file diff --git a/sublime/Packages/Package Control/lib/windows/ntlm/ntlm.py b/sublime/Packages/Package Control/lib/windows/ntlm/ntlm.py new file mode 100644 index 0000000..9cc2a29 --- /dev/null +++ b/sublime/Packages/Package Control/lib/windows/ntlm/ntlm.py @@ -0,0 +1,466 @@ +# 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 or . + +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(' 40: + TargetInfoLen = struct.unpack(" Package Settings > Package Control > Settings - User and + set the key "submit_usage" to false. + + - Added local tracking of installed packages in + User/Package Control.sublime-settings via the "installed_packages" key. + This allows distributing a settings file that will automatically install + packages. + + - repositories.json schema version was increased to 1.1 and the + "last_modified" key was added. \ No newline at end of file diff --git a/sublime/Packages/Package Control/messages/1.6.0.txt b/sublime/Packages/Package Control/messages/1.6.0.txt new file mode 100644 index 0000000..0a055a0 --- /dev/null +++ b/sublime/Packages/Package Control/messages/1.6.0.txt @@ -0,0 +1,95 @@ +Package Control 1.6.0 Changelog: + +Wow! It has been 9 months since the last stable release of Package Control. +Quite a lot has happened since then, including the release of Sublime Text 2 +stable, and hundreds upon hundreds of new packages from the community! + +A quick thank you to Kevin Yank (@sentience) for recently volunteering to help +review packages for inclusion in the default channel, and ninj0x +(https://github.com/ninj0x) for rewriting the Package Control Community +Packages search functionality so it is nice and fast once again! The lists +below include specific thanks for code contributions. + +As Sublime Text has become increasingly more popular, and the number of +packages has increased so rapidly, the bandwidth requirements have also +significantly increased. This month the default channel will very likely serve +over 1TB of JSON data. If you feel so inclined, consider pitching in a small +amount to help cover the cost: +http://wbond.net/sublime_packages/package_control/say_thanks. A big thank you +to all of the users who have already contributed! + + +Enhancements + + + - Added full (custom) proxy authentication support for HTTPS connections + + - Added NTLM authentication for proxies on Windows + + - Proxy authentication information is now set via the new proxy_username and + proxy_password settings. + + - If the https_proxy setting it set to false, it will not inherit from the + http_proxy setting (thanks planardothum!) + + - The time of the last successful run is no longer stored in + Packages/User/Package Control.sublime-settings, but rather in + Packages/User/Package Control.last-run making it easier to ignore via git, + hg, etc. (thanks schlamar!) + + - Packages are now ignored during install and upgrade to help prevents errors + where Sublime Text tries to read a file as it is being extracted + + - Packages that include DLLs for Windows can now be upgraded. In-use + DLLs will be detected and the user prompted to restart. + + - Package version numbers may now include non-numeric components, and semantic + versioning (http://semver.org) is fully supported + + - JSON parsing messages are now printed to the console instead of being shown + in an error popup + + - Added support for changes to the BitBucket API + + - Added support for changes to GitHub URLs + + - Added the debug setting to help track down HTTP connection issues + + - All of the downloaders will now try to use HTTP compression + + - All of the downloaders will now follow redirects + + - Added new install_missing setting to control if Package Control should try + to install any packages that appear to be missing from the current machine. + This defaults to true, and is really only useful if you want to prevent + Package Control from connecting to the internet without explicitly asking + it to. + + - Added lots of code comments as a first step towards making contributions + by other developers easier + + +Bug Fixes + + + - Added support for the new preferences filename (thanks titoBouzout!) + + - If a package is missing from a machine, but not available for that + platform, it is no longer considered an error (thanks schlamar!) + + - Updated CA certs + + - Fixed handling of install and upgrade messages that contain non-ASCII + characters + + - Fixed a unicode error trying to load the CA cert bundle file on Windows when + the install path to Sublime Text contains non-ASCII characters + + - Better handling for edge case HTTP errors (thanks tgecho!) + + - Fixed a number of errors related to non-ASCII error messages being created + by the operating system (thanks quarnster!) + + - GitHub URLs will now automatically be trimmed of trailing .git suffixes + + - Badly formatted messages.json files will no longer break the install process \ No newline at end of file diff --git a/sublime/Packages/Package Control/package-metadata.json b/sublime/Packages/Package Control/package-metadata.json new file mode 100644 index 0000000..adff7f1 --- /dev/null +++ b/sublime/Packages/Package Control/package-metadata.json @@ -0,0 +1 @@ +{"url": "http://wbond.net/sublime_packages/package_control", "version": "1.6.3", "description": "A full-featured package manager"} \ No newline at end of file diff --git a/sublime/Packages/Package Control/readme.creole b/sublime/Packages/Package Control/readme.creole new file mode 100644 index 0000000..eb37565 --- /dev/null +++ b/sublime/Packages/Package Control/readme.creole @@ -0,0 +1,43 @@ += Sublime Package Control + +A Sublime Text 2 (http://www.sublimetext.com/2) package manager for easily +discovering, install, upgrading and removing packages. Also includes an +automatic updater and package creation tool. + +Packages can be installed from GitHub, BitBucket or custom package repositories. +The plugin uses a channel and repository system to allow users to find new +packages over time without any work. It also supports working with packages that +were manually installed. + +Please see http://wbond.net/sublime_packages/package_control for install +instructions, screenshots and documentation. + +== License + +Sublime Package Control (except for the ntlm library) is licensed under the MIT +license. + + Copyright (c) 2011-2012 Will Bond + + 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, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +The ntlm library (for Windows) is from the python-ntlm project +(http://code.google.com/p/python-ntlm/) and is licensed under the GNU Lesser +General Public License (LGPL). Details can be found in the source files +located in lib/windows/ntlm/. \ No newline at end of file diff --git a/sublime/Packages/User/Package Control.last-run b/sublime/Packages/User/Package Control.last-run new file mode 100644 index 0000000..b24d6be --- /dev/null +++ b/sublime/Packages/User/Package Control.last-run @@ -0,0 +1 @@ +1363369577 \ No newline at end of file diff --git a/sublime/Packages/User/Package Control.sublime-settings b/sublime/Packages/User/Package Control.sublime-settings new file mode 100644 index 0000000..2d6ff63 --- /dev/null +++ b/sublime/Packages/User/Package Control.sublime-settings @@ -0,0 +1,10 @@ +{ + "auto_upgrade_last_run": null, + "installed_packages": + [ + "AAAPackageDev", + "LESS", + "LineEndings", + "Package Control" + ] +} diff --git a/sublime/Packages/User/TOML.tmLanguage b/sublime/Packages/User/TOML.tmLanguage new file mode 100644 index 0000000..a425338 --- /dev/null +++ b/sublime/Packages/User/TOML.tmLanguage @@ -0,0 +1,180 @@ + + + + + fileTypes + + toml + tml + + name + TOML + patterns + + + include + #comments + + + captures + + 1 + + name + punctuation.definition.section.begin.toml + + 2 + + name + entity.section.toml + + 3 + + name + punctuation.definition.section.end.toml + + + comment + Key group + match + ^\s*(\[)(.*?)(\])\s* + name + meta.tag.section.toml + + + include + #dataTypes + + + repository + + comments + + patterns + + + captures + + 1 + + name + punctuation.definition.comment.toml + + + comment + Comments - whole line or partial + match + (#.*$) + name + comment.line.number-sign.toml + + + + dataTypes + + patterns + + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.toml + + + comment + String + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.toml + + + name + string.name.value.toml + + + comment + Datetime - ISO8601 dates + match + (\d{4})-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])Z + name + constant.other.date.toml + + + comment + Float + match + (-?[0-9]+)\.([0-9]+) + name + constant.numeric.float.toml + + + comment + Integer + match + -?[0-9]+ + name + constant.numeric.integer.toml + + + comment + Boolean + match + (true|false) + name + constant.language,boolean.toml + + + begin + \[ + beginCaptures + + 0 + + name + punctuation.definition.array.begin.toml + + + comment + Array + end + \] + endCaptures + + 0 + + name + punctuation.definition.array.end.toml + + + name + meta.array.toml + patterns + + + include + #comments + + + include + #dataTypes + + + + + + + scopeName + source.toml + uuid + 9b00c027-8f13-4f5a-a57e-d90478a1f817 + +