form_utils.js000064400000013673147207073150007305 0ustar00/** * form_utils.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); function getColorPickerHTML(id, target_form_element) { var h = "", dom = tinyMCEPopup.dom; if (label = dom.select('label[for=' + target_form_element + ']')[0]) { label.id = label.id || dom.uniqueId(); } h += ''; h += ' '; return h; } function updateColor(img_id, form_element_id) { document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; } function setBrowserDisabled(id, state) { var img = document.getElementById(id); var lnk = document.getElementById(id + "_link"); if (lnk) { if (state) { lnk.setAttribute("realhref", lnk.getAttribute("href")); lnk.removeAttribute("href"); tinyMCEPopup.dom.addClass(img, 'disabled'); } else { if (lnk.getAttribute("realhref")) { lnk.setAttribute("href", lnk.getAttribute("realhref")); } tinyMCEPopup.dom.removeClass(img, 'disabled'); } } } function getBrowserHTML(id, target_form_element, type, prefix) { var option = prefix + "_" + type + "_browser_callback", cb, html; cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); if (!cb) { return ""; } html = ""; html += ''; html += ' '; return html; } function openBrowser(img_id, target_form_element, type, option) { var img = document.getElementById(img_id); if (img.className != "mceButtonDisabled") { tinyMCEPopup.openBrowser(target_form_element, type, option); } } function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { if (!form_obj || !form_obj.elements[field_name]) { return; } if (!value) { value = ""; } var sel = form_obj.elements[field_name]; var found = false; for (var i = 0; i < sel.options.length; i++) { var option = sel.options[i]; if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { option.selected = true; found = true; } else { option.selected = false; } } if (!found && add_custom && value != '') { var option = new Option(value, value); option.selected = true; sel.options[sel.options.length] = option; sel.selectedIndex = sel.options.length - 1; } return found; } function getSelectValue(form_obj, field_name) { var elm = form_obj.elements[field_name]; if (elm == null || elm.options == null || elm.selectedIndex === -1) { return ""; } return elm.options[elm.selectedIndex].value; } function addSelectValue(form_obj, field_name, name, value) { var s = form_obj.elements[field_name]; var o = new Option(name, value); s.options[s.options.length] = o; } function addClassesToList(list_id, specific_option) { // Setup class droplist var styleSelectElm = document.getElementById(list_id); var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); styles = tinyMCEPopup.getParam(specific_option, styles); if (styles) { var stylesAr = styles.split(';'); for (var i = 0; i < stylesAr.length; i++) { if (stylesAr != "") { var key, value; key = stylesAr[i].split('=')[0]; value = stylesAr[i].split('=')[1]; styleSelectElm.options[styleSelectElm.length] = new Option(key, value); } } } else { /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); });*/ } } function isVisible(element_id) { var elm = document.getElementById(element_id); return elm && elm.style.display != "none"; } function convertRGBToHex(col) { var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); var rgb = col.replace(re, "$1,$2,$3").split(','); if (rgb.length == 3) { r = parseInt(rgb[0]).toString(16); g = parseInt(rgb[1]).toString(16); b = parseInt(rgb[2]).toString(16); r = r.length == 1 ? '0' + r : r; g = g.length == 1 ? '0' + g : g; b = b.length == 1 ? '0' + b : b; return "#" + r + g + b; } return col; } function convertHexToRGB(col) { if (col.indexOf('#') != -1) { col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); r = parseInt(col.substring(0, 2), 16); g = parseInt(col.substring(2, 4), 16); b = parseInt(col.substring(4, 6), 16); return "rgb(" + r + "," + g + "," + b + ")"; } return col; } function trimSize(size) { return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); } function getCSSSize(size) { size = trimSize(size); if (size == "") { return ""; } // Add px if (/^[0-9]+$/.test(size)) { size += 'px'; } // Confidence check, IE doesn't like broken values else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) { return ""; } return size; } function getStyle(elm, attrib, style) { var val = tinyMCEPopup.dom.getAttrib(elm, attrib); if (val != '') { return '' + val; } if (typeof (style) == 'undefined') { style = attrib; } return tinyMCEPopup.dom.getStyle(elm, style); } editable_selects.js000064400000004115147207073150010404 0ustar00/** * editable_selects.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var TinyMCE_EditableSelects = { editSelectElm : null, init : function () { var nl = document.getElementsByTagName("select"), i, d = document, o; for (i = 0; i < nl.length; i++) { if (nl[i].className.indexOf('mceEditableSelect') != -1) { o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); o.className = 'mceAddSelectValue'; nl[i].options[nl[i].options.length] = o; nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; } } }, onChangeEditableSelect : function (e) { var d = document, ne, se = window.event ? window.event.srcElement : e.target; if (se.options[se.selectedIndex].value == '__mce_add_custom__') { ne = d.createElement("input"); ne.id = se.id + "_custom"; ne.name = se.name + "_custom"; ne.type = "text"; ne.style.width = se.offsetWidth + 'px'; se.parentNode.insertBefore(ne, se); se.style.display = 'none'; ne.focus(); ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; TinyMCE_EditableSelects.editSelectElm = se; } }, onBlurEditableSelectInput : function () { var se = TinyMCE_EditableSelects.editSelectElm; if (se) { if (se.previousSibling.value != '') { addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); selectByValue(document.forms[0], se.id, se.previousSibling.value); } else { selectByValue(document.forms[0], se.id, ''); } se.style.display = 'inline'; se.parentNode.removeChild(se.previousSibling); TinyMCE_EditableSelects.editSelectElm = null; } }, onKeyDown : function (e) { e = e || window.event; if (e.keyCode == 13) { TinyMCE_EditableSelects.onBlurEditableSelectInput(); } } }; validate.js000064400000014502147207073150006703 0ustar00/** * validate.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /** // String validation: if (!Validator.isEmail('myemail')) alert('Invalid email.'); // Form validation: var f = document.forms['myform']; if (!Validator.isEmail(f.myemail)) alert('Invalid email.'); */ var Validator = { isEmail : function (s) { return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); }, isAbsUrl : function (s) { return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); }, isSize : function (s) { return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); }, isId : function (s) { return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); }, isEmpty : function (s) { var nl, i; if (s.nodeName == 'SELECT' && s.selectedIndex < 1) { return true; } if (s.type == 'checkbox' && !s.checked) { return true; } if (s.type == 'radio') { for (i = 0, nl = s.form.elements; i < nl.length; i++) { if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) { return false; } } return true; } return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); }, isNumber : function (s, d) { return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); }, test : function (s, p) { s = s.nodeType == 1 ? s.value : s; return s == '' || new RegExp(p).test(s); } }; var AutoValidator = { settings : { id_cls : 'id', int_cls : 'int', url_cls : 'url', number_cls : 'number', email_cls : 'email', size_cls : 'size', required_cls : 'required', invalid_cls : 'invalid', min_cls : 'min', max_cls : 'max' }, init : function (s) { var n; for (n in s) { this.settings[n] = s[n]; } }, validate : function (f) { var i, nl, s = this.settings, c = 0; nl = this.tags(f, 'label'); for (i = 0; i < nl.length; i++) { this.removeClass(nl[i], s.invalid_cls); nl[i].setAttribute('aria-invalid', false); } c += this.validateElms(f, 'input'); c += this.validateElms(f, 'select'); c += this.validateElms(f, 'textarea'); return c == 3; }, invalidate : function (n) { this.mark(n.form, n); }, getErrorMessages : function (f) { var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; nl = this.tags(f, "label"); for (i = 0; i < nl.length; i++) { if (this.hasClass(nl[i], s.invalid_cls)) { field = document.getElementById(nl[i].getAttribute("for")); values = { field: nl[i].textContent }; if (this.hasClass(field, s.min_cls, true)) { message = ed.getLang('invalid_data_min'); values.min = this.getNum(field, s.min_cls); } else if (this.hasClass(field, s.number_cls)) { message = ed.getLang('invalid_data_number'); } else if (this.hasClass(field, s.size_cls)) { message = ed.getLang('invalid_data_size'); } else { message = ed.getLang('invalid_data'); } message = message.replace(/{\#([^}]+)\}/g, function (a, b) { return values[b] || '{#' + b + '}'; }); messages.push(message); } } return messages; }, reset : function (e) { var t = ['label', 'input', 'select', 'textarea']; var i, j, nl, s = this.settings; if (e == null) { return; } for (i = 0; i < t.length; i++) { nl = this.tags(e.form ? e.form : e, t[i]); for (j = 0; j < nl.length; j++) { this.removeClass(nl[j], s.invalid_cls); nl[j].setAttribute('aria-invalid', false); } } }, validateElms : function (f, e) { var nl, i, n, s = this.settings, st = true, va = Validator, v; nl = this.tags(f, e); for (i = 0; i < nl.length; i++) { n = nl[i]; this.removeClass(n, s.invalid_cls); if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) { st = this.mark(f, n); } if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.size_cls) && !va.isSize(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.id_cls) && !va.isId(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.min_cls, true)) { v = this.getNum(n, s.min_cls); if (isNaN(v) || parseInt(n.value) < parseInt(v)) { st = this.mark(f, n); } } if (this.hasClass(n, s.max_cls, true)) { v = this.getNum(n, s.max_cls); if (isNaN(v) || parseInt(n.value) > parseInt(v)) { st = this.mark(f, n); } } } return st; }, hasClass : function (n, c, d) { return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); }, getNum : function (n, c) { c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; c = c.replace(/[^0-9]/g, ''); return c; }, addClass : function (n, c, b) { var o = this.removeClass(n, c); n.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c; }, removeClass : function (n, c) { c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); return n.className = c !== ' ' ? c : ''; }, tags : function (f, s) { return f.getElementsByTagName(s); }, mark : function (f, n) { var s = this.settings; this.addClass(n, s.invalid_cls); n.setAttribute('aria-invalid', 'true'); this.markLabels(f, n, s.invalid_cls); return false; }, markLabels : function (f, n, ic) { var nl, i; nl = this.tags(f, "label"); for (i = 0; i < nl.length; i++) { if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) { this.addClass(nl[i], ic); } } return null; } }; mctabs.js000064400000010100147207073150006351 0ustar00/** * mctabs.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /*jshint globals: tinyMCEPopup */ function MCTabs() { this.settings = []; this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); } MCTabs.prototype.init = function (settings) { this.settings = settings; }; MCTabs.prototype.getParam = function (name, default_value) { var value = null; value = (typeof (this.settings[name]) == "undefined") ? default_value : this.settings[name]; // Fix bool values if (value == "true" || value == "false") { return (value == "true"); } return value; }; MCTabs.prototype.showTab = function (tab) { tab.className = 'current'; tab.setAttribute("aria-selected", true); tab.setAttribute("aria-expanded", true); tab.tabIndex = 0; }; MCTabs.prototype.hideTab = function (tab) { var t = this; tab.className = ''; tab.setAttribute("aria-selected", false); tab.setAttribute("aria-expanded", false); tab.tabIndex = -1; }; MCTabs.prototype.showPanel = function (panel) { panel.className = 'current'; panel.setAttribute("aria-hidden", false); }; MCTabs.prototype.hidePanel = function (panel) { panel.className = 'panel'; panel.setAttribute("aria-hidden", true); }; MCTabs.prototype.getPanelForTab = function (tabElm) { return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); }; MCTabs.prototype.displayTab = function (tab_id, panel_id, avoid_focus) { var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; tabElm = document.getElementById(tab_id); if (panel_id === undefined) { panel_id = t.getPanelForTab(tabElm); } panelElm = document.getElementById(panel_id); panelContainerElm = panelElm ? panelElm.parentNode : null; tabContainerElm = tabElm ? tabElm.parentNode : null; selectionClass = t.getParam('selection_class', 'current'); if (tabElm && tabContainerElm) { nodes = tabContainerElm.childNodes; // Hide all other tabs for (i = 0; i < nodes.length; i++) { if (nodes[i].nodeName == "LI") { t.hideTab(nodes[i]); } } // Show selected tab t.showTab(tabElm); } if (panelElm && panelContainerElm) { nodes = panelContainerElm.childNodes; // Hide all other panels for (i = 0; i < nodes.length; i++) { if (nodes[i].nodeName == "DIV") { t.hidePanel(nodes[i]); } } if (!avoid_focus) { tabElm.focus(); } // Show selected panel t.showPanel(panelElm); } }; MCTabs.prototype.getAnchor = function () { var pos, url = document.location.href; if ((pos = url.lastIndexOf('#')) != -1) { return url.substring(pos + 1); } return ""; }; //Global instance var mcTabs = new MCTabs(); tinyMCEPopup.onInit.add(function () { var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; each(dom.select('div.tabs'), function (tabContainerElm) { //var keyNav; dom.setAttrib(tabContainerElm, "role", "tablist"); var items = tinyMCEPopup.dom.select('li', tabContainerElm); var action = function (id) { mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); mcTabs.onChange.dispatch(id); }; each(items, function (item) { dom.setAttrib(item, 'role', 'tab'); dom.bind(item, 'click', function (evt) { action(item.id); }); }); dom.bind(dom.getRoot(), 'keydown', function (evt) { if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab //keyNav.moveFocus(evt.shiftKey ? -1 : 1); tinymce.dom.Event.cancel(evt); } }); each(dom.select('a', tabContainerElm), function (a) { dom.setAttrib(a, 'tabindex', '-1'); }); /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { root: tabContainerElm, items: items, onAction: action, actOnFocus: true, enableLeftRight: true, enableUpDown: true }, tinyMCEPopup.dom);*/ } ); });svg/svg-sanitizer.php000064400000034403147207256750010704 0ustar00is_encoded( $original_content ); if ( $is_encoded ) { $decoded = $this->decode_svg( $original_content ); if ( false === $decoded ) { return false; } $original_content = $decoded; } $valid_svg = $this->sanitize( $original_content ); if ( false === $valid_svg ) { return false; } // If we were gzipped, we need to re-zip if ( $is_encoded ) { $valid_svg = $this->encode_svg( $valid_svg ); } file_put_contents( $filename, $valid_svg ); return true; } /** * Sanitize * * @since 3.16.0 * @access public * * @param $content * @return bool|string */ public function sanitize( $content ) { // Strip php tags $content = $this->strip_comments( $content ); $content = $this->strip_php_tags( $content ); $content = $this->strip_line_breaks( $content ); // Find the start and end tags so we can cut out miscellaneous garbage. $start = strpos( $content, '' ); if ( false === $start || false === $end ) { return false; } $content = substr( $content, $start, ( $end - $start + 6 ) ); // If the server's PHP version is 8 or up, make sure to Disable the ability to load external entities $php_version_under_eight = version_compare( PHP_VERSION, '8.0.0', '<' ); if ( $php_version_under_eight ) { $libxml_disable_entity_loader = libxml_disable_entity_loader( true ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated } // Suppress the errors $libxml_use_internal_errors = libxml_use_internal_errors( true ); // Create DomDocument instance $this->svg_dom = new \DOMDocument(); $this->svg_dom->formatOutput = false; $this->svg_dom->preserveWhiteSpace = false; $this->svg_dom->strictErrorChecking = false; $open_svg = $this->svg_dom->loadXML( $content ); if ( ! $open_svg ) { return false; } $this->strip_doctype(); $this->sanitize_elements(); // Export sanitized svg to string // Using documentElement to strip out svg_dom->saveXML( $this->svg_dom->documentElement, LIBXML_NOEMPTYTAG ); // Restore defaults if ( $php_version_under_eight ) { libxml_disable_entity_loader( $libxml_disable_entity_loader ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated } libxml_use_internal_errors( $libxml_use_internal_errors ); return $sanitized; } /** * Is Encoded * * Check if the contents of the SVG file are gzipped * @see http://www.gzip.org/zlib/rfc-gzip.html#member-format * * @since 3.16.0 * @access private * * @param $contents * * @return bool */ private function is_encoded( $contents ) { $needle = "\x1f\x8b\x08"; if ( function_exists( 'mb_strpos' ) ) { return 0 === mb_strpos( $contents, $needle ); } else { return 0 === strpos( $contents, $needle ); } } /** * Encode SVG * * @since 3.16.0 * @access private * * @param $content * @return string */ private function encode_svg( $content ) { return gzencode( $content ); } /** * Decode SVG * * @since 3.16.0 * @access private * * @param $content * * @return string */ private function decode_svg( $content ) { return gzdecode( $content ); } /** * Is Allowed Tag * * @since 3.16.0 * @access private * * @param $element * @return bool */ private function is_allowed_tag( $element ) { static $allowed_tags = false; if ( false === $allowed_tags ) { $allowed_tags = $this->get_allowed_elements(); } $tag_name = $element->tagName; // phpcs:ignore -- php DomDocument if ( ! in_array( strtolower( $tag_name ), $allowed_tags ) ) { $this->remove_element( $element ); return false; } return true; } /** * Remove Element * * Removes the passed element from its DomDocument tree * * @since 3.16.0 * @access private * * @param $element */ private function remove_element( $element ) { $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomDocument } /** * Is It An Attribute * * @since 3.16.0 * @access private * * @param $name * @param $check * @return bool */ private function is_a_attribute( $name, $check ) { return 0 === strpos( $name, $check . '-' ); } /** * Is Remote Value * * @since 3.16.0 * @access private * * @param $value * @return string */ private function is_remote_value( $value ) { $value = trim( preg_replace( '/[^ -~]/xu', '', $value ) ); $wrapped_in_url = preg_match( '~^url\(\s*[\'"]\s*(.*)\s*[\'"]\s*\)$~xi', $value, $match ); if ( ! $wrapped_in_url ) { return false; } $value = trim( $match[1], '\'"' ); return preg_match( '~^((https?|ftp|file):)?//~xi', $value ); } /** * Has JS Value * * @since 3.16.0 * @access private * * @param $value * @return false|int */ private function has_js_value( $value ) { return preg_match( '/base64|data|(?:java)?script|alert\(|window\.|document/i', $value ); } /** * Get Allowed Attributes * * Returns an array of allowed tag attributes in SVG files. * * @since 3.16.0 * @access private * * @return array */ private function get_allowed_attributes() { $allowed_attributes = [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemlanguage', 'transform', 'href', 'xlink:href', 'xlink:title', 'cx', 'cy', 'r', 'requiredfeatures', 'clippathunits', 'type', 'rx', 'ry', 'color-interpolation-filters', 'stddeviation', 'filterres', 'filterunits', 'height', 'primitiveunits', 'width', 'x', 'y', 'font-size', 'display', 'font-family', 'font-style', 'font-weight', 'text-anchor', 'marker-end', 'marker-mid', 'marker-start', 'x1', 'x2', 'y1', 'y2', 'gradienttransform', 'gradientunits', 'spreadmethod', 'markerheight', 'markerunits', 'markerwidth', 'orient', 'preserveaspectratio', 'refx', 'refy', 'viewbox', 'maskcontentunits', 'maskunits', 'd', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'fx', 'fy', 'offset', 'stop-color', 'stop-opacity', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'xml:space', 'method', 'spacing', 'startoffset', 'dx', 'dy', 'rotate', 'textlength', ]; /** * Allowed attributes in SVG file. * * Filters the list of allowed attributes in SVG files. * * Since SVG files can run JS code that may inject malicious code, all attributes * are removed except the allowed attributes. * * This hook can be used to manage allowed SVG attributes. To either add new * attributes or delete existing attributes. To strengthen or weaken site security. * * @param array $allowed_attributes A list of allowed attributes. */ $allowed_attributes = apply_filters( 'elementor/files/svg/allowed_attributes', $allowed_attributes ); return $allowed_attributes; } /** * Get Allowed Elements * * Returns an array of allowed element tags to be in SVG files. * * @since 3.16.0 * @access private * * @return array */ private function get_allowed_elements() { $allowed_elements = [ 'a', 'circle', 'clippath', 'defs', 'style', 'desc', 'ellipse', 'fegaussianblur', 'filter', 'foreignobject', 'g', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'svg', 'switch', 'symbol', 'text', 'textpath', 'title', 'tspan', 'use', ]; /** * Allowed elements in SVG file. * * Filters the list of allowed elements in SVG files. * * Since SVG files can run JS code that may inject malicious code, all elements * are removed except the allowed elements. * * This hook can be used to manage SVG elements. To either add new elements or * delete existing elements. To strengthen or weaken site security. * * @param array $allowed_elements A list of allowed elements. */ $allowed_elements = apply_filters( 'elementor/files/svg/allowed_elements', $allowed_elements ); return $allowed_elements; } /** * Validate Allowed Attributes * * @since 3.16.0 * @access private * * @param \DOMElement $element */ private function validate_allowed_attributes( $element ) { static $allowed_attributes = false; if ( false === $allowed_attributes ) { $allowed_attributes = $this->get_allowed_attributes(); } for ( $index = $element->attributes->length - 1; $index >= 0; $index-- ) { // get attribute name $attr_name = $element->attributes->item( $index )->name; $attr_name_lowercase = strtolower( $attr_name ); // Remove attribute if not in whitelist if ( ! in_array( $attr_name_lowercase, $allowed_attributes ) && ! $this->is_a_attribute( $attr_name_lowercase, 'aria' ) && ! $this->is_a_attribute( $attr_name_lowercase, 'data' ) ) { $element->removeAttribute( $attr_name ); continue; } $attr_value = $element->attributes->item( $index )->value; // Remove attribute if it has a remote reference or js or data-URI/base64 if ( ! empty( $attr_value ) && ( $this->is_remote_value( $attr_value ) || $this->has_js_value( $attr_value ) ) ) { $element->removeAttribute( $attr_name ); continue; } } } /** * Strip xlinks * * @since 3.16.0 * @access private * * @param \DOMElement $element */ private function strip_xlinks( $element ) { $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); if ( ! $xlinks ) { return; } if ( ! $this->is_safe_href( $xlinks ) ) { $element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); } } /** * @see https://github.com/darylldoyle/svg-sanitizer/blob/2321a914e/src/Sanitizer.php#L454 */ private function is_safe_href( $value ) { // Allow empty values. if ( empty( $value ) ) { return true; } // Allow fragment identifiers. if ( '#' === substr( $value, 0, 1 ) ) { return true; } // Allow relative URIs. if ( '/' === substr( $value, 0, 1 ) ) { return true; } // Allow HTTPS domains. if ( 'https://' === substr( $value, 0, 8 ) ) { return true; } // Allow HTTP domains. if ( 'http://' === substr( $value, 0, 7 ) ) { return true; } // Allow known data URIs. if ( in_array( substr( $value, 0, 14 ), [ 'data:image/png', // PNG 'data:image/gif', // GIF 'data:image/jpg', // JPG 'data:image/jpe', // JPEG 'data:image/pjp', // PJPEG ], true ) ) { return true; } // Allow known short data URIs. if ( in_array( substr( $value, 0, 12 ), [ 'data:img/png', // PNG 'data:img/gif', // GIF 'data:img/jpg', // JPG 'data:img/jpe', // JPEG 'data:img/pjp', // PJPEG ], true ) ) { return true; } return false; } /** * Validate Use Tag * * @since 3.16.0 * @access private * * @param $element */ private function validate_use_tag( $element ) { $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); if ( $xlinks && '#' !== substr( $xlinks, 0, 1 ) ) { $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomNode } } /** * Strip Doctype * * @since 3.16.0 * @access private * */ private function strip_doctype() { foreach ( $this->svg_dom->childNodes as $child ) { if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) { // phpcs:ignore -- php DomDocument $child->parentNode->removeChild( $child ); // phpcs:ignore -- php DomDocument } } } /** * Sanitize Elements * * @since 3.16.0 * @access private */ private function sanitize_elements() { $elements = $this->svg_dom->getElementsByTagName( '*' ); // loop through all elements // we do this backwards so we don't skip anything if we delete a node // see comments at: http://php.net/manual/en/class.domnamednodemap.php for ( $index = $elements->length - 1; $index >= 0; $index-- ) { /** * @var \DOMElement $current_element */ $current_element = $elements->item( $index ); // If the tag isn't in the whitelist, remove it and continue with next iteration if ( ! $this->is_allowed_tag( $current_element ) ) { continue; } //validate element attributes $this->validate_allowed_attributes( $current_element ); $this->strip_xlinks( $current_element ); if ( 'use' === strtolower( $current_element->tagName ) ) { // phpcs:ignore -- php DomDocument $this->validate_use_tag( $current_element ); } } } /** * Strip PHP Tags * * @since 3.16.0 * @access private * * @param $string * @return string */ private function strip_php_tags( $string ) { $string = preg_replace( '/<\?(=|php)(.+?)\?>/i', '', $string ); // Remove XML, ASP, etc. $string = preg_replace( '/<\?(.*)\?>/Us', '', $string ); $string = preg_replace( '/<\%(.*)\%>/Us', '', $string ); if ( ( false !== strpos( $string, '/Us', '', $string ); $string = preg_replace( '/\/\*(.*)\*\//Us', '', $string ); if ( ( false !== strpos( $string, ' $generator $rss_info_name $rss_info_url $rss_info_description $pub_date $rss_info_language $wxr_version $wxr_site_url $rss_info_url $page_on_front_xml $dynamic EOT; return $result; } public function __construct( array $args = [] ) { global $wpdb; $this->args = wp_parse_args( $args, self::$default_args ); $this->wpdb = $wpdb; } } assets-translation-loader.php000064400000004774147207256750012412 0ustar00registered[ $handle ]->src; }, $handles ); } private static function default_replace_translation( $relative_path ) { // Translations are always based on the non-minified filename. $relative_path_without_ext = preg_replace( '/(\.min)?\.js$/i', '', $relative_path ); // By default, we suffix the file with `.strings` (e.g 'assets/js/editor.js' => 'assets/js/editor.strings.js'). return implode( '.', [ $relative_path_without_ext, 'strings', 'js', ] ); } } http.php000064400000001725147207256750006260 0ustar00request( $url, $args ); if ( $this->is_successful_response( $response ) ) { return $response; } } return $response; } /** * @param $response * * @return bool */ private function is_successful_response( $response ) { if ( is_wp_error( $response ) ) { return false; } $response_code = (int) wp_remote_retrieve_response_code( $response ); if ( in_array( $response_code, [ 0, 404, 500 ], true ) ) { return false; } return true; } } force-locale.php000064400000007070147207256750007633 0ustar00new_locale = $new_locale; $this->original_locale = $original_locale ? $original_locale : determine_locale(); $this->filter = function() use ( $new_locale ) { return $new_locale; }; } /** * Force the translations to use a specific locale. * * @return void */ public function force() { switch_to_locale( $this->new_locale ); /** * Reset the \WP_Textdomain_Registry instance to clear its cache. * * @see https://github.com/WordPress/wordpress-develop/blob/799d7dc86f5b07b17f7a418948fc851bd2fc334b/src/wp-includes/class-wp-textdomain-registry.php#L179-L187 * @see https://github.com/WordPress/wordpress-develop/blob/799d7dc86f5b07b17f7a418948fc851bd2fc334b/tests/phpunit/tests/l10n/wpLocaleSwitcher.php#L19-L31 */ $this->reset_textdomain_registry(); /** * Reset l10n in order to clear the translations cache. * * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1324 * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1222 * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L821 */ $this->reset_l10n(); /** * Force the translations of `$new_locale` to be loaded. * * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1294 */ add_filter( 'pre_determine_locale', $this->filter ); } /** * Restore the original locale and cleanup filters, etc. * * @return void */ public function restore() { $this->restore_textdomain_registry(); $this->reset_l10n(); switch_to_locale( $this->original_locale ); remove_filter( 'pre_determine_locale', $this->filter ); } private function reset_textdomain_registry() { if ( ! class_exists( '\WP_Textdomain_Registry' ) ) { return; } /** @var \WP_Textdomain_Registry $wp_textdomain_registry */ global $wp_textdomain_registry; $this->original_textdomain_registry = $wp_textdomain_registry; $wp_textdomain_registry = new \WP_Textdomain_Registry(); } private function restore_textdomain_registry() { if ( ! $this->original_textdomain_registry ) { return; } /** @var \WP_Textdomain_Registry $wp_textdomain_registry */ global $wp_textdomain_registry; $wp_textdomain_registry = $this->original_textdomain_registry; } /** * Reset the l10n global variables. * * @return void */ private function reset_l10n() { global $l10n, $l10n_unloaded; if ( is_array( $l10n ) ) { foreach ( $l10n as $domain => $l10n_data ) { unset( $l10n[ $domain ] ); } } if ( is_array( $l10n_unloaded ) ) { foreach ( $l10n_unloaded as $domain => $l10n_unloaded_data ) { unset( $l10n_unloaded[ $domain ] ); } } } } hints.php000064400000023266147207256750006432 0ustar00 [ self::DISMISSED => 'image-optimization-once', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization-once-media-modal' => [ self::DISMISSED => 'image-optimization-once-media-modal', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization' => [ self::DISMISSED => 'image_optimizer_hint', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization-media-modal' => [ self::DISMISSED => 'image-optimization-media-modal', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], ]; if ( ! $hint_key ) { return $hints; } return $hints[ $hint_key ] ?? []; } /** * get_notice_icon * @return string */ public static function get_notice_icon(): string { return '
'; } /** * get_notice_template * * Print or Retrieve the notice template. * @param array $notice * @param bool $return * * @return string|void */ public static function get_notice_template( array $notice, bool $return = false ) { $default_settings = [ 'type' => 'info', 'icon' => false, 'heading' => '', 'content' => '', 'dismissible' => false, 'button_text' => '', 'button_event' => '', 'button_data' => [], 'display' => false, ]; $notice_settings = array_merge( $default_settings, $notice ); if ( empty( $notice_settings['heading'] ) && empty( $notice_settings['content'] ) ) { return ''; } if ( ! in_array( $notice_settings['type'], self::get_notice_types(), true ) ) { $notice_settings['type'] = 'info'; } $icon = ''; $heading = ''; $content = ''; $dismissible = ''; $button = ''; if ( $notice_settings['icon'] ) { $icon = self::get_notice_icon(); } if ( ! empty( $notice_settings['heading'] ) ) { $heading = '
' . $notice_settings['heading'] . '
'; } if ( ! empty( $notice_settings['content'] ) ) { $content = '
' . $notice_settings['content'] . '
'; } if ( ! empty( $notice_settings['button_text'] ) ) { $button_settings = ( ! empty( $notice_settings['button_data'] ) ) ? ' data-settings="' . esc_attr( json_encode( $notice_settings['button_data'] ) ) . '"' : ''; $button = '
'; } if ( $notice_settings['dismissible'] ) { $dismissible = ''; } $notice_template = sprintf( '
%2$s
%3$s %4$s %5$s
%6$s
', $notice_settings['type'], $icon, $heading, $content, $button, $dismissible, $notice_settings['display'] ); if ( $return ) { return $notice_template; } echo wp_kses( $notice_template, self::get_notice_allowed_html() ); } /** * get_plugin_install_url * @param $plugin_slug * * @return string */ public static function get_plugin_install_url( $plugin_slug ): string { $action = 'install-plugin'; return wp_nonce_url( add_query_arg( [ 'action' => $action, 'plugin' => $plugin_slug, ], admin_url( 'update.php' ) ), $action . '_' . $plugin_slug ); } /** * get_plugin_activate_url * @param $plugin_slug * * @return string */ public static function get_plugin_activate_url( $plugin_slug ): string { $path = "$plugin_slug/$plugin_slug.php"; return wp_nonce_url( admin_url( 'plugins.php?action=activate&plugin=' . $path ), 'activate-plugin_' . $path ); } /** * is_dismissed * @param $key * * @return bool */ public static function is_dismissed( $key ): bool { $dismissed = User::get_dismissed_editor_notices(); return in_array( $key, $dismissed, true ); } /** * should_display_hint * @param $hint_key * * @return bool */ public static function should_display_hint( $hint_key ): bool { $hint = self::get_hints( $hint_key ); if ( empty( $hint ) ) { return false; } foreach ( $hint as $key => $value ) { switch ( $key ) { case self::DISMISSED: if ( self::is_dismissed( $value ) ) { return false; } break; case self::CAPABILITY: if ( ! current_user_can( $value ) ) { return false; } break; case self::DEFINED: if ( defined( $value ) ) { return false; } break; case self::PLUGIN_INSTALLED: if ( ! self::is_plugin_installed( $value ) ) { return false; } break; case self::PLUGIN_ACTIVE: if ( ! self::is_plugin_active( $value ) ) { return false; } break; } } return true; } private static function is_conflict_plugin_installed(): bool { if ( ! Utils::has_pro() ) { return false; } $conflicting_plugins = [ 'imagify/imagify.php', 'optimole-wp/optimole-wp.php', 'ewww-image-optimizer/ewww-image-optimizer.php', 'ewww-image-optimizer-cloud/ewww-image-optimizer-cloud.php', 'kraken-image-optimizer/kraken.php', 'shortpixel-image-optimiser/wp-shortpixel.php', 'wp-smushit/wp-smush.php', 'wp-smush-pro/wp-smush.php', 'tiny-compress-images/tiny-compress-images.php', ]; foreach ( $conflicting_plugins as $plugin ) { if ( self::is_plugin_active( $plugin ) ) { return true; } } return false; } /** * is_plugin_installed * @param $plugin * * @return bool */ public static function is_plugin_installed( $plugin ) : bool { $plugins = get_plugins(); $plugin = self::ensure_plugin_folder( $plugin ); return ! empty( $plugins[ $plugin ] ); } /** * is_plugin_active * @param $plugin * * @return bool */ public static function is_plugin_active( $plugin ): bool { $plugin = self::ensure_plugin_folder( $plugin ); return is_plugin_active( $plugin ); } /** * get_plugin_action_url * @param $plugin * * @return string */ public static function get_plugin_action_url( $plugin ): string { if ( ! self::is_plugin_installed( $plugin ) ) { return self::get_plugin_install_url( $plugin ); } if ( ! self::is_plugin_active( $plugin ) ) { return self::get_plugin_activate_url( $plugin ); } return ''; } /** * ensure_plugin_folder * @param $plugin * * @return string */ private static function ensure_plugin_folder( $plugin ): string { if ( false === strpos( $plugin, '/' ) ) { $plugin = $plugin . '/' . $plugin . '.php'; } return $plugin; } /** * get_notice_allowed_html * @return array[] */ public static function get_notice_allowed_html(): array { return [ 'div' => [ 'class' => [], 'data-display' => [], ], 'svg' => [ 'width' => [], 'height' => [], 'viewbox' => [], 'fill' => [], 'xmlns' => [], ], 'path' => [ 'd' => [], 'stroke' => [], 'stroke-width' => [], 'stroke-linecap' => [], 'stroke-linejoin' => [], ], 'button' => [ 'class' => [], 'data-event' => [], 'data-settings' => [], 'data-tooltip' => [], ], 'i' => [ 'class' => [], 'aria-hidden' => [], ], 'span' => [ 'class' => [], ], 'a' => [ 'href' => [], 'style' => [], 'target' => [], ], ]; } } promotions/filtered-promotions-manager.php000064400000004143147207256750015124 0ustar00path_resolver = $path_resolver; return $this; } /** * Load asset config from a file into the collection. * * @param $key * @param $path * * @return $this */ public function load( $key, $path = null ) { if ( ! $path && $this->path_resolver ) { $path_resolver_callback = $this->path_resolver; $path = $path_resolver_callback( $key ); } if ( ! $path || ! file_exists( $path ) ) { return $this; } $config = require $path; if ( ! $this->is_valid_handle( $config ) ) { return $this; } $this->items[ $key ] = [ 'handle' => $config['handle'], 'deps' => $this->is_valid_deps( $config ) ? $config['deps'] : [], ]; return $this; } /** * Check that the handle property in the config is a valid. * * @param $config * * @return bool */ private function is_valid_handle( $config ) { return ! empty( $config['handle'] ) && is_string( $config['handle'] ); } /** * Check that the deps property in the config is a valid. * * @param $config * * @return bool */ private function is_valid_deps( $config ) { return isset( $config['deps'] ) && is_array( $config['deps'] ); } } collection.php000064400000022573147207256750007440 0ustar00items = $items; } /** * @param array $items * * @return static */ public static function make( array $items = [] ) { return new static( $items ); } /** * @param callable|null $callback * * @return $this */ public function filter( callable $callback = null ) { if ( ! $callback ) { return new static( array_filter( $this->items ) ); } return new static( array_filter( $this->items, $callback, ARRAY_FILTER_USE_BOTH ) ); } /** * @param $items * * @return $this */ public function merge( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_merge( $this->items, $items ) ); } /** * Union the collection with the given items. * * @param array $items * * @return $this */ public function union( array $items ) { return new static( $this->all() + $items ); } /** * Merge array recursively * * @param $items * * @return $this */ public function merge_recursive( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_merge_recursive( $this->items, $items ) ); } /** * Replace array recursively * * @param $items * * @return $this */ public function replace_recursive( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_replace_recursive( $this->items, $items ) ); } /** * Implode the items * * @param $glue * * @return string */ public function implode( $glue ) { return implode( $glue, $this->items ); } /** * Run a map over each of the items. * * @param callable $callback * @return $this */ public function map( callable $callback ) { $keys = array_keys( $this->items ); $items = array_map( $callback, $this->items, $keys ); return new static( array_combine( $keys, $items ) ); } /** * Run a callback over each of the items. * * @param callable $callback * @return $this */ public function each( callable $callback ) { foreach ( $this->items as $key => $value ) { if ( false === $callback( $value, $key ) ) { break; } } return $this; } /** * @param callable $callback * @param null $initial * * @return mixed|null */ public function reduce( callable $callback, $initial = null ) { $result = $initial; foreach ( $this->all() as $key => $value ) { $result = $callback( $result, $value, $key ); } return $result; } /** * @param callable $callback * * @return $this */ public function map_with_keys( callable $callback ) { $result = []; foreach ( $this->items as $key => $value ) { $assoc = $callback( $value, $key ); foreach ( $assoc as $map_key => $map_value ) { $result[ $map_key ] = $map_value; } } return new static( $result ); } /** * Get all items except for those with the specified keys. * * @param array $keys * * @return $this */ public function except( array $keys ) { return $this->filter( function ( $value, $key ) use ( $keys ) { return ! in_array( $key, $keys, true ); } ); } /** * Get the items with the specified keys. * * @param array $keys * * @return $this */ public function only( array $keys ) { return $this->filter( function ( $value, $key ) use ( $keys ) { return in_array( $key, $keys, true ); } ); } /** * Run over the collection to get specific prop from the collection item. * * @param $key * * @return $this */ public function pluck( $key ) { $result = []; foreach ( $this->items as $item ) { $result[] = $this->get_item_value( $item, $key ); } return new static( $result ); } /** * Group the collection items by specific key in each collection item. * * @param $group_by * * @return $this */ public function group_by( $group_by ) { $result = []; foreach ( $this->items as $item ) { $group_key = $this->get_item_value( $item, $group_by, 0 ); $result[ $group_key ][] = $item; } return new static( $result ); } /** * Sort keys * * @param false $descending * * @return $this */ public function sort_keys( $descending = false ) { $items = $this->items; if ( $descending ) { krsort( $items ); } else { ksort( $items ); } return new static( $items ); } /** * Get specific item from the collection. * * @param $key * @param null $default * * @return mixed|null */ public function get( $key, $default = null ) { if ( ! array_key_exists( $key, $this->items ) ) { return $default; } return $this->items[ $key ]; } /** * Get the first item. * * @param null $default * * @return mixed|null */ public function first( $default = null ) { if ( $this->is_empty() ) { return $default; } foreach ( $this->items as $item ) { return $item; } } /** * Find an element from the items. * * @param callable $callback * @param null $default * * @return mixed|null */ public function find( callable $callback, $default = null ) { foreach ( $this->all() as $key => $item ) { if ( $callback( $item, $key ) ) { return $item; } } return $default; } /** * @param callable|string|int $value * * @return bool */ public function contains( $value ) { $callback = $value instanceof \Closure ? $value : function ( $item ) use ( $value ) { return $item === $value; }; foreach ( $this->all() as $key => $item ) { if ( $callback( $item, $key ) ) { return true; } } return false; } /** * Make sure all the values inside the array are uniques. * * @param null|string|string[] $keys * * @return $this */ public function unique( $keys = null ) { if ( ! $keys ) { return new static( array_unique( $this->items ) ); } if ( ! is_array( $keys ) ) { $keys = [ $keys ]; } $exists = []; return $this->filter( function ( $item ) use ( $keys, &$exists ) { $value = null; foreach ( $keys as $key ) { $current_value = $this->get_item_value( $item, $key ); $value .= "{$key}:{$current_value};"; } // If no value for the specific key return the item. if ( null === $value ) { return true; } // If value is not exists, add to the exists array and return the item. if ( ! in_array( $value, $exists, true ) ) { $exists[] = $value; return true; } return false; } ); } /** * @return array */ public function keys() { return array_keys( $this->items ); } /** * @return bool */ public function is_empty() { return empty( $this->items ); } /** * @return array */ public function all() { return $this->items; } /** * @return array */ public function values() { return array_values( $this->all() ); } /** * Support only one level depth. * * @return $this */ public function flatten() { $result = []; foreach ( $this->all() as $item ) { $item = $item instanceof Collection ? $item->all() : $item; if ( ! is_array( $item ) ) { $result[] = $item; } else { $values = array_values( $item ); foreach ( $values as $value ) { $result[] = $value; } } } return new static( $result ); } /** * @param ...$values * * @return $this */ public function push( ...$values ) { foreach ( $values as $value ) { $this->items[] = $value; } return $this; } public function prepend( ...$values ) { $this->items = array_merge( $values, $this->items ); return $this; } public function some( callable $callback ) { foreach ( $this->items as $key => $item ) { if ( $callback( $item, $key ) ) { return true; } } return false; } /** * @param mixed $offset * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists( $offset ) { return isset( $this->items[ $offset ] ); } /** * @param mixed $offset * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet( $offset ) { return $this->items[ $offset ]; } /** * @param mixed $offset * @param mixed $value */ #[\ReturnTypeWillChange] public function offsetSet( $offset, $value ) { if ( is_null( $offset ) ) { $this->items[] = $value; } else { $this->items[ $offset ] = $value; } } /** * @param mixed $offset */ #[\ReturnTypeWillChange] public function offsetUnset( $offset ) { unset( $this->items[ $offset ] ); } /** * @return \ArrayIterator|\Traversable */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator( $this->items ); } /** * @return int|void */ #[\ReturnTypeWillChange] public function count() { return count( $this->items ); } /** * @param $item * @param $key * @param null $default * * @return mixed|null */ private function get_item_value( $item, $key, $default = null ) { $value = $default; if ( is_object( $item ) && isset( $item->{$key} ) ) { $value = $item->{$key}; } elseif ( is_array( $item ) && isset( $item[ $key ] ) ) { $value = $item[ $key ]; } return $value; } } plugins-manager.php000064400000005532147207256750010372 0ustar00upgrader = $upgrader; } else { $skin = new WP_Ajax_Upgrader_Skin(); $this->upgrader = new Plugin_Upgrader( $skin ); } } /** * Install plugin or an array of plugins. * * @since 3.6.2 * * @param string|array $plugins * @return array [ 'succeeded' => [] , 'failed' => [] ] */ public function install( $plugins ) { $succeeded = []; $failed = []; $already_installed_plugins = Plugin::$instance->wp->get_plugins(); if ( ! is_array( $plugins ) ) { $plugins = [ $plugins ]; } foreach ( $plugins as $plugin ) { if ( in_array( $plugin, $already_installed_plugins->keys(), true ) ) { $succeeded[] = $plugin; continue; } $slug = $this->clean_slug( $plugin ); $api = Plugin::$instance->wp->plugins_api('plugin_information', [ 'slug' => $slug, 'fields' => array( 'short_description' => false, 'sections' => false, 'requires' => false, 'rating' => false, 'ratings' => false, 'downloaded' => false, 'last_updated' => false, 'added' => false, 'tags' => false, 'compatibility' => false, 'homepage' => false, 'donate_link' => false, ), ] ); if ( ! isset( $api->download_link ) ) { $failed[] = $plugin; continue; } $installation = $this->upgrader->install( $api->download_link ); if ( $installation ) { $succeeded[] = $plugin; } else { $failed[] = $plugin; } } return [ 'succeeded' => $succeeded, 'failed' => $failed, ]; } /** * Activate plugin or array off plugins. * * @since 3.6.2 * * @param array|string $plugins * @return array [ 'succeeded' => [] , 'failed' => [] ] */ public function activate( $plugins ) { $succeeded = []; $failed = []; if ( ! is_array( $plugins ) ) { $plugins = [ $plugins ]; } foreach ( $plugins as $plugin ) { if ( Plugin::$instance->wp->is_plugin_active( $plugin ) ) { $succeeded[] = $plugin; continue; } Plugin::$instance->wp->activate_plugin( $plugin ); if ( Plugin::$instance->wp->is_plugin_active( $plugin ) ) { $succeeded[] = $plugin; } else { $failed[] = $plugin; } } return [ 'succeeded' => $succeeded, 'failed' => $failed, ]; } private function clean_slug( $initial_slug ) { return explode( '/', $initial_slug )[0]; } } version.php000064400000007211147207256750006762 0ustar00major1 = $major1; $this->major2 = $major2; $this->patch = $patch; $this->stage = $stage; } /** * Create Version instance. * * @param string $major1 * @param string $major2 * @param string $patch * @param null $stage * * @return static */ public static function create( $major1 = '0', $major2 = '0', $patch = '0', $stage = null ) { return new static( $major1, $major2, $patch, $stage ); } /** * Checks if the current version string is valid. * * @param $version * * @return bool */ public static function is_valid_version( $version ) { return ! ! preg_match( '/^(\d+\.)?(\d+\.)?(\*|\d+)(-.+)?$/', $version ); } /** * Creates a Version instance from a string. * * @param $version * @param bool $should_validate * * @return static * @throws \Exception */ public static function create_from_string( $version, $should_validate = true ) { if ( $should_validate && ! static::is_valid_version( $version ) ) { throw new \Exception( "{$version} is an invalid version." ); } $parts = explode( '.', $version ); $patch_parts = []; $major1 = '0'; $major2 = '0'; $patch = '0'; $stage = null; if ( isset( $parts[0] ) ) { $major1 = $parts[0]; } if ( isset( $parts[1] ) ) { $major2 = $parts[1]; } if ( isset( $parts[2] ) ) { $patch_parts = explode( '-', $parts[2] ); $patch = $patch_parts[0]; } if ( isset( $patch_parts[1] ) ) { $stage = $patch_parts[1]; } return static::create( $major1, $major2, $patch, $stage ); } /** * Compare the current version instance with another version. * * @param $operator * @param $version * @param string $part * * @return bool * @throws \Exception */ public function compare( $operator, $version, $part = self::PART_STAGE ) { if ( ! ( $version instanceof Version ) ) { if ( ! static::is_valid_version( $version ) ) { $version = '0.0.0'; } $version = static::create_from_string( $version, false ); } $current_version = clone $this; $compare_version = clone $version; if ( in_array( $part, [ self::PART_PATCH, self::PART_MAJOR_2, self::PART_MAJOR_1 ], true ) ) { $current_version->stage = null; $compare_version->stage = null; } if ( in_array( $part, [ self::PART_MAJOR_2, self::PART_MAJOR_1 ], true ) ) { $current_version->patch = '0'; $compare_version->patch = '0'; } if ( self::PART_MAJOR_1 === $part ) { $current_version->major2 = '0'; $compare_version->major2 = '0'; } return version_compare( $current_version, $compare_version, $operator ); } /** * Implode the version and return it as string. * * @return string */ public function __toString() { $version = implode( '.', [ $this->major1, $this->major2, $this->patch ] ); if ( $this->stage ) { $version .= '-' . $this->stage; } return $version; } } __init__.py000064400000110001147221650610006652 0ustar00"""passlib.utils -- helpers for writing password hashes""" #============================================================================= # imports #============================================================================= from passlib.utils.compat import JYTHON # core from binascii import b2a_base64, a2b_base64, Error as _BinAsciiError from base64 import b64encode, b64decode import collections from codecs import lookup as _lookup_codec from functools import update_wrapper import itertools import inspect import logging; log = logging.getLogger(__name__) import math import os import sys import random import re if JYTHON: # pragma: no cover -- runtime detection # Jython 2.5.2 lacks stringprep module - # see http://bugs.jython.org/issue1758320 try: import stringprep except ImportError: stringprep = None _stringprep_missing_reason = "not present under Jython" else: import stringprep import time if stringprep: import unicodedata import types from warnings import warn # site # pkg from passlib.utils.binary import ( # [remove these aliases in 2.0] BASE64_CHARS, AB64_CHARS, HASH64_CHARS, BCRYPT_CHARS, Base64Engine, LazyBase64Engine, h64, h64big, bcrypt64, ab64_encode, ab64_decode, b64s_encode, b64s_decode ) from passlib.utils.decor import ( # [remove these aliases in 2.0] deprecated_function, deprecated_method, memoized_property, classproperty, hybrid_method, ) from passlib.exc import ExpectedStringError from passlib.utils.compat import (add_doc, join_bytes, join_byte_values, join_byte_elems, irange, imap, PY3, u, join_unicode, unicode, byte_elem_value, nextgetter, unicode_or_bytes_types, get_method_function, suppress_cause) # local __all__ = [ # constants 'JYTHON', 'sys_bits', 'unix_crypt_schemes', 'rounds_cost_values', # unicode helpers 'consteq', 'saslprep', # bytes helpers "xor_bytes", "render_bytes", # encoding helpers 'is_same_codec', 'is_ascii_safe', 'to_bytes', 'to_unicode', 'to_native_str', # host OS 'has_crypt', 'test_crypt', 'safe_crypt', 'tick', # randomness 'rng', 'getrandbytes', 'getrandstr', 'generate_password', # object type / interface tests 'is_crypt_handler', 'is_crypt_context', 'has_rounds_info', 'has_salt_info', ] #============================================================================= # constants #============================================================================= # bitsize of system architecture (32 or 64) sys_bits = int(math.log(sys.maxsize if PY3 else sys.maxint, 2) + 1.5) # list of hashes algs supported by crypt() on at least one OS. # XXX: move to .registry for passlib 2.0? unix_crypt_schemes = [ "sha512_crypt", "sha256_crypt", "sha1_crypt", "bcrypt", "md5_crypt", # "bsd_nthash", "bsdi_crypt", "des_crypt", ] # list of rounds_cost constants rounds_cost_values = [ "linear", "log2" ] # legacy import, will be removed in 1.8 from passlib.exc import MissingBackendError # internal helpers _BEMPTY = b'' _UEMPTY = u("") _USPACE = u(" ") # maximum password size which passlib will allow; see exc.PasswordSizeError MAX_PASSWORD_SIZE = int(os.environ.get("PASSLIB_MAX_PASSWORD_SIZE") or 4096) #============================================================================= # type helpers #============================================================================= class SequenceMixin(object): """ helper which lets result object act like a fixed-length sequence. subclass just needs to provide :meth:`_as_tuple()`. """ def _as_tuple(self): raise NotImplemented("implement in subclass") def __repr__(self): return repr(self._as_tuple()) def __getitem__(self, idx): return self._as_tuple()[idx] def __iter__(self): return iter(self._as_tuple()) def __len__(self): return len(self._as_tuple()) def __eq__(self, other): return self._as_tuple() == other def __ne__(self, other): return not self.__eq__(other) if PY3: # getargspec() is deprecated, use this under py3. # even though it's a lot more awkward to get basic info :| _VAR_KEYWORD = inspect.Parameter.VAR_KEYWORD _VAR_ANY_SET = set([_VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL]) def accepts_keyword(func, key): """test if function accepts specified keyword""" params = inspect.signature(get_method_function(func)).parameters if not params: return False arg = params.get(key) if arg and arg.kind not in _VAR_ANY_SET: return True # XXX: annoying what we have to do to determine if VAR_KWDS in use. return params[list(params)[-1]].kind == _VAR_KEYWORD else: def accepts_keyword(func, key): """test if function accepts specified keyword""" spec = inspect.getargspec(get_method_function(func)) return key in spec.args or spec.keywords is not None def update_mixin_classes(target, add=None, remove=None, append=False, before=None, after=None, dryrun=False): """ helper to update mixin classes installed in target class. :param target: target class whose bases will be modified. :param add: class / classes to install into target's base class list. :param remove: class / classes to remove from target's base class list. :param append: by default, prepends mixins to front of list. if True, appends to end of list instead. :param after: optionally make sure all mixins are inserted after this class / classes. :param before: optionally make sure all mixins are inserted before this class / classes. :param dryrun: optionally perform all calculations / raise errors, but don't actually modify the class. """ if isinstance(add, type): add = [add] bases = list(target.__bases__) # strip out requested mixins if remove: if isinstance(remove, type): remove = [remove] for mixin in remove: if add and mixin in add: continue if mixin in bases: bases.remove(mixin) # add requested mixins if add: for mixin in add: # if mixin already present (explicitly or not), leave alone if any(issubclass(base, mixin) for base in bases): continue # determine insertion point if append: for idx, base in enumerate(bases): if issubclass(mixin, base): # don't insert mixin after one of it's own bases break if before and issubclass(base, before): # don't insert mixin after any classes. break else: # append to end idx = len(bases) elif after: for end_idx, base in enumerate(reversed(bases)): if issubclass(base, after): # don't insert mixin before any classes. idx = len(bases) - end_idx assert bases[idx-1] == base break else: idx = 0 else: # insert at start idx = 0 # insert mixin bases.insert(idx, mixin) # modify class if not dryrun: target.__bases__ = tuple(bases) #============================================================================= # collection helpers #============================================================================= def batch(source, size): """ split iterable into chunks of elements. """ if size < 1: raise ValueError("size must be positive integer") if isinstance(source, collections.Sequence): end = len(source) i = 0 while i < end: n = i + size yield source[i:n] i = n elif isinstance(source, collections.Iterable): itr = iter(source) while True: chunk_itr = itertools.islice(itr, size) try: first = next(chunk_itr) except StopIteration: break yield itertools.chain((first,), chunk_itr) else: raise TypeError("source must be iterable") #============================================================================= # unicode helpers #============================================================================= # XXX: should this be moved to passlib.crypto, or compat backports? def consteq(left, right): """Check two strings/bytes for equality. This function uses an approach designed to prevent timing analysis, making it appropriate for cryptography. a and b must both be of the same type: either str (ASCII only), or any type that supports the buffer protocol (e.g. bytes). Note: If a and b are of different lengths, or if an error occurs, a timing attack could theoretically reveal information about the types and lengths of a and b--but not their values. """ # NOTE: # resources & discussions considered in the design of this function: # hmac timing attack -- # http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/ # python developer discussion surrounding similar function -- # http://bugs.python.org/issue15061 # http://bugs.python.org/issue14955 # validate types if isinstance(left, unicode): if not isinstance(right, unicode): raise TypeError("inputs must be both unicode or both bytes") is_py3_bytes = False elif isinstance(left, bytes): if not isinstance(right, bytes): raise TypeError("inputs must be both unicode or both bytes") is_py3_bytes = PY3 else: raise TypeError("inputs must be both unicode or both bytes") # do size comparison. # NOTE: the double-if construction below is done deliberately, to ensure # the same number of operations (including branches) is performed regardless # of whether left & right are the same size. same_size = (len(left) == len(right)) if same_size: # if sizes are the same, setup loop to perform actual check of contents. tmp = left result = 0 if not same_size: # if sizes aren't the same, set 'result' so equality will fail regardless # of contents. then, to ensure we do exactly 'len(right)' iterations # of the loop, just compare 'right' against itself. tmp = right result = 1 # run constant-time string comparision # TODO: use izip instead (but first verify it's faster than zip for this case) if is_py3_bytes: for l,r in zip(tmp, right): result |= l ^ r else: for l,r in zip(tmp, right): result |= ord(l) ^ ord(r) return result == 0 # keep copy of this around since stdlib's version throws error on non-ascii chars in unicode strings. # our version does, but suffers from some underlying VM issues. but something is better than # nothing for plaintext hashes, which need this. everything else should use consteq(), # since the stdlib one is going to be as good / better in the general case. str_consteq = consteq try: # for py3.3 and up, use the stdlib version from hmac import compare_digest as consteq except ImportError: pass # TODO: could check for cryptography package's version, # but only operates on bytes, so would need a wrapper, # or separate consteq() into a unicode & a bytes variant. # from cryptography.hazmat.primitives.constant_time import bytes_eq as consteq def splitcomma(source, sep=","): """split comma-separated string into list of elements, stripping whitespace. """ source = source.strip() if source.endswith(sep): source = source[:-1] if not source: return [] return [ elem.strip() for elem in source.split(sep) ] def saslprep(source, param="value"): """Normalizes unicode strings using SASLPrep stringprep profile. The SASLPrep profile is defined in :rfc:`4013`. It provides a uniform scheme for normalizing unicode usernames and passwords before performing byte-value sensitive operations such as hashing. Among other things, it normalizes diacritic representations, removes non-printing characters, and forbids invalid characters such as ``\\n``. Properly internationalized applications should run user passwords through this function before hashing. :arg source: unicode string to normalize & validate :param param: Optional noun identifying source parameter in error messages (Defaults to the string ``"value"``). This is mainly useful to make the caller's error messages make more sense contextually. :raises ValueError: if any characters forbidden by the SASLPrep profile are encountered. :raises TypeError: if input is not :class:`!unicode` :returns: normalized unicode string .. note:: This function is not available under Jython, as the Jython stdlib is missing the :mod:`!stringprep` module (`Jython issue 1758320 `_). .. versionadded:: 1.6 """ # saslprep - http://tools.ietf.org/html/rfc4013 # stringprep - http://tools.ietf.org/html/rfc3454 # http://docs.python.org/library/stringprep.html # validate type # XXX: support bytes (e.g. run through want_unicode)? # might be easier to just integrate this into cryptcontext. if not isinstance(source, unicode): raise TypeError("input must be unicode string, not %s" % (type(source),)) # mapping stage # - map non-ascii spaces to U+0020 (stringprep C.1.2) # - strip 'commonly mapped to nothing' chars (stringprep B.1) in_table_c12 = stringprep.in_table_c12 in_table_b1 = stringprep.in_table_b1 data = join_unicode( _USPACE if in_table_c12(c) else c for c in source if not in_table_b1(c) ) # normalize to KC form data = unicodedata.normalize('NFKC', data) if not data: return _UEMPTY # check for invalid bi-directional strings. # stringprep requires the following: # - chars in C.8 must be prohibited. # - if any R/AL chars in string: # - no L chars allowed in string # - first and last must be R/AL chars # this checks if start/end are R/AL chars. if so, prohibited loop # will forbid all L chars. if not, prohibited loop will forbid all # R/AL chars instead. in both cases, prohibited loop takes care of C.8. is_ral_char = stringprep.in_table_d1 if is_ral_char(data[0]): if not is_ral_char(data[-1]): raise ValueError("malformed bidi sequence in " + param) # forbid L chars within R/AL sequence. is_forbidden_bidi_char = stringprep.in_table_d2 else: # forbid R/AL chars if start not setup correctly; L chars allowed. is_forbidden_bidi_char = is_ral_char # check for prohibited output - stringprep tables A.1, B.1, C.1.2, C.2 - C.9 in_table_a1 = stringprep.in_table_a1 in_table_c21_c22 = stringprep.in_table_c21_c22 in_table_c3 = stringprep.in_table_c3 in_table_c4 = stringprep.in_table_c4 in_table_c5 = stringprep.in_table_c5 in_table_c6 = stringprep.in_table_c6 in_table_c7 = stringprep.in_table_c7 in_table_c8 = stringprep.in_table_c8 in_table_c9 = stringprep.in_table_c9 for c in data: # check for chars mapping stage should have removed assert not in_table_b1(c), "failed to strip B.1 in mapping stage" assert not in_table_c12(c), "failed to replace C.1.2 in mapping stage" # check for forbidden chars if in_table_a1(c): raise ValueError("unassigned code points forbidden in " + param) if in_table_c21_c22(c): raise ValueError("control characters forbidden in " + param) if in_table_c3(c): raise ValueError("private use characters forbidden in " + param) if in_table_c4(c): raise ValueError("non-char code points forbidden in " + param) if in_table_c5(c): raise ValueError("surrogate codes forbidden in " + param) if in_table_c6(c): raise ValueError("non-plaintext chars forbidden in " + param) if in_table_c7(c): # XXX: should these have been caught by normalize? # if so, should change this to an assert raise ValueError("non-canonical chars forbidden in " + param) if in_table_c8(c): raise ValueError("display-modifying / deprecated chars " "forbidden in" + param) if in_table_c9(c): raise ValueError("tagged characters forbidden in " + param) # do bidi constraint check chosen by bidi init, above if is_forbidden_bidi_char(c): raise ValueError("forbidden bidi character in " + param) return data # replace saslprep() with stub when stringprep is missing if stringprep is None: # pragma: no cover -- runtime detection def saslprep(source, param="value"): """stub for saslprep()""" raise NotImplementedError("saslprep() support requires the 'stringprep' " "module, which is " + _stringprep_missing_reason) #============================================================================= # bytes helpers #============================================================================= def render_bytes(source, *args): """Peform ``%`` formating using bytes in a uniform manner across Python 2/3. This function is motivated by the fact that :class:`bytes` instances do not support ``%`` or ``{}`` formatting under Python 3. This function is an attempt to provide a replacement: it converts everything to unicode (decoding bytes instances as ``latin-1``), performs the required formatting, then encodes the result to ``latin-1``. Calling ``render_bytes(source, *args)`` should function roughly the same as ``source % args`` under Python 2. """ if isinstance(source, bytes): source = source.decode("latin-1") result = source % tuple(arg.decode("latin-1") if isinstance(arg, bytes) else arg for arg in args) return result.encode("latin-1") if PY3: # new in py32 def bytes_to_int(value): return int.from_bytes(value, 'big') def int_to_bytes(value, count): return value.to_bytes(count, 'big') else: # XXX: can any of these be sped up? from binascii import hexlify, unhexlify def bytes_to_int(value): return int(hexlify(value),16) def int_to_bytes(value, count): return unhexlify(('%%0%dx' % (count<<1)) % value) add_doc(bytes_to_int, "decode byte string as single big-endian integer") add_doc(int_to_bytes, "encode integer as single big-endian byte string") def xor_bytes(left, right): """Perform bitwise-xor of two byte strings (must be same size)""" return int_to_bytes(bytes_to_int(left) ^ bytes_to_int(right), len(left)) def repeat_string(source, size): """repeat or truncate string, so it has length """ cur = len(source) if size > cur: mult = (size+cur-1)//cur return (source*mult)[:size] else: return source[:size] _BNULL = b"\x00" _UNULL = u("\x00") def right_pad_string(source, size, pad=None): """right-pad or truncate string, so it has length """ cur = len(source) if size > cur: if pad is None: pad = _UNULL if isinstance(source, unicode) else _BNULL return source+pad*(size-cur) else: return source[:size] #============================================================================= # encoding helpers #============================================================================= _ASCII_TEST_BYTES = b"\x00\n aA:#!\x7f" _ASCII_TEST_UNICODE = _ASCII_TEST_BYTES.decode("ascii") def is_ascii_codec(codec): """Test if codec is compatible with 7-bit ascii (e.g. latin-1, utf-8; but not utf-16)""" return _ASCII_TEST_UNICODE.encode(codec) == _ASCII_TEST_BYTES def is_same_codec(left, right): """Check if two codec names are aliases for same codec""" if left == right: return True if not (left and right): return False return _lookup_codec(left).name == _lookup_codec(right).name _B80 = b'\x80'[0] _U80 = u('\x80') def is_ascii_safe(source): """Check if string (bytes or unicode) contains only 7-bit ascii""" r = _B80 if isinstance(source, bytes) else _U80 return all(c < r for c in source) def to_bytes(source, encoding="utf-8", param="value", source_encoding=None): """Helper to normalize input to bytes. :arg source: Source bytes/unicode to process. :arg encoding: Target encoding (defaults to ``"utf-8"``). :param param: Optional name of variable/noun to reference when raising errors :param source_encoding: If this is specified, and the source is bytes, the source will be transcoded from *source_encoding* to *encoding* (via unicode). :raises TypeError: if source is not unicode or bytes. :returns: * unicode strings will be encoded using *encoding*, and returned. * if *source_encoding* is not specified, byte strings will be returned unchanged. * if *source_encoding* is specified, byte strings will be transcoded to *encoding*. """ assert encoding if isinstance(source, bytes): if source_encoding and not is_same_codec(source_encoding, encoding): return source.decode(source_encoding).encode(encoding) else: return source elif isinstance(source, unicode): return source.encode(encoding) else: raise ExpectedStringError(source, param) def to_unicode(source, encoding="utf-8", param="value"): """Helper to normalize input to unicode. :arg source: source bytes/unicode to process. :arg encoding: encoding to use when decoding bytes instances. :param param: optional name of variable/noun to reference when raising errors. :raises TypeError: if source is not unicode or bytes. :returns: * returns unicode strings unchanged. * returns bytes strings decoded using *encoding* """ assert encoding if isinstance(source, unicode): return source elif isinstance(source, bytes): return source.decode(encoding) else: raise ExpectedStringError(source, param) if PY3: def to_native_str(source, encoding="utf-8", param="value"): if isinstance(source, bytes): return source.decode(encoding) elif isinstance(source, unicode): return source else: raise ExpectedStringError(source, param) else: def to_native_str(source, encoding="utf-8", param="value"): if isinstance(source, bytes): return source elif isinstance(source, unicode): return source.encode(encoding) else: raise ExpectedStringError(source, param) add_doc(to_native_str, """Take in unicode or bytes, return native string. Python 2: encodes unicode using specified encoding, leaves bytes alone. Python 3: leaves unicode alone, decodes bytes using specified encoding. :raises TypeError: if source is not unicode or bytes. :arg source: source unicode or bytes string. :arg encoding: encoding to use when encoding unicode or decoding bytes. this defaults to ``"utf-8"``. :param param: optional name of variable/noun to reference when raising errors. :returns: :class:`str` instance """) @deprecated_function(deprecated="1.6", removed="1.7") def to_hash_str(source, encoding="ascii"): # pragma: no cover -- deprecated & unused """deprecated, use to_native_str() instead""" return to_native_str(source, encoding, param="hash") _true_set = set("true t yes y on 1 enable enabled".split()) _false_set = set("false f no n off 0 disable disabled".split()) _none_set = set(["", "none"]) def as_bool(value, none=None, param="boolean"): """ helper to convert value to boolean. recognizes strings such as "true", "false" """ assert none in [True, False, None] if isinstance(value, unicode_or_bytes_types): clean = value.lower().strip() if clean in _true_set: return True if clean in _false_set: return False if clean in _none_set: return none raise ValueError("unrecognized %s value: %r" % (param, value)) elif isinstance(value, bool): return value elif value is None: return none else: return bool(value) #============================================================================= # host OS helpers #============================================================================= try: from crypt import crypt as _crypt except ImportError: # pragma: no cover _crypt = None has_crypt = False def safe_crypt(secret, hash): return None else: has_crypt = True _NULL = '\x00' # some crypt() variants will return various constant strings when # an invalid/unrecognized config string is passed in; instead of # returning NULL / None. examples include ":", ":0", "*0", etc. # safe_crypt() returns None for any string starting with one of the # chars in this string... _invalid_prefixes = u("*:!") if PY3: def safe_crypt(secret, hash): if isinstance(secret, bytes): # Python 3's crypt() only accepts unicode, which is then # encoding using utf-8 before passing to the C-level crypt(). # so we have to decode the secret. orig = secret try: secret = secret.decode("utf-8") except UnicodeDecodeError: return None assert secret.encode("utf-8") == orig, \ "utf-8 spec says this can't happen!" if _NULL in secret: raise ValueError("null character in secret") if isinstance(hash, bytes): hash = hash.decode("ascii") result = _crypt(secret, hash) if not result or result[0] in _invalid_prefixes: return None return result else: def safe_crypt(secret, hash): if isinstance(secret, unicode): secret = secret.encode("utf-8") if _NULL in secret: raise ValueError("null character in secret") if isinstance(hash, unicode): hash = hash.encode("ascii") result = _crypt(secret, hash) if not result: return None result = result.decode("ascii") if result[0] in _invalid_prefixes: return None return result add_doc(safe_crypt, """Wrapper around stdlib's crypt. This is a wrapper around stdlib's :func:`!crypt.crypt`, which attempts to provide uniform behavior across Python 2 and 3. :arg secret: password, as bytes or unicode (unicode will be encoded as ``utf-8``). :arg hash: hash or config string, as ascii bytes or unicode. :returns: resulting hash as ascii unicode; or ``None`` if the password couldn't be hashed due to one of the issues: * :func:`crypt()` not available on platform. * Under Python 3, if *secret* is specified as bytes, it must be use ``utf-8`` or it can't be passed to :func:`crypt()`. * Some OSes will return ``None`` if they don't recognize the algorithm being used (though most will simply fall back to des-crypt). * Some OSes will return an error string if the input config is recognized but malformed; current code converts these to ``None`` as well. """) def test_crypt(secret, hash): """check if :func:`crypt.crypt` supports specific hash :arg secret: password to test :arg hash: known hash of password to use as reference :returns: True or False """ assert secret and hash return safe_crypt(secret, hash) == hash # pick best timer function to expose as "tick" - lifted from timeit module. if sys.platform == "win32": # On Windows, the best timer is time.clock() from time import clock as timer else: # On most other platforms the best timer is time.time() from time import time as timer # legacy alias, will be removed in passlib 2.0 tick = timer def parse_version(source): """helper to parse version string""" m = re.search(r"(\d+(?:\.\d+)+)", source) if m: return tuple(int(elem) for elem in m.group(1).split(".")) return None #============================================================================= # randomness #============================================================================= #------------------------------------------------------------------------ # setup rng for generating salts #------------------------------------------------------------------------ # NOTE: # generating salts (e.g. h64_gensalt, below) doesn't require cryptographically # strong randomness. it just requires enough range of possible outputs # that making a rainbow table is too costly. so it should be ok to # fall back on python's builtin mersenne twister prng, as long as it's seeded each time # this module is imported, using a couple of minor entropy sources. try: os.urandom(1) has_urandom = True except NotImplementedError: # pragma: no cover has_urandom = False def genseed(value=None): """generate prng seed value from system resources""" from hashlib import sha512 if hasattr(value, "getstate") and hasattr(value, "getrandbits"): # caller passed in RNG as seed value try: value = value.getstate() except NotImplementedError: # this method throws error for e.g. SystemRandom instances, # so fall back to extracting 4k of state value = value.getrandbits(1 << 15) text = u("%s %s %s %.15f %.15f %s") % ( # if caller specified a seed value, mix it in value, # add current process id # NOTE: not available in some environments, e.g. GAE os.getpid() if hasattr(os, "getpid") else None, # id of a freshly created object. # (at least 1 byte of which should be hard to predict) id(object()), # the current time, to whatever precision os uses time.time(), time.clock(), # if urandom available, might as well mix some bytes in. os.urandom(32).decode("latin-1") if has_urandom else 0, ) # hash it all up and return it as int/long return int(sha512(text.encode("utf-8")).hexdigest(), 16) if has_urandom: rng = random.SystemRandom() else: # pragma: no cover -- runtime detection # NOTE: to reseed use ``rng.seed(genseed(rng))`` # XXX: could reseed on every call rng = random.Random(genseed()) #------------------------------------------------------------------------ # some rng helpers #------------------------------------------------------------------------ def getrandbytes(rng, count): """return byte-string containing *count* number of randomly generated bytes, using specified rng""" # NOTE: would be nice if this was present in stdlib Random class ###just in case rng provides this... ##meth = getattr(rng, "getrandbytes", None) ##if meth: ## return meth(count) if not count: return _BEMPTY def helper(): # XXX: break into chunks for large number of bits? value = rng.getrandbits(count<<3) i = 0 while i < count: yield value & 0xff value >>= 3 i += 1 return join_byte_values(helper()) def getrandstr(rng, charset, count): """return string containing *count* number of chars/bytes, whose elements are drawn from specified charset, using specified rng""" # NOTE: tests determined this is 4x faster than rng.sample(), # which is why that's not being used here. # check alphabet & count if count < 0: raise ValueError("count must be >= 0") letters = len(charset) if letters == 0: raise ValueError("alphabet must not be empty") if letters == 1: return charset * count # get random value, and write out to buffer def helper(): # XXX: break into chunks for large number of letters? value = rng.randrange(0, letters**count) i = 0 while i < count: yield charset[value % letters] value //= letters i += 1 if isinstance(charset, unicode): return join_unicode(helper()) else: return join_byte_elems(helper()) _52charset = '2346789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrstuvwxyz' @deprecated_function(deprecated="1.7", removed="2.0", replacement="passlib.pwd.genword() / passlib.pwd.genphrase()") def generate_password(size=10, charset=_52charset): """generate random password using given length & charset :param size: size of password. :param charset: optional string specified set of characters to draw from. the default charset contains all normal alphanumeric characters, except for the characters ``1IiLl0OoS5``, which were omitted due to their visual similarity. :returns: :class:`!str` containing randomly generated password. .. note:: Using the default character set, on a OS with :class:`!SystemRandom` support, this function should generate passwords with 5.7 bits of entropy per character. """ return getrandstr(rng, charset, size) #============================================================================= # object type / interface tests #============================================================================= _handler_attrs = ( "name", "setting_kwds", "context_kwds", "verify", "hash", "identify", ) def is_crypt_handler(obj): """check if object follows the :ref:`password-hash-api`""" # XXX: change to use isinstance(obj, PasswordHash) under py26+? return all(hasattr(obj, name) for name in _handler_attrs) _context_attrs = ( "needs_update", "genconfig", "genhash", "verify", "encrypt", "identify", ) def is_crypt_context(obj): """check if object appears to be a :class:`~passlib.context.CryptContext` instance""" # XXX: change to use isinstance(obj, CryptContext)? return all(hasattr(obj, name) for name in _context_attrs) ##def has_many_backends(handler): ## "check if handler provides multiple baceknds" ## # NOTE: should also provide get_backend(), .has_backend(), and .backends attr ## return hasattr(handler, "set_backend") def has_rounds_info(handler): """check if handler provides the optional :ref:`rounds information ` attributes""" return ('rounds' in handler.setting_kwds and getattr(handler, "min_rounds", None) is not None) def has_salt_info(handler): """check if handler provides the optional :ref:`salt information ` attributes""" return ('salt' in handler.setting_kwds and getattr(handler, "min_salt_size", None) is not None) ##def has_raw_salt(handler): ## "check if handler takes in encoded salt as unicode (False), or decoded salt as bytes (True)" ## sc = getattr(handler, "salt_chars", None) ## if sc is None: ## return None ## elif isinstance(sc, unicode): ## return False ## elif isinstance(sc, bytes): ## return True ## else: ## raise TypeError("handler.salt_chars must be None/unicode/bytes") #============================================================================= # eof #============================================================================= hashes.py000064400000005462147221650610006404 0ustar00from __future__ import absolute_import import hashlib from pip.exceptions import HashMismatch, HashMissing, InstallationError from pip.utils import read_chunks from pip._vendor.six import iteritems, iterkeys, itervalues # The recommended hash algo of the moment. Change this whenever the state of # the art changes; it won't hurt backward compatibility. FAVORITE_HASH = 'sha256' # Names of hashlib algorithms allowed by the --hash option and ``pip hash`` # Currently, those are the ones at least as collision-resistant as sha256. STRONG_HASHES = ['sha256', 'sha384', 'sha512'] class Hashes(object): """A wrapper that builds multiple hashes at once and checks them against known-good values """ def __init__(self, hashes=None): """ :param hashes: A dict of algorithm names pointing to lists of allowed hex digests """ self._allowed = {} if hashes is None else hashes def check_against_chunks(self, chunks): """Check good hashes against ones built from iterable of chunks of data. Raise HashMismatch if none match. """ gots = {} for hash_name in iterkeys(self._allowed): try: gots[hash_name] = hashlib.new(hash_name) except (ValueError, TypeError): raise InstallationError('Unknown hash name: %s' % hash_name) for chunk in chunks: for hash in itervalues(gots): hash.update(chunk) for hash_name, got in iteritems(gots): if got.hexdigest() in self._allowed[hash_name]: return self._raise(gots) def _raise(self, gots): raise HashMismatch(self._allowed, gots) def check_against_file(self, file): """Check good hashes against a file-like object Raise HashMismatch if none match. """ return self.check_against_chunks(read_chunks(file)) def check_against_path(self, path): with open(path, 'rb') as file: return self.check_against_file(file) def __nonzero__(self): """Return whether I know any known-good hashes.""" return bool(self._allowed) def __bool__(self): return self.__nonzero__() class MissingHashes(Hashes): """A workalike for Hashes used when we're missing a hash for a requirement It computes the actual hash of the requirement and raises a HashMissing exception showing it to the user. """ def __init__(self): """Don't offer the ``hashes`` kwarg.""" # Pass our favorite hash in to generate a "gotten hash". With the # empty list, it will never match, so an error will always raise. super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []}) def _raise(self, gots): raise HashMissing(gots[FAVORITE_HASH].hexdigest()) outdated.py000064400000013545147221650610006743 0ustar00from __future__ import absolute_import import datetime import json import logging import os.path import sys from pip._vendor import lockfile from pip._vendor.packaging import version as packaging_version from pip.compat import total_seconds, WINDOWS from pip.models import PyPI from pip.locations import USER_CACHE_DIR, running_under_virtualenv from pip.utils import ensure_dir, get_installed_version from pip.utils.filesystem import check_path_owner SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" logger = logging.getLogger(__name__) class VirtualenvSelfCheckState(object): def __init__(self): self.statefile_path = os.path.join(sys.prefix, "pip-selfcheck.json") # Load the existing state try: with open(self.statefile_path) as statefile: self.state = json.load(statefile) except (IOError, ValueError): self.state = {} def save(self, pypi_version, current_time): # Attempt to write out our version check file with open(self.statefile_path, "w") as statefile: json.dump( { "last_check": current_time.strftime(SELFCHECK_DATE_FMT), "pypi_version": pypi_version, }, statefile, sort_keys=True, separators=(",", ":") ) class GlobalSelfCheckState(object): def __init__(self): self.statefile_path = os.path.join(USER_CACHE_DIR, "selfcheck.json") # Load the existing state try: with open(self.statefile_path) as statefile: self.state = json.load(statefile)[sys.prefix] except (IOError, ValueError, KeyError): self.state = {} def save(self, pypi_version, current_time): # Check to make sure that we own the directory if not check_path_owner(os.path.dirname(self.statefile_path)): return # Now that we've ensured the directory is owned by this user, we'll go # ahead and make sure that all our directories are created. ensure_dir(os.path.dirname(self.statefile_path)) # Attempt to write out our version check file with lockfile.LockFile(self.statefile_path): if os.path.exists(self.statefile_path): with open(self.statefile_path) as statefile: state = json.load(statefile) else: state = {} state[sys.prefix] = { "last_check": current_time.strftime(SELFCHECK_DATE_FMT), "pypi_version": pypi_version, } with open(self.statefile_path, "w") as statefile: json.dump(state, statefile, sort_keys=True, separators=(",", ":")) def load_selfcheck_statefile(): if running_under_virtualenv(): return VirtualenvSelfCheckState() else: return GlobalSelfCheckState() def pip_installed_by_pip(): """Checks whether pip was installed by pip This is used not to display the upgrade message when pip is in fact installed by system package manager, such as dnf on Fedora. """ import pkg_resources try: dist = pkg_resources.get_distribution('pip') return (dist.has_metadata('INSTALLER') and 'pip' in dist.get_metadata_lines('INSTALLER')) except pkg_resources.DistributionNotFound: return False def pip_version_check(session): """Check for an update for pip. Limit the frequency of checks to once per week. State is stored either in the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix of the pip script path. """ installed_version = get_installed_version("pip") if installed_version is None: return pip_version = packaging_version.parse(installed_version) pypi_version = None try: state = load_selfcheck_statefile() current_time = datetime.datetime.utcnow() # Determine if we need to refresh the state if "last_check" in state.state and "pypi_version" in state.state: last_check = datetime.datetime.strptime( state.state["last_check"], SELFCHECK_DATE_FMT ) if total_seconds(current_time - last_check) < 7 * 24 * 60 * 60: pypi_version = state.state["pypi_version"] # Refresh the version if we need to or just see if we need to warn if pypi_version is None: resp = session.get( PyPI.pip_json_url, headers={"Accept": "application/json"}, ) resp.raise_for_status() pypi_version = [ v for v in sorted( list(resp.json()["releases"]), key=packaging_version.parse, ) if not packaging_version.parse(v).is_prerelease ][-1] # save that we've performed a check state.save(pypi_version, current_time) remote_version = packaging_version.parse(pypi_version) # Determine if our pypi_version is older if (pip_version < remote_version and pip_version.base_version != remote_version.base_version and pip_installed_by_pip()): # Advise "python -m pip" on Windows to avoid issues # with overwriting pip.exe. if WINDOWS: pip_cmd = "python -m pip" else: pip_cmd = "pip" logger.warning( "You are using pip version %s, however version %s is " "available.\nYou should consider upgrading via the " "'%s install --upgrade pip' command.", pip_version, pypi_version, pip_cmd ) except Exception: logger.debug( "There was an error checking the latest version of pip", exc_info=True, ) __pycache__/filesystem.cpython-36.opt-1.pyc000064400000001064147221650610014532 0ustar003 . g@s(ddlZddlZddlmZddZdS)N) get_path_uidc CsttdsdSd}xp||krtjj|rntjdkr^y t|}Wntk rTdSX|dkStj|tjSq|tjj |}}qWdS)NgeteuidTrF) hasattrospathlexistsrrOSErroraccessW_OKdirname)rZpreviousZpath_uidr /usr/lib/python3.6/filesystem.pycheck_path_owners     r)rZos.pathZ pip.compatrrr r r r s __pycache__/filesystem.cpython-36.pyc000064400000001064147221650610013573 0ustar003 . g@s(ddlZddlZddlmZddZdS)N) get_path_uidc CsttdsdSd}xp||krtjj|rntjdkr^y t|}Wntk rTdSX|dkStj|tjSq|tjj |}}qWdS)NgeteuidTrF) hasattrospathlexistsrrOSErroraccessW_OKdirname)rZpreviousZpath_uidr /usr/lib/python3.6/filesystem.pycheck_path_owners     r)rZos.pathZ pip.compatrrr r r r s __pycache__/hashes.cpython-36.pyc000064400000006227147221650610012670 0ustar003 . g2 @szddlmZddlZddlmZmZmZddlmZddl m Z m Z m Z dZ dddgZGd d d eZGd d d eZdS) )absolute_importN) HashMismatch HashMissingInstallationError) read_chunks) iteritemsiterkeys itervaluesZsha256Zsha384Zsha512c@sJeZdZdZdddZddZddZd d Zd d Zd dZ ddZ dS)HasheszaA wrapper that builds multiple hashes at once and checks them against known-good values NcCs|dkr in||_dS)zo :param hashes: A dict of algorithm names pointing to lists of allowed hex digests N)_allowed)selfhashesr/usr/lib/python3.6/hashes.py__init__szHashes.__init__c Csi}xJt|jD]<}ytj|||<Wqttfk rJtd|YqXqWx(|D] }xt|D]}|j|qdWqVWx*t |D]\}}|j |j|krdSqW|j |dS)zCheck good hashes against ones built from iterable of chunks of data. Raise HashMismatch if none match. zUnknown hash name: %sN) rr hashlibnew ValueError TypeErrorrr updater hexdigest_raise)r ZchunksgotsZ hash_namechunkhashZgotrrrcheck_against_chunks s zHashes.check_against_chunkscCst|j|dS)N)rr )r rrrrr7sz Hashes._raisecCs|jt|S)zaCheck good hashes against a file-like object Raise HashMismatch if none match. )rr)r filerrrcheck_against_file:szHashes.check_against_filec Cs t|d }|j|SQRXdS)Nrb)openr)r pathrrrrcheck_against_pathBs zHashes.check_against_pathcCs t|jS)z,Return whether I know any known-good hashes.)boolr )r rrr __nonzero__FszHashes.__nonzero__cCs|jS)N)r#)r rrr__bool__JszHashes.__bool__)N) __name__ __module__ __qualname____doc__rrrrr!r#r$rrrrr s r cs(eZdZdZfddZddZZS) MissingHasheszA workalike for Hashes used when we're missing a hash for a requirement It computes the actual hash of the requirement and raises a HashMissing exception showing it to the user. cstt|jtgiddS)z!Don't offer the ``hashes`` kwarg.)r N)superr)r FAVORITE_HASH)r ) __class__rrrUszMissingHashes.__init__cCst|tjdS)N)rr+r)r rrrrr[szMissingHashes._raise)r%r&r'r(rr __classcell__rr)r,rr)Ns r))Z __future__rrZpip.exceptionsrrrZ pip.utilsrZpip._vendor.sixrrr r+Z STRONG_HASHESobjectr r)rrrrs   :__pycache__/appdirs.cpython-36.pyc000064400000017002147221650610013050 0ustar003 . gk" @sdZddlmZddlZddlZddlmZmZddlm Z m Z ddZ dd d Z dd d Z ddZddZddZeryddlZeZWnek reZYnXddZdS)zd This code was taken from https://github.com/ActiveState/appdirs and modified to suit our purposes. )absolute_importN)WINDOWS expanduser)PY2 text_typecCstr Unix: ~/.cache/ (XDG default) Windows: C:\Users\\AppData\Local\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir`). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. CSIDL_LOCAL_APPDATAZCachedarwinz~/Library/CachesZXDG_CACHE_HOMEz~/.cache)rospathnormpath_get_win_folderr isinstancer_win_path_to_bytesjoinsysplatformrgetenv)appnamer r/usr/lib/python3.6/appdirs.pyuser_cache_dirs rFcCshtr,|r dpd}tjjtjjt||}n8tjdkrJtjjtd|}ntjjtj dtd|}|S)aS Return full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\ ... ...Application Data\ Win XP (roaming): C:\Documents and Settings\\Local ... ...Settings\Application Data\ Win 7 (not roaming): C:\Users\\AppData\Local\ Win 7 (roaming): C:\Users\\AppData\Roaming\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". CSIDL_APPDATArrz~/Library/Application Support/Z XDG_DATA_HOMEz~/.local/share) rr r rr r rrrr)rroamingconstr rrr user_data_dir>s  rTcCsHtrt||d}n2tjdkr&t|}ntjdtd}tjj||}|S)arReturn full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default True) can be set False to not use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: same as user_data_dir Unix: ~/.config/ Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by default "~/.config/". )rrZXDG_CONFIG_HOMEz ~/.config) rrrrr rrr r)rrr rrruser_config_dirjs  rcstr&tjjtd}tjj|g}nVtjdkrBtjjdg}n:tjdd}|rnfdd|j tj D}ng}|j d|S) aReturn a list of potential user-shared config dirs for this application. "appname" is the name of application. Typical user config directories are: macOS: /Library/Application Support// Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in $XDG_CONFIG_DIRS Win XP: C:\Documents and Settings\All Users\Application ... ...Data\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: Hidden, but writeable on Win 7: C:\ProgramData\ CSIDL_COMMON_APPDATArz/Library/Application SupportZXDG_CONFIG_DIRSz/etc/xdgcsg|]}tjjt|qSr)r r rr).0x)rrr sz$site_config_dirs..z/etc) rr r r r rrrrsplitpathsepappend)rr ZpathlistZxdg_config_dirsr)rrsite_config_dirss    r#cCs:ddl}dddd|}|j|jd}|j||\}}|S)z This is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. rNZAppDatazCommon AppDataz Local AppData)rrrz@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders)_winregOpenKeyHKEY_CURRENT_USERZ QueryValueEx) csidl_namer$Zshell_folder_namekeyZ directoryZ_typerrr_get_win_folder_from_registrysr)cCsdddd|}tjd}tjjjd|dd|d}x|D]}t|dkr:d }Pq:W|rztjd}tjjj|j|drz|}|jS) N#)rrrirFT) ctypesZcreate_unicode_bufferZwindllZshell32ZSHGetFolderPathWordZkernel32ZGetShortPathNameWvalue)r'Z csidl_constZbufZ has_high_charcZbuf2rrr_get_win_folder_with_ctypess     r2c Cs6x0dD](}y |j|Sttfk r,YqXqW|S)aEncode Windows paths to bytes. Only used on Python 2. Motivation is to be consistent with other operating systems where paths are also returned as bytes. This avoids problems mixing bytes and Unicode elsewhere in the codebase. For more details and discussion see . If encoding using ASCII and MBCS fails, return the original Unicode path. ASCIIMBCS)r3r4)encodeUnicodeEncodeError LookupError)r encodingrrrrs   r)F)T)__doc__Z __future__rr rZ pip.compatrrZpip._vendor.sixrrrrrr#r)r2r.r ImportErrorrrrrrs$ 0 , !( __pycache__/outdated.cpython-36.opt-1.pyc000064400000011147147221650610014162 0ustar003 . ge@sddlmZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl mZmZddlmZddlmZmZddlmZmZdd lmZd ZejeZGd d d eZGd ddeZ ddZ!ddZ"ddZ#dS))absolute_importN)lockfile)version) total_secondsWINDOWS)PyPI)USER_CACHE_DIRrunning_under_virtualenv) ensure_dirget_installed_version)check_path_ownerz%Y-%m-%dT%H:%M:%SZc@seZdZddZddZdS)VirtualenvSelfCheckStatecCs\tjjtjd|_y&t|j}tj||_ WdQRXWnt t fk rVi|_ YnXdS)Nzpip-selfcheck.json) ospathjoinsysprefixstatefile_pathopenjsonloadstateIOError ValueError)self statefiler/usr/lib/python3.6/outdated.py__init__s  z!VirtualenvSelfCheckState.__init__c Cs:t|jd$}tj|jt|d|dddWdQRXdS)Nw) last_check pypi_versionT,:) sort_keys separators)r"r#)rrrdumpstrftimeSELFCHECK_DATE_FMT)rr! current_timerrrrsave$szVirtualenvSelfCheckState.saveN)__name__ __module__ __qualname__rr*rrrrr s r c@seZdZddZddZdS)GlobalSelfCheckStatecCsbtjjtd|_y,t|j}tj|tj |_ WdQRXWn t t t fk r\i|_ YnXdS)Nzselfcheck.json)rrrrrrrrrrrrrKeyError)rrrrrr3s   zGlobalSelfCheckState.__init__cCsttjj|jsdSttjj|jtj|jztjj|jrft |j}t j |}WdQRXni}|j t |d|tj<t |jd}t j||dddWdQRXWdQRXdS)N)r r!rTr"r#)r$r%)r"r#)r rrdirnamerr rZLockFileexistsrrrr'r(rrr&)rr!r)rrrrrr*=s  zGlobalSelfCheckState.saveN)r+r,r-rr*rrrrr.2s r.cCstr tStSdS)N)r r r.rrrrload_selfcheck_statefileXsr2c CsFddl}y"|jd}|jdo*d|jdkS|jk r@dSXdS)zChecks whether pip was installed by pip This is used not to display the upgrade message when pip is in fact installed by system package manager, such as dnf on Fedora. rNpipZ INSTALLERF) pkg_resourcesZget_distributionZ has_metadataZget_metadata_linesZDistributionNotFound)r4Zdistrrrpip_installed_by_pip_s  r5c CsFtd}|dkrdStj|}d}yt}tjj}d|jkrxd|jkrxtjj|jdt}t ||dkrx|jd}|dkr|j t j dd id }|j d d tt|jd tjdDd}|j||tj|}||kr|j|jkrtrtrd} nd} tjd||| Wn$tk r@tjdddYnXdS)zCheck for an update for pip. Limit the frequency of checks to once per week. State is stored either in the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix of the pip script path. r3Nr r!<ZAcceptzapplication/json)ZheaderscSsg|]}tj|js|qSr)packaging_versionparseZ is_prerelease).0vrrr sz%pip_version_check..Zreleases)keyz python -m pipzYou are using pip version %s, however version %s is available. You should consider upgrading via the '%s install --upgrade pip' command.z5There was an error checking the latest version of pipT)exc_infoi`'i: )r r9r:r2datetimeZutcnowrZstrptimer(rgetrZ pip_json_urlZraise_for_statussortedlistrr*Z base_versionr5rloggerZwarning Exceptiondebug) ZsessionZinstalled_versionZ pip_versionr!rr)r ZrespZremote_versionZpip_cmdrrrpip_version_checknsL        rJ)$Z __future__rrCrZloggingZos.pathrrZ pip._vendorrZpip._vendor.packagingrr9Z pip.compatrrZ pip.modelsrZ pip.locationsrr Z pip.utilsr r Zpip.utils.filesystemr r(Z getLoggerr+rGobjectr r.r2r5rJrrrrs&      &__pycache__/packaging.cpython-36.opt-1.pyc000064400000003657147221650610014304 0ustar003 . g @s~ddlmZddlmZddlZddlZddlmZddlmZddl m Z ddl m Z ej eZdd Zd d Zd d ZdS))absolute_import) FeedParserN) specifiers)version) pkg_resources) exceptionscCs>|dkr dStj|}tjdjtttjdd}||kS)aG Check if the python version in use match the `requires_python` specifier. Returns `True` if the version of python in use matches the requirement. Returns `False` if the version of python in use does not matches the requirement. Raises an InvalidSpecifier if `requires_python` have an invalid format. NT.) rZ SpecifierSetrparsejoinmapstrsys version_info)requires_pythonZrequires_python_specifierZpython_versionr/usr/lib/python3.6/packaging.pycheck_requires_pythons   rcCs8t|tjr |jdr |jdS|jdr4|jdSdS)NZMETADATAzPKG-INFO) isinstancerZDistInfoDistributionZ has_metadata get_metadata)distrrrr%s     rcCst|}t}|j||j}|jd}y8t|s`tjd|j|dj t t t j ddfWn8tjk r}ztjd|j||fdSd}~XnXdS)NzRequires-Pythonz4%s requires Python '%s' but the running Python is %srr z7Package %s has an invalid Requires-Python entry %s - %s)rrZfeedclosegetrrZUnsupportedPythonVersionZ project_namer r r rrrZInvalidSpecifierloggerZwarning)rZmetadataZ feed_parserZ pkg_info_dictrerrrcheck_dist_requires_python-s"  $r)Z __future__rZ email.parserrZloggingrZpip._vendor.packagingrrZ pip._vendorrZpiprZ getLogger__name__rrrrrrrrs       __pycache__/glibc.cpython-36.opt-1.pyc000064400000002503147221650610013425 0ustar003 . g{ @sPddlmZddlZddlZddlZddlZddZddZddZd d Z dS) )absolute_importNc CsPtjd}y |j}Wntk r(dSXtj|_|}t|tsL|jd}|S)z9Returns glibc version string, or None if not using glibc.Nascii) ctypesZCDLLgnu_get_libc_versionAttributeErrorZc_char_pZrestype isinstancestrdecode)Zprocess_namespacer version_strr /usr/lib/python3.6/glibc.pyglibc_version_string s    r cCsHtjd|}|s$tjd|tdSt|jd|koFt|jd|kS)Nz$(?P[0-9]+)\.(?P[0-9]+)z=Expected glibc version with 2 components major.minor, got: %sFmajorminor)rematchwarningswarnRuntimeWarningintgroup)r required_major minimum_minormr r r check_glibc_version#s  rcCst}|dkrdSt|||S)NF)r r)rrr r r r have_compatible_glibc3srcCs"t}|dkrtjSd|fSdS)NZglibc)r platformlibc_ver)Z glibc_versionr r r rKsr) Z __future__rrrrrr rrrr r r r s __pycache__/deprecation.cpython-36.opt-1.pyc000064400000003255147221650610014647 0ustar003 . g@sdZddlmZddlZddlZGdddeZGdddeZGdd d eZ Gd d d eeZ Gd d d eZ da dddZ ddZdS)zN A module that implements tooling to enable easy warnings about deprecations. )absolute_importNc@s eZdZdS)PipDeprecationWarningN)__name__ __module__ __qualname__rr!/usr/lib/python3.6/deprecation.pyr src@s eZdZdS)PendingN)rrrrrrrr sr c@s eZdZdS)RemovedInPip10WarningN)rrrrrrrr sr c@s eZdZdS)RemovedInPip11WarningN)rrrrrrrr sr c@s eZdZdS)Python26DeprecationWarningN)rrrrrrrr sr cCsx|dk r$tdk rtt||||||nPt|trbtjd}d|}t|trV|j|qt|j|nt||||||dS)Nzpip.deprecationszDEPRECATION: %s)_warnings_showwarning issubclassrloggingZ getLoggerr Zwarningerror)messagecategoryfilenamelinenofilelineZloggerZ log_messagerrr _showwarning$s     rcCs(tjdtddtdkr$tjatt_dS)NdefaultT)append)warnings simplefilterrr showwarningrrrrrinstall_warning_loggerDsr)NN)__doc__Z __future__rrrWarningrobjectr r r r r rrrrrrs  __pycache__/packaging.cpython-36.pyc000064400000003657147221650610013345 0ustar003 . g @s~ddlmZddlmZddlZddlZddlmZddlmZddl m Z ddl m Z ej eZdd Zd d Zd d ZdS))absolute_import) FeedParserN) specifiers)version) pkg_resources) exceptionscCs>|dkr dStj|}tjdjtttjdd}||kS)aG Check if the python version in use match the `requires_python` specifier. Returns `True` if the version of python in use matches the requirement. Returns `False` if the version of python in use does not matches the requirement. Raises an InvalidSpecifier if `requires_python` have an invalid format. NT.) rZ SpecifierSetrparsejoinmapstrsys version_info)requires_pythonZrequires_python_specifierZpython_versionr/usr/lib/python3.6/packaging.pycheck_requires_pythons   rcCs8t|tjr |jdr |jdS|jdr4|jdSdS)NZMETADATAzPKG-INFO) isinstancerZDistInfoDistributionZ has_metadata get_metadata)distrrrr%s     rcCst|}t}|j||j}|jd}y8t|s`tjd|j|dj t t t j ddfWn8tjk r}ztjd|j||fdSd}~XnXdS)NzRequires-Pythonz4%s requires Python '%s' but the running Python is %srr z7Package %s has an invalid Requires-Python entry %s - %s)rrZfeedclosegetrrZUnsupportedPythonVersionZ project_namer r r rrrZInvalidSpecifierloggerZwarning)rZmetadataZ feed_parserZ pkg_info_dictrerrrcheck_dist_requires_python-s"  $r)Z __future__rZ email.parserrZloggingrZpip._vendor.packagingrrZ pip._vendorrZpiprZ getLogger__name__rrrrrrrrs       __pycache__/build.cpython-36.opt-1.pyc000064400000002420147221650610013442 0ustar003 . g @s<ddlmZddlZddlZddlmZGdddeZdS))absolute_importN)rmtreec@s6eZdZd ddZddZddZdd Zd d ZdS) BuildDirectoryNcCsL|dkr|dkrd}|dkr)format __class____name__r )r r r r__repr__szBuildDirectory.__repr__cCs|jS)N)r )r r r r __enter__"szBuildDirectory.__enter__cCs |jdS)N)cleanup)r excvaluetbr r r__exit__%szBuildDirectory.__exit__cCs|jrt|jdS)N)r rr )r r r rr(szBuildDirectory.cleanup)NN)r __module__ __qualname__rrrrrr r r rr s  r) Z __future__rZos.pathrr Z pip.utilsrobjectrr r r rs  __pycache__/ui.cpython-36.opt-1.pyc000064400000022441147221650610012765 0ustar003 . gM-@sddlmZddlmZddlZddlZddlmZmZmZddlZddl Z ddl Z ddl m Z ddl mZddlmZddlmZdd lmZmZdd lmZmZmZdd lmZydd lmZWnek rdZYnXe jeZ d dZ!e!eeZ"Gddde#Z$Gddde#Z%Gddde#Z&Gddde&e$e%e"Z'Gddde&e$e%eeZ(e j)ddZ*Gddde#Z+Gddde#Z,Gdd d e#Z-e j)d!d"Z.dS)#)absolute_import)divisionN)signalSIGINTdefault_int_handler)WINDOWS) format_size)get_indentation)six)BarIncrementalBar) WritelnMixin HIDE_CURSOR SHOW_CURSOR)Spinner)coloramac Cst|jdd}|s|St|dtjt|dtjg}|tt|dg7}ytjj|j|Wntk rv|SX|SdS)NencodingZ empty_fillZfillphases)getattrfiler Z text_typelistjoinencodeUnicodeEncodeError)Z preferredZfallbackrZ charactersr/usr/lib/python3.6/ui.py_select_progress_classsrcs4eZdZdZfddZfddZddZZS)InterruptibleMixina Helper to ensure that self.finish() gets called on keyboard interrupt. This allows downloads to be interrupted without leaving temporary state (like hidden cursors) behind. This class is similar to the progress library's existing SigIntMixin helper, but as of version 1.2, that helper has the following problems: 1. It calls sys.exit(). 2. It discards the existing SIGINT handler completely. 3. It leaves its own handler in place even after an uninterrupted finish, which will have unexpected delayed effects if the user triggers an unrelated keyboard interrupt some time after a progress-displaying download has already completed, for example. cs4tt|j||tt|j|_|jdkr0t|_dS)z= Save the original SIGINT handler for later. N)superr__init__rr handle_sigintoriginal_handlerr)selfargskwargs) __class__rrrNs zInterruptibleMixin.__init__cstt|jtt|jdS)z Restore the original SIGINT handler after finishing. This should happen regardless of whether the progress display finishes normally, or gets interrupted. N)rrfinishrrr!)r")r%rrr&^szInterruptibleMixin.finishcCs|j|j||dS)z Call self.finish() before delegating to the original SIGINT handler. This handler should only be in place while the progress display is active. N)r&r!)r"Zsignumframerrrr hsz InterruptibleMixin.handle_sigint)__name__ __module__ __qualname____doc__rr&r __classcell__rr)r%rr<s  rcsJeZdZfddZeddZeddZeddZd d d ZZ S) DownloadProgressMixincs,tt|j||dtd|j|_dS)N )rr-rr message)r"r#r$)r%rrruszDownloadProgressMixin.__init__cCs t|jS)N)rindex)r"rrr downloadedysz DownloadProgressMixin.downloadedcCs |jdkrdStd|jdS)Ngz...z/s)Zavgr)r"rrrdownload_speed}s z$DownloadProgressMixin.download_speedcCs|jrd|jSdS)Nzeta %s)ZetaZeta_td)r"rrr pretty_etas z DownloadProgressMixin.pretty_etar3ccs*x|D]}|V|j|qW|jdS)N)nextr&)r"itnxrrriters zDownloadProgressMixin.iter)r3) r(r)r*rpropertyr2r4r6r;r,rr)r%rr-ss     r-cseZdZfddZZS) WindowsMixincs\trjrd_ttj||trXtrXtjj_fddj_fddj_ dS)NFcs jjjS)N)rwrappedisattyr)r"rrsz'WindowsMixin.__init__..cs jjjS)N)rr>flushr)r"rrr@s) rZ hide_cursorrr=rrZ AnsiToWin32rr?rA)r"r#r$)r%)r"rrs zWindowsMixin.__init__)r(r)r*rr,rr)r%rr=sr=c@seZdZejZdZdZdS)DownloadProgressBarz %(percent)d%%z0%(downloaded)s %(download_speed)s %(pretty_eta)sN)r(r)r*sysstdoutrr0suffixrrrrrBsrBc@s&eZdZejZdZddZddZdS)DownloadProgressSpinnerz!%(downloaded)s %(download_speed)scCs"t|dstj|j|_t|jS)N_phaser)hasattr itertoolscyclerrGr7)r"rrr next_phases z"DownloadProgressSpinner.next_phasecCsN|j|}|j}|j|}dj||r*dnd||r6dnd|g}|j|dS)Nr5r.)r0rKrErZwriteln)r"r0ZphaserElinerrrupdates    zDownloadProgressSpinner.updateN) r(r)r*rCrDrrErKrMrrrrrFsrFc csRtr dVnB|j s$tjtjkr,dVn"|jtz dVWd|jtXdS)N) rr?loggergetEffectiveLevelloggingINFOwriterr)rrrr hidden_cursors  rSc@s$eZdZddZddZddZdS) RateLimitercCs||_d|_dS)Nr)_min_update_interval_seconds _last_update)r"min_update_interval_secondsrrrrszRateLimiter.__init__cCstj}||j}||jkS)N)timerVrU)r"ZnowZdeltarrrreadys zRateLimiter.readycCstj|_dS)N)rXrV)r"rrrresetszRateLimiter.resetN)r(r)r*rrYrZrrrrrTsrTc@s.eZdZd ddZddZdd Zd d ZdS) InteractiveSpinnerN-\|/?cCs\||_|dkrtj}||_t||_d|_tj||_ |jj dt |jdd|_ dS)NFr.z ... r) _messagerCrD_filerT _rate_limiter _finishedrIrJ _spin_cyclerRr _width)r"r0rZ spin_charsrWrrrrs  zInteractiveSpinner.__init__cCsRd|j}|jj|d|j||jj|t||_|jj|jjdS)Nr.)rcr_rRlenrAr`rZ)r"statusZbackuprrr_write s     zInteractiveSpinner._writecCs,|jr dS|jjsdS|jt|jdS)N)rar`rYrgr7rb)r"rrrspins  zInteractiveSpinner.spincCs4|jr dS|j||jjd|jjd|_dS)N T)rargr_rRrA)r" final_statusrrrr&s    zInteractiveSpinner.finish)Nr\r])r(r)r*rrgrhr&rrrrr[s   r[c@s.eZdZd ddZddZddZdd Zd S) NonInteractiveSpinner<cCs$||_d|_t||_|jddS)NFZstarted)r^rarTr`_update)r"r0rWrrrr*s zNonInteractiveSpinner.__init__cCs|jjtjd|j|dS)Nz%s: %s)r`rZrNinfor^)r"rfrrrrm0s zNonInteractiveSpinner._updatecCs&|jr dS|jjsdS|jddS)Nzstill running...)rar`rYrm)r"rrrrh5s  zNonInteractiveSpinner.spincCs$|jr dS|jd|fd|_dS)Nzfinished with status '%s'T)rarm)r"rjrrrr&<szNonInteractiveSpinner.finishN)rl)r(r)r*rrmrhr&rrrrrk)s rkccstjjr"tjtjkr"t|}nt|}y t tj |VWdQRXWn>t k rj|j dYn*t k r|j dYn X|j ddS)NZcancelederrordone) rCrDr?rNrOrPrQr[rkrSKeyboardInterruptr& Exception)r0Zspinnerrrr open_spinnerCs    rs)/Z __future__rrrIrCrrrrX contextlibrPZ pip.compatrZ pip.utilsrZpip.utils.loggingr Z pip._vendorr Zpip._vendor.progress.barr r Zpip._vendor.progress.helpersr rrZpip._vendor.progress.spinnerrrrrZ getLoggerr(rNrZ_BaseBarobjectrr-r=rBrFcontextmanagerrSrTr[rkrsrrrrsB          7 !0__pycache__/logging.cpython-36.pyc000064400000007447147221650610013050 0ustar003 . g @sddlmZddlZddlZddlZddlZy ddlZWnek rTddlZYnXddl m Z ddl m Z yddl mZWnek rdZYnXejZde_ejdddZd d ZGd d d ejZd dZGdddejZGdddejjZGdddejZdS))absolute_importN)WINDOWS) ensure_dir)coloramac cs.tj|7_z dVWdtj|8_XdS)zv A context manager which will cause the log output to be indented for any log messages emitted inside it. N) _log_state indentation)Znumr /usr/lib/python3.6/logging.py indent_logs r cCs ttddS)Nrr)getattrrr r r r get_indentation)sr c@seZdZddZdS)IndentingFormattercCs,tjj||}djdd|jdD}|S)z Calls the standard formatter, but will indent all of the log messages by our current indentation level. cSsg|]}dt|qS) )r ).0liner r r 6sz-IndentingFormatter.format..T)logging Formatterformatjoin splitlines)selfrecordZ formattedr r r r/s zIndentingFormatter.formatN)__name__ __module__ __qualname__rr r r r r-srcsfdd}|S)Ncsdjt|tjjgS)Nr)rlistrZStyleZ RESET_ALL)Zinp)colorsr r wrapped=sz_color_wrap..wrappedr )rr r )rr _color_wrap<s r!c@sTeZdZer2ejeejjfej eejj fgZ ngZ dddZ ddZ ddZdS) ColorizedStreamHandlerNcCs(tjj||tr$tr$tj|j|_dS)N)r StreamHandler__init__rr AnsiToWin32stream)rr&r r r r$NszColorizedStreamHandler.__init__cCsRtsdSt|jtjs|jn|jj}t|dr:|jr:dStjj ddkrNdSdS)NFisattyTZTERMZANSI) r isinstancer&r%r hasattrr'osenvironget)rZ real_streamr r r should_colorTsz#ColorizedStreamHandler.should_colorcCsBtjj||}|jr>x&|jD]\}}|j|kr||}PqW|S)N)rr#rr-COLORSlevelno)rrmsglevelZcolorr r r ris zColorizedStreamHandler.format)N)rrrrrZERRORr!ZForeZREDZWARNINGZYELLOWr.r$r-rr r r r r"Bs r"c@seZdZddZdS)BetterRotatingFileHandlercCs ttjj|jtjjj|S)N) rr*pathdirnameZ baseFilenamerhandlersRotatingFileHandler_open)rr r r r7wszBetterRotatingFileHandler._openN)rrrr7r r r r r2usr2c@seZdZddZddZdS)MaxLevelFiltercCs ||_dS)N)r1)rr1r r r r$~szMaxLevelFilter.__init__cCs |j|jkS)N)r/r1)rrr r r filterszMaxLevelFilter.filterN)rrrr$r9r r r r r8|sr8)r) Z __future__r contextlibrZlogging.handlersr*Z threading ImportErrorZdummy_threadingZ pip.compatrZ pip.utilsrZ pip._vendorr ExceptionZlocalrrcontextmanagerr r rrr!r#r"r5r6r2ZFilterr8r r r r s0      3__pycache__/setuptools_build.cpython-36.pyc000064400000000464147221650610015012 0ustar003 . g@sdZdS)zimport setuptools, tokenize;__file__=%r;f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))N)ZSETUPTOOLS_SHIMrr&/usr/lib/python3.6/setuptools_build.pys__pycache__/setuptools_build.cpython-36.opt-1.pyc000064400000000464147221650610015751 0ustar003 . g@sdZdS)zimport setuptools, tokenize;__file__=%r;f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))N)ZSETUPTOOLS_SHIMrr&/usr/lib/python3.6/setuptools_build.pys__pycache__/__init__.cpython-36.opt-1.pyc000064400000053713147221650610014115 0ustar003 . gyk@sddlmZddlmZddlZddlZddlZddlZddlZ ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlmZddlmZmZmZddlmZmZmZmZmZmZddl m!Z!ddl"m#Z#dd l$m%Z%dd l&m'Z'e%r dd lm(Z)n dd lm)Z)d ddddddddddddddddddd d!d"d#d$gZ*e j+e,Z-dzZ.d{Z/d|Z0d}Z1e0e.e1e/Z2e0e1Z3yddl4Z4e3e.7Z3Wn e5k re-j6d1YnXyddl7Z7e3e/7Z3Wn e5k re-j6d2YnXd3d4Z8d5d!Z9d6dZ:e'd7d8d9d~d;d Z;ddZ=dd@dZ>dAdBZ?dCdZ@dDdZAdEdZBdFdZCdGdZDejEfdHdIZFdJdZGdKdZHddMdZIdNdZJdOdZKdPdQZLdRdSZMdTdUZNdVdWZOdXdYZPdZd[ZQdLedLd:d:fd\d]ZRd^d_ZSd`daZTdbdZUdcddZVddedZWdfdZXdgdZYddidZZdjdkZ[dldmZ\Gdndodoe]Z^Gdpdqdqe)Z_ej`drdsZadtd ZbGdudvdve]Zcddwd$ZddxdyZedS))absolute_import)dequeN)InstallationError)console_to_str expanduser stdlib_pkgs) site_packages user_siterunning_under_virtualenvvirtualenv_no_globalwrite_delete_marker_filedistutils_scheme) pkg_resources)input)PY2)retry)BytesIO)StringIOrmtree display_path backup_dirasksplitext format_sizeis_installable_dir is_svn_page file_contentssplit_leading_dirhas_leading_dirnormalize_pathrenamesget_terminal_sizeget_prog unzip_file untar_file unpack_filecall_subprocesscaptured_stdout ensure_dirARCHIVE_EXTENSIONSSUPPORTED_EXTENSIONSget_installed_version.tar.bz2.tbz.tar.xz.txz.tlz.tar.lz .tar.lzma.zip.whl.tar.gz.tgz.tarzbz2 module is not availablezlzma module is not availablec Os,yt|Stk r&|||YnXdS)N) __import__ ImportError)Zpkg_or_module_stringZ ExceptionTypeargskwargsr</usr/lib/python3.6/__init__.pyimport_or_raiseIsr>cCsDytj|Wn0tk r>}z|jtjkr.WYdd}~XnXdS)z os.path.makedirs without EEXIST.N)osmakedirsOSErrorerrnoZEEXIST)pather<r<r=r(Ps  c CsDy$tjjtjddkr"dtjSWntttfk r>YnXdS)Nr __main__.py-cz %s -m pipZpip)rErF) r?rCbasenamesysargv executableAttributeError TypeError IndexErrorr<r<r<r=r"Ys i i)Zstop_max_delayZ wait_fixedFcCstj||tddS)N) ignore_errorsonerror)shutilrrmtree_errorhandler)dirrNr<r<r=rcscCs2tj|jtj@r,tj|tj||dSdS)zOn Windows, the files in .svn are read-only, so when rmtree() tries to remove them, an exception is thrown. We catch that here, remove the read-only attribute, and hopefully continue without problems.N)r?statst_modeS_IREADchmodS_IWRITE)funcrCexc_infor<r<r=rQis rQcCsttjjtjj|}tjddkrB|jtjd}|jtj d}|j tj tjj rpd|t tj d}|S)zTGives the display value for a given path, making it relative to cwd if possible.rreplace.N)r?rCnormcaseabspathrH version_infodecodegetfilesystemencodingencodegetdefaultencoding startswithgetcwdseplen)rCr<r<r=rxs.bakcCs:d}|}x(tjj||r0|d7}|t|}q W||S)z\Figure out the name of a directory to back up the given dir to (adding .bak, .bak2, etc))r?rCexistsstr)rRextn extensionr<r<r=rs cCs2x&tjjddjD]}||kr|SqWt||S)NZPIP_EXISTS_ACTION)r?environgetsplitr)messageoptionsactionr<r<r=ask_path_existssrvcCsZxTtjjdrtd|t|}|jj}||krNtd|dj|fq|SqWdS)z@Ask the message interactively, with the given possible responsesZ PIP_NO_INPUTz7No input was expected ($PIP_NO_INPUT set); question: %sz[^<]*Revision \d+:z#Powered by (?:]*?>)?Subversion)researchI)Zhtmlr<r<r=rs c Cs$t|d}|jjdSQRXdS)Nrbzutf-8)openreadr`)filenamefpr<r<r=rs ccs x|j|}|sP|VqWdS)z7Yield pieces of data from a file-like object until EOF.N)r)filesizechunkr<r<r= read_chunkss  rcCsh|jdjd}d|krHd|kr4|jd|jdkss rcCs8x2tjD](}tjj||jd}tjj|rdSqWdS)z$Is distribution an editable install?z .egg-linkTF)rHrCr?r{ project_namer)rZ path_itemegg_linkr<r<r=dist_is_editableHs   rcsl|r tndd|r ddndd|r6ddndd|rHtnd d fd d tjDS) a Return a list of installed Distribution objects. If ``local_only`` is True (default), only return installations local to the current virtualenv, if in a virtualenv. ``skip`` argument is an iterable of lower-case project names to ignore; defaults to stdlib_pkgs If ``editables`` is False, don't report editables. If ``editables_only`` is True , only report editables. If ``user_only`` is True , only report installations in the user site directory. cSsdS)NTr<)dr<r<r= local_testjsz/get_installed_distributions..local_testcSsdS)NTr<)rr<r<r= editable_testnsz2get_installed_distributions..editable_testcSs t| S)N)r)rr<r<r=rqscSst|S)N)r)rr<r<r=editables_only_testusz8get_installed_distributions..editables_only_testcSsdS)NTr<)rr<r<r=rxscSsdS)NTr<)rr<r<r= user_test~sz.get_installed_distributions..user_testcs:g|]2}|r|jkr|r|r|r|qSr<)key).0r)rrrskiprr<r= s  z/get_installed_distributions..)rrr working_set)Z local_onlyrZinclude_editablesZeditables_onlyZ user_onlyr<)rrrrrr=get_installed_distributionsQs  rcCsg}tr6tr|jtqN|jttrN|jtntrD|jt|jtx0|D](}tjj||jd}tjj |rT|SqTWdS)a Return the path for the .egg-link file if it exists, otherwise, None. There's 3 scenarios: 1) not in a virtualenv try to find in site.USER_SITE, then site_packages 2) in a no-global virtualenv try to find in site_packages 3) in a yes-global virtualenv try to find in site_packages, then site.USER_SITE (don't look in global location) For #1 and #3, there could be odd cases, where there's an egg-link in 2 locations. This method will just return the first one found. z .egg-linkN) r r appendrr r?rCr{rr)rZsitesZsiteZegglinkr<r<r= egg_link_paths       rcCst|}|r|S|jS)z Get the site-packages location of this distribution. Generally this is dist.location, except in the case of develop-installed packages, where dist.location is the source code location, and we want to know where the egg-link file is. )rlocation)rrr<r<r=rsrc Csdd}|dp|dp|d}|sZy(tjtjtj}||}tj|Wn YnX|sztjjddtjjdd f}t|dt|dfS) zlReturns a tuple (x, y) representing the width(x) and the height(x) in characters of the terminal window.c SsPy4ddl}ddl}ddl}|jd|j||jd}Wn dS|dkrLdS|S)NrZhhZ1234)rr)fcntltermiosstructunpackZioctlZ TIOCGWINSZ)fdrrrcrr<r<r= ioctl_GWINSZsz'get_terminal_size..ioctl_GWINSZrrirZZLINESZCOLUMNSP)r?rctermidO_RDONLYcloserprqint)rrrr<r<r=r!scCstjd}tj||S)zBGet the current umask which involves having to set it temporarily.r)r?umask)maskr<r<r= current_umasks  rc Cst|t|d}ztj|dd}t|jo0|}x|jD]}|j}|j|}|} |rdt |d} t j j || } t j j | } | jds| jdrt| qd}n8|jjtrRd}n$|jjdrfd}ntjd|d }tj||}zxt d d |j D}xZ|j D]L}|j }|d krq|rt |d }t jj||}|jrt|q|jrDy|j||Wn8tk r@}ztjd||j |wWYdd}~XnXqy|j|} Wn<ttfk r}ztjd||j |wWYdd}~XnXtt jj|t|d} tj| | WdQRX| j|j|||jd@rt j|dtdBqWWd|jXdS)a Untar the file (with path `filename`) to the destination `location`. All files are written based on system defaults and umask (i.e. permissions are not preserved), except that regular file members with any execute permissions (user, group, or world) have "chmod +x" applied after being written. Note that for windows, any execute changes using os.chmod are no-ops per the python docs. z.gzz.tgzzr:gzzr:bz2zr:xzz.tarrz-Cannot determine compression type for file %szr:*cSsg|]}|jdkr|jqS)pax_global_header)r)rmemberr<r<r=r(szuntar_file..rriz/In the tar file %s the member %s is invalid: %sNrri)r(ryrBZ2_EXTENSIONS XZ_EXTENSIONSloggerwarningtarfilerrZ getmembersrrr?rCr{r~ZissymZ_extract_memberrwZ extractfileKeyErrorrKrrPZ copyfileobjrutimerrVr) rrrZtarrrrrCexcrZdestfpr<r<r=r$ s`          cCstjj|}|dks,|jjts,tj|rDt|||jd dn|dkslt j |sl|jjt t t rxt||nX|r|jdrtt|rddlm}|d|jj|ntjd |||td |dS) Nzapplication/zipz.whl)rzapplication/x-gzipz text/htmlr) Subversionzsvn+zZCannot unpack file %s (downloaded from %s, content-type: %s); cannot detect archive formatz%Cannot determine archive format of %s)r?rCrryrZIP_EXTENSIONSrZ is_zipfiler#rZ is_tarfileTAR_EXTENSIONSrrr$rdrrZpip.vcs.subversionrZurlrrcriticalr)rrZ content_typelinkrr<r<r=r%Ys,       raisecCs,|r d}ntj}|dkrng}xF|D]>} d| ksFd| ksFd| ksFd| krVd| jdd} |j| q"Wdj|}tjd|tjj } |r| j |ytj |tj d||| d} Wn2t k r} ztjd | |WYdd} ~ XnX|dk rNg} x\t| jj}|sP|j}| j|dtjtjkr:tj|q|dk r|jqW| j|dk r~| jrt|jd n |jd | jr|d krtjtjkr| rtjd |tjdj| dtd|| j|fn:|dkrtjd|| j|n|dkrntdt||s(dj| SdS)N  "'z"%s"z\"zRunning command %s)stderrstdinstdoutcwdenvz#Error %s while executing command %serrordonerz Complete output from command %s:roz) ----------------------------------------z,Command "%s" failed with error code %s in %swarnz$Command "%s" had error code %s in %signorezInvalid value: on_returncode=%s) subprocessPIPEr[rr{rdebugr?rpcopyupdatePopenZSTDOUTrwrrrreadlinerstripZgetEffectiveLevel std_loggingDEBUGZspinwait returncodeZfinishrrr ValueErrorrepr)cmdZ show_stdoutrZ on_returncodeZ command_descZ extra_environZspinnerrZ cmd_partspartrprocrZ all_outputliner<r<r=r&zsz                  cCsht|d}|j}WdQRXdtjddg}x4|D],}y|j|}Wntk r\w4YnXPq4W|S)aRReturn the contents of *filename*. Try to decode the file contents with utf-8, the preferred system encoding (e.g., cp1252 on some Windows machines), and latin1, in that order. Decoding a byte string with latin1 will never raise an error. In the worst case, the returned string will contain some garbage characters. rNzutf-8Flatin1)rrlocalegetpreferredencodingr`UnicodeDecodeError)rrrZ encodingsencr<r<r=read_text_files  r cCstj|t|dS)N)r?r@r )Z build_dirr<r<r=_make_build_dirs rc@s(eZdZdZddZddZddZdS) FakeFilezQWrap a list of lines in an object with readline() to make ConfigParser happy.cCsdd|D|_dS)Ncss|] }|VqdS)Nr<)rlr<r<r= sz$FakeFile.__init__..)_gen)selflinesr<r<r=__init__szFakeFile.__init__cCsDy*y t|jStk r&|jjSXWntk r>dSXdS)Nro)nextr NameError StopIteration)rr<r<r=rs zFakeFile.readlinecCs|jS)N)r)rr<r<r=__iter__szFakeFile.__iter__N)__name__ __module__ __qualname____doc__rrrr<r<r<r=rs rc@s$eZdZeddZeddZdS) StreamWrappercCs ||_|S)N) orig_stream)clsrr<r<r= from_streamszStreamWrapper.from_streamcCs|jjS)N)rencoding)rr<r<r=r"szStreamWrapper.encodingN)rrr classmethodr!propertyr"r<r<r<r=r s rc cs@tt|}tt|tj|ztt|VWdtt||XdS)zReturn a context manager used by captured_stdout/stdin/stderr that temporarily replaces the sys stream *stream_name* with a StringIO. Taken from Lib/support/__init__.py in the CPython repo. N)getattrrHsetattrrr!)Z stream_nameZ orig_stdoutr<r<r=captured_outputs  r'cCstdS)zCapture the output of sys.stdout: with captured_stdout() as stdout: print('hello') self.assertEqual(stdout.getvalue(), 'hello ') Taken from Lib/support/__init__.py in the CPython repo. r)r'r<r<r<r=r'(s c@s eZdZdZddZddZdS)cached_propertyzA property that is only computed once per instance and then replaces itself with an ordinary attribute. Deleting the attribute resets the property. Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 cCst|d|_||_dS)Nr)r%rrX)rrXr<r<r=r<s zcached_property.__init__cCs(|dkr |S|j|}|j|jj<|S)N)rX__dict__r)robjr valuer<r<r=__get__@szcached_property.__get__N)rrrrrr,r<r<r<r=r(4sr(cCs@tjj|}|dkrtj}n tj|}|j|}|r<|jSdS)zCGet the installed version of dist_name avoiding pkg_resources cacheN)rZ RequirementparseZ WorkingSetrversion)Z dist_nameZ lookup_dirsZreqrrr<r<r=r+Hs     cCst|dddS)zConsume an iterable at C speed.r)maxlenN)r)iteratorr<r<r=consume\sr1)r,r-)r.r/r0r1r2)r3r4)r5r6r7)F)rh)T)T)TNrNNN)N)fZ __future__r collectionsr contextlibrBior Zloggingrrr?rrPrSrrHrrZpip.exceptionsrZ pip.compatrrrZ pip.locationsrr r r r r Z pip._vendorrZpip._vendor.six.movesrZpip._vendor.sixrZpip._vendor.retryingrrr__all__Z getLoggerrrrrrrr)r*bz2r9rZlzmar>r(r"rrQrrrvrrrrrDEFAULT_BUFFER_SIZErrrrrr rrrrrrrrrr!rr#r$r%r&r robjectrrcontextmanagerr'r'r(r+r1r<r<r<r=s                            5% +L! _   __pycache__/glibc.cpython-36.pyc000064400000002503147221650610012466 0ustar003 . g{ @sPddlmZddlZddlZddlZddlZddZddZddZd d Z dS) )absolute_importNc CsPtjd}y |j}Wntk r(dSXtj|_|}t|tsL|jd}|S)z9Returns glibc version string, or None if not using glibc.Nascii) ctypesZCDLLgnu_get_libc_versionAttributeErrorZc_char_pZrestype isinstancestrdecode)Zprocess_namespacer version_strr /usr/lib/python3.6/glibc.pyglibc_version_string s    r cCsHtjd|}|s$tjd|tdSt|jd|koFt|jd|kS)Nz$(?P[0-9]+)\.(?P[0-9]+)z=Expected glibc version with 2 components major.minor, got: %sFmajorminor)rematchwarningswarnRuntimeWarningintgroup)r required_major minimum_minormr r r check_glibc_version#s  rcCst}|dkrdSt|||S)NF)r r)rrr r r r have_compatible_glibc3srcCs"t}|dkrtjSd|fSdS)NZglibc)r platformlibc_ver)Z glibc_versionr r r rKsr) Z __future__rrrrrr rrrr r r r s __pycache__/outdated.cpython-36.pyc000064400000011147147221650610013223 0ustar003 . ge@sddlmZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl mZmZddlmZddlmZmZddlmZmZdd lmZd ZejeZGd d d eZGd ddeZ ddZ!ddZ"ddZ#dS))absolute_importN)lockfile)version) total_secondsWINDOWS)PyPI)USER_CACHE_DIRrunning_under_virtualenv) ensure_dirget_installed_version)check_path_ownerz%Y-%m-%dT%H:%M:%SZc@seZdZddZddZdS)VirtualenvSelfCheckStatecCs\tjjtjd|_y&t|j}tj||_ WdQRXWnt t fk rVi|_ YnXdS)Nzpip-selfcheck.json) ospathjoinsysprefixstatefile_pathopenjsonloadstateIOError ValueError)self statefiler/usr/lib/python3.6/outdated.py__init__s  z!VirtualenvSelfCheckState.__init__c Cs:t|jd$}tj|jt|d|dddWdQRXdS)Nw) last_check pypi_versionT,:) sort_keys separators)r"r#)rrrdumpstrftimeSELFCHECK_DATE_FMT)rr! current_timerrrrsave$szVirtualenvSelfCheckState.saveN)__name__ __module__ __qualname__rr*rrrrr s r c@seZdZddZddZdS)GlobalSelfCheckStatecCsbtjjtd|_y,t|j}tj|tj |_ WdQRXWn t t t fk r\i|_ YnXdS)Nzselfcheck.json)rrrrrrrrrrrrrKeyError)rrrrrr3s   zGlobalSelfCheckState.__init__cCsttjj|jsdSttjj|jtj|jztjj|jrft |j}t j |}WdQRXni}|j t |d|tj<t |jd}t j||dddWdQRXWdQRXdS)N)r r!rTr"r#)r$r%)r"r#)r rrdirnamerr rZLockFileexistsrrrr'r(rrr&)rr!r)rrrrrr*=s  zGlobalSelfCheckState.saveN)r+r,r-rr*rrrrr.2s r.cCstr tStSdS)N)r r r.rrrrload_selfcheck_statefileXsr2c CsFddl}y"|jd}|jdo*d|jdkS|jk r@dSXdS)zChecks whether pip was installed by pip This is used not to display the upgrade message when pip is in fact installed by system package manager, such as dnf on Fedora. rNpipZ INSTALLERF) pkg_resourcesZget_distributionZ has_metadataZget_metadata_linesZDistributionNotFound)r4Zdistrrrpip_installed_by_pip_s  r5c CsFtd}|dkrdStj|}d}yt}tjj}d|jkrxd|jkrxtjj|jdt}t ||dkrx|jd}|dkr|j t j dd id }|j d d tt|jd tjdDd}|j||tj|}||kr|j|jkrtrtrd} nd} tjd||| Wn$tk r@tjdddYnXdS)zCheck for an update for pip. Limit the frequency of checks to once per week. State is stored either in the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix of the pip script path. r3Nr r!<ZAcceptzapplication/json)ZheaderscSsg|]}tj|js|qSr)packaging_versionparseZ is_prerelease).0vrrr sz%pip_version_check..Zreleases)keyz python -m pipzYou are using pip version %s, however version %s is available. You should consider upgrading via the '%s install --upgrade pip' command.z5There was an error checking the latest version of pipT)exc_infoi`'i: )r r9r:r2datetimeZutcnowrZstrptimer(rgetrZ pip_json_urlZraise_for_statussortedlistrr*Z base_versionr5rloggerZwarning Exceptiondebug) ZsessionZinstalled_versionZ pip_versionr!rr)r ZrespZremote_versionZpip_cmdrrrpip_version_checknsL        rJ)$Z __future__rrCrZloggingZos.pathrrZ pip._vendorrZpip._vendor.packagingrr9Z pip.compatrrZ pip.modelsrZ pip.locationsrr Z pip.utilsr r Zpip.utils.filesystemr r(Z getLoggerr+rGobjectr r.r2r5rJrrrrs&      &__pycache__/logging.cpython-36.opt-1.pyc000064400000007447147221650610014007 0ustar003 . g @sddlmZddlZddlZddlZddlZy ddlZWnek rTddlZYnXddl m Z ddl m Z yddl mZWnek rdZYnXejZde_ejdddZd d ZGd d d ejZd dZGdddejZGdddejjZGdddejZdS))absolute_importN)WINDOWS) ensure_dir)coloramac cs.tj|7_z dVWdtj|8_XdS)zv A context manager which will cause the log output to be indented for any log messages emitted inside it. N) _log_state indentation)Znumr /usr/lib/python3.6/logging.py indent_logs r cCs ttddS)Nrr)getattrrr r r r get_indentation)sr c@seZdZddZdS)IndentingFormattercCs,tjj||}djdd|jdD}|S)z Calls the standard formatter, but will indent all of the log messages by our current indentation level. cSsg|]}dt|qS) )r ).0liner r r 6sz-IndentingFormatter.format..T)logging Formatterformatjoin splitlines)selfrecordZ formattedr r r r/s zIndentingFormatter.formatN)__name__ __module__ __qualname__rr r r r r-srcsfdd}|S)Ncsdjt|tjjgS)Nr)rlistrZStyleZ RESET_ALL)Zinp)colorsr r wrapped=sz_color_wrap..wrappedr )rr r )rr _color_wrap<s r!c@sTeZdZer2ejeejjfej eejj fgZ ngZ dddZ ddZ ddZdS) ColorizedStreamHandlerNcCs(tjj||tr$tr$tj|j|_dS)N)r StreamHandler__init__rr AnsiToWin32stream)rr&r r r r$NszColorizedStreamHandler.__init__cCsRtsdSt|jtjs|jn|jj}t|dr:|jr:dStjj ddkrNdSdS)NFisattyTZTERMZANSI) r isinstancer&r%r hasattrr'osenvironget)rZ real_streamr r r should_colorTsz#ColorizedStreamHandler.should_colorcCsBtjj||}|jr>x&|jD]\}}|j|kr||}PqW|S)N)rr#rr-COLORSlevelno)rrmsglevelZcolorr r r ris zColorizedStreamHandler.format)N)rrrrrZERRORr!ZForeZREDZWARNINGZYELLOWr.r$r-rr r r r r"Bs r"c@seZdZddZdS)BetterRotatingFileHandlercCs ttjj|jtjjj|S)N) rr*pathdirnameZ baseFilenamerhandlersRotatingFileHandler_open)rr r r r7wszBetterRotatingFileHandler._openN)rrrr7r r r r r2usr2c@seZdZddZddZdS)MaxLevelFiltercCs ||_dS)N)r1)rr1r r r r$~szMaxLevelFilter.__init__cCs |j|jkS)N)r/r1)rrr r r filterszMaxLevelFilter.filterN)rrrr$r9r r r r r8|sr8)r) Z __future__r contextlibrZlogging.handlersr*Z threading ImportErrorZdummy_threadingZ pip.compatrZ pip.utilsrZ pip._vendorr ExceptionZlocalrrcontextmanagerr r rrr!r#r"r5r6r2ZFilterr8r r r r s0      3__pycache__/__init__.cpython-36.pyc000064400000053770147221650610013161 0ustar003 . gyk@sddlmZddlmZddlZddlZddlZddlZddlZ ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlmZddlmZmZmZddlmZmZmZmZmZmZddl m!Z!ddl"m#Z#dd l$m%Z%dd l&m'Z'e%r dd lm(Z)n dd lm)Z)d ddddddddddddddddddd d!d"d#d$gZ*e j+e,Z-dzZ.d{Z/d|Z0d}Z1e0e.e1e/Z2e0e1Z3yddl4Z4e3e.7Z3Wn e5k re-j6d1YnXyddl7Z7e3e/7Z3Wn e5k re-j6d2YnXd3d4Z8d5d!Z9d6dZ:e'd7d8d9d~d;d Z;ddZ=dd@dZ>dAdBZ?dCdZ@dDdZAdEdZBdFdZCdGdZDejEfdHdIZFdJdZGdKdZHddMdZIdNdZJdOdZKdPdQZLdRdSZMdTdUZNdVdWZOdXdYZPdZd[ZQdLedLd:d:fd\d]ZRd^d_ZSd`daZTdbdZUdcddZVddedZWdfdZXdgdZYddidZZdjdkZ[dldmZ\Gdndodoe]Z^Gdpdqdqe)Z_ej`drdsZadtd ZbGdudvdve]Zcddwd$ZddxdyZedS))absolute_import)dequeN)InstallationError)console_to_str expanduser stdlib_pkgs) site_packages user_siterunning_under_virtualenvvirtualenv_no_globalwrite_delete_marker_filedistutils_scheme) pkg_resources)input)PY2)retry)BytesIO)StringIOrmtree display_path backup_dirasksplitext format_sizeis_installable_dir is_svn_page file_contentssplit_leading_dirhas_leading_dirnormalize_pathrenamesget_terminal_sizeget_prog unzip_file untar_file unpack_filecall_subprocesscaptured_stdout ensure_dirARCHIVE_EXTENSIONSSUPPORTED_EXTENSIONSget_installed_version.tar.bz2.tbz.tar.xz.txz.tlz.tar.lz .tar.lzma.zip.whl.tar.gz.tgz.tarzbz2 module is not availablezlzma module is not availablec Os,yt|Stk r&|||YnXdS)N) __import__ ImportError)Zpkg_or_module_stringZ ExceptionTypeargskwargsr</usr/lib/python3.6/__init__.pyimport_or_raiseIsr>cCsDytj|Wn0tk r>}z|jtjkr.WYdd}~XnXdS)z os.path.makedirs without EEXIST.N)osmakedirsOSErrorerrnoZEEXIST)pather<r<r=r(Ps  c CsDy$tjjtjddkr"dtjSWntttfk r>YnXdS)Nr __main__.py-cz %s -m pipZpip)rErF) r?rCbasenamesysargv executableAttributeError TypeError IndexErrorr<r<r<r=r"Ys i i)Zstop_max_delayZ wait_fixedFcCstj||tddS)N) ignore_errorsonerror)shutilrrmtree_errorhandler)dirrNr<r<r=rcscCs2tj|jtj@r,tj|tj||dSdS)zOn Windows, the files in .svn are read-only, so when rmtree() tries to remove them, an exception is thrown. We catch that here, remove the read-only attribute, and hopefully continue without problems.N)r?statst_modeS_IREADchmodS_IWRITE)funcrCexc_infor<r<r=rQis rQcCsttjjtjj|}tjddkrB|jtjd}|jtj d}|j tj tjj rpd|t tj d}|S)zTGives the display value for a given path, making it relative to cwd if possible.rreplace.N)r?rCnormcaseabspathrH version_infodecodegetfilesystemencodingencodegetdefaultencoding startswithgetcwdseplen)rCr<r<r=rxs.bakcCs:d}|}x(tjj||r0|d7}|t|}q W||S)z\Figure out the name of a directory to back up the given dir to (adding .bak, .bak2, etc))r?rCexistsstr)rRextn extensionr<r<r=rs cCs2x&tjjddjD]}||kr|SqWt||S)NZPIP_EXISTS_ACTION)r?environgetsplitr)messageoptionsactionr<r<r=ask_path_existssrvcCsZxTtjjdrtd|t|}|jj}||krNtd|dj|fq|SqWdS)z@Ask the message interactively, with the given possible responsesZ PIP_NO_INPUTz7No input was expected ($PIP_NO_INPUT set); question: %sz[^<]*Revision \d+:z#Powered by (?:]*?>)?Subversion)researchI)Zhtmlr<r<r=rs c Cs$t|d}|jjdSQRXdS)Nrbzutf-8)openreadr`)filenamefpr<r<r=rs ccs x|j|}|sP|VqWdS)z7Yield pieces of data from a file-like object until EOF.N)r)filesizechunkr<r<r= read_chunkss  rcCsh|jdjd}d|krHd|kr4|jd|jdkss rcCs8x2tjD](}tjj||jd}tjj|rdSqWdS)z$Is distribution an editable install?z .egg-linkTF)rHrCr?r{ project_namer)rZ path_itemegg_linkr<r<r=dist_is_editableHs   rcsl|r tndd|r ddndd|r6ddndd|rHtnd d fd d tjDS) a Return a list of installed Distribution objects. If ``local_only`` is True (default), only return installations local to the current virtualenv, if in a virtualenv. ``skip`` argument is an iterable of lower-case project names to ignore; defaults to stdlib_pkgs If ``editables`` is False, don't report editables. If ``editables_only`` is True , only report editables. If ``user_only`` is True , only report installations in the user site directory. cSsdS)NTr<)dr<r<r= local_testjsz/get_installed_distributions..local_testcSsdS)NTr<)rr<r<r= editable_testnsz2get_installed_distributions..editable_testcSs t| S)N)r)rr<r<r=rqscSst|S)N)r)rr<r<r=editables_only_testusz8get_installed_distributions..editables_only_testcSsdS)NTr<)rr<r<r=rxscSsdS)NTr<)rr<r<r= user_test~sz.get_installed_distributions..user_testcs:g|]2}|r|jkr|r|r|r|qSr<)key).0r)rrrskiprr<r= s  z/get_installed_distributions..)rrr working_set)Z local_onlyrZinclude_editablesZeditables_onlyZ user_onlyr<)rrrrrr=get_installed_distributionsQs  rcCsg}tr6tr|jtqN|jttrN|jtntrD|jt|jtx0|D](}tjj||jd}tjj |rT|SqTWdS)a Return the path for the .egg-link file if it exists, otherwise, None. There's 3 scenarios: 1) not in a virtualenv try to find in site.USER_SITE, then site_packages 2) in a no-global virtualenv try to find in site_packages 3) in a yes-global virtualenv try to find in site_packages, then site.USER_SITE (don't look in global location) For #1 and #3, there could be odd cases, where there's an egg-link in 2 locations. This method will just return the first one found. z .egg-linkN) r r appendrr r?rCr{rr)rZsitesZsiteZegglinkr<r<r= egg_link_paths       rcCst|}|r|S|jS)z Get the site-packages location of this distribution. Generally this is dist.location, except in the case of develop-installed packages, where dist.location is the source code location, and we want to know where the egg-link file is. )rlocation)rrr<r<r=rsrc Csdd}|dp|dp|d}|sZy(tjtjtj}||}tj|Wn YnX|sztjjddtjjdd f}t|dt|dfS) zlReturns a tuple (x, y) representing the width(x) and the height(x) in characters of the terminal window.c SsPy4ddl}ddl}ddl}|jd|j||jd}Wn dS|dkrLdS|S)NrZhhZ1234)rr)fcntltermiosstructunpackZioctlZ TIOCGWINSZ)fdrrrcrr<r<r= ioctl_GWINSZsz'get_terminal_size..ioctl_GWINSZrrirZZLINESZCOLUMNSP)r?rctermidO_RDONLYcloserprqint)rrrr<r<r=r!scCstjd}tj||S)zBGet the current umask which involves having to set it temporarily.r)r?umask)maskr<r<r= current_umasks  rc Cst|t|d}ztj|dd}t|jo0|}x|jD]}|j}|j|}|} |rdt |d} t j j || } t j j | } | jds| jdrt| qd}n8|jjtrRd}n$|jjdrfd}ntjd|d }tj||}zxt d d |j D}xZ|j D]L}|j }|d krq|rt |d }t jj||}|jrt|q|jrDy|j||Wn8tk r@}ztjd||j |wWYdd}~XnXqy|j|} Wn<ttfk r}ztjd||j |wWYdd}~XnXtt jj|t|d} tj| | WdQRX| j|j|||jd@rt j|dtdBqWWd|jXdS)a Untar the file (with path `filename`) to the destination `location`. All files are written based on system defaults and umask (i.e. permissions are not preserved), except that regular file members with any execute permissions (user, group, or world) have "chmod +x" applied after being written. Note that for windows, any execute changes using os.chmod are no-ops per the python docs. z.gzz.tgzzr:gzzr:bz2zr:xzz.tarrz-Cannot determine compression type for file %szr:*cSsg|]}|jdkr|jqS)pax_global_header)r)rmemberr<r<r=r(szuntar_file..rriz/In the tar file %s the member %s is invalid: %sNrri)r(ryrBZ2_EXTENSIONS XZ_EXTENSIONSloggerwarningtarfilerrZ getmembersrrr?rCr{r~ZissymZ_extract_memberrwZ extractfileKeyErrorrKrrPZ copyfileobjrutimerrVr) rrrZtarrrrrCexcrZdestfpr<r<r=r$ s`          cCstjj|}|dks,|jjts,tj|rDt|||jd dn|dkslt j |sl|jjt t t rxt||nX|r|jdrtt|rddlm}|d|jj|ntjd |||td |dS) Nzapplication/zipz.whl)rzapplication/x-gzipz text/htmlr) Subversionzsvn+zZCannot unpack file %s (downloaded from %s, content-type: %s); cannot detect archive formatz%Cannot determine archive format of %s)r?rCrryrZIP_EXTENSIONSrZ is_zipfiler#rZ is_tarfileTAR_EXTENSIONSrrr$rdrrZpip.vcs.subversionrZurlrrcriticalr)rrZ content_typelinkrr<r<r=r%Ys,       raisecCs,|r d}ntj}|dkrng}xF|D]>} d| ksFd| ksFd| ksFd| krVd| jdd} |j| q"Wdj|}tjd|tjj } |r| j |ytj |tj d||| d} Wn2t k r} ztjd | |WYdd} ~ XnX|dk rNg} x\t| jj}|sP|j}| j|dtjtjkr:tj|q|dk r|jqW| j|dk r~| jrt|jd n |jd | jr|d krtjtjkr| rtjd |tjdj| dtd|| j|fn:|dkrtjd|| j|n|dkrntdt||s(dj| SdS)N  "'z"%s"z\"zRunning command %s)stderrstdinstdoutcwdenvz#Error %s while executing command %serrordonerz Complete output from command %s:roz) ----------------------------------------z,Command "%s" failed with error code %s in %swarnz$Command "%s" had error code %s in %signorezInvalid value: on_returncode=%s) subprocessPIPEr[rr{rdebugr?rpcopyupdatePopenZSTDOUTrwrrrreadlinerstripZgetEffectiveLevel std_loggingDEBUGZspinwait returncodeZfinishrrr ValueErrorrepr)cmdZ show_stdoutrZ on_returncodeZ command_descZ extra_environZspinnerrZ cmd_partspartrprocrZ all_outputliner<r<r=r&zsz                  cCsxt|d}|j}WdQRXdtjddg}x4|D],}y|j|}Wntk r\w4YnXPq4Wt|tkstt|S)aRReturn the contents of *filename*. Try to decode the file contents with utf-8, the preferred system encoding (e.g., cp1252 on some Windows machines), and latin1, in that order. Decoding a byte string with latin1 will never raise an error. In the worst case, the returned string will contain some garbage characters. rNzutf-8Flatin1) rrlocalegetpreferredencodingr`UnicodeDecodeErrortyper}AssertionError)rrrZ encodingsencr<r<r=read_text_files  rcCstj|t|dS)N)r?r@r )Z build_dirr<r<r=_make_build_dirs rc@s(eZdZdZddZddZddZdS) FakeFilezQWrap a list of lines in an object with readline() to make ConfigParser happy.cCsdd|D|_dS)Ncss|] }|VqdS)Nr<)rlr<r<r= sz$FakeFile.__init__..)_gen)selflinesr<r<r=__init__szFakeFile.__init__cCsDy*y t|jStk r&|jjSXWntk r>dSXdS)Nro)nextr NameError StopIteration)rr<r<r=rs zFakeFile.readlinecCs|jS)N)r)rr<r<r=__iter__szFakeFile.__iter__N)__name__ __module__ __qualname____doc__rrrr<r<r<r=rs rc@s$eZdZeddZeddZdS) StreamWrappercCs ||_|S)N) orig_stream)clsr!r<r<r= from_streamszStreamWrapper.from_streamcCs|jjS)N)r!encoding)rr<r<r=r$szStreamWrapper.encodingN)rrr classmethodr#propertyr$r<r<r<r=r  s r c cs@tt|}tt|tj|ztt|VWdtt||XdS)zReturn a context manager used by captured_stdout/stdin/stderr that temporarily replaces the sys stream *stream_name* with a StringIO. Taken from Lib/support/__init__.py in the CPython repo. N)getattrrHsetattrr r#)Z stream_nameZ orig_stdoutr<r<r=captured_outputs  r)cCstdS)zCapture the output of sys.stdout: with captured_stdout() as stdout: print('hello') self.assertEqual(stdout.getvalue(), 'hello ') Taken from Lib/support/__init__.py in the CPython repo. r)r)r<r<r<r=r'(s c@s eZdZdZddZddZdS)cached_propertyzA property that is only computed once per instance and then replaces itself with an ordinary attribute. Deleting the attribute resets the property. Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 cCst|d|_||_dS)Nr)r'rrX)rrXr<r<r=r<s zcached_property.__init__cCs(|dkr |S|j|}|j|jj<|S)N)rX__dict__r)robjr"valuer<r<r=__get__@szcached_property.__get__N)rrrrrr.r<r<r<r=r*4sr*cCs@tjj|}|dkrtj}n tj|}|j|}|r<|jSdS)zCGet the installed version of dist_name avoiding pkg_resources cacheN)rZ RequirementparseZ WorkingSetrversion)Z dist_nameZ lookup_dirsZreqrrr<r<r=r+Hs     cCst|dddS)zConsume an iterable at C speed.r)maxlenN)r)iteratorr<r<r=consume\sr3)r,r-)r.r/r0r1r2)r3r4)r5r6r7)F)rh)T)T)TNrNNN)N)fZ __future__r collectionsr contextlibrBior Zloggingrrr?rrPrSrrHrrZpip.exceptionsrZ pip.compatrrrZ pip.locationsrr r r r r Z pip._vendorrZpip._vendor.six.movesrZpip._vendor.sixrZpip._vendor.retryingrrr__all__Z getLoggerrrrrrrr)r*bz2r9rZlzmar>r(r"rrQrrrvrrrrrDEFAULT_BUFFER_SIZErrrrrr rrrrrrrrrr!rr#r$r%r&rrobjectrr contextmanagerr)r'r*r+r3r<r<r<r=s                            5% +L! _   __pycache__/deprecation.cpython-36.pyc000064400000003255147221650610013710 0ustar003 . g@sdZddlmZddlZddlZGdddeZGdddeZGdd d eZ Gd d d eeZ Gd d d eZ da dddZ ddZdS)zN A module that implements tooling to enable easy warnings about deprecations. )absolute_importNc@s eZdZdS)PipDeprecationWarningN)__name__ __module__ __qualname__rr!/usr/lib/python3.6/deprecation.pyr src@s eZdZdS)PendingN)rrrrrrrr sr c@s eZdZdS)RemovedInPip10WarningN)rrrrrrrr sr c@s eZdZdS)RemovedInPip11WarningN)rrrrrrrr sr c@s eZdZdS)Python26DeprecationWarningN)rrrrrrrr sr cCsx|dk r$tdk rtt||||||nPt|trbtjd}d|}t|trV|j|qt|j|nt||||||dS)Nzpip.deprecationszDEPRECATION: %s)_warnings_showwarning issubclassrloggingZ getLoggerr Zwarningerror)messagecategoryfilenamelinenofilelineZloggerZ log_messagerrr _showwarning$s     rcCs(tjdtddtdkr$tjatt_dS)NdefaultT)append)warnings simplefilterrr showwarningrrrrrinstall_warning_loggerDsr)NN)__doc__Z __future__rrrWarningrobjectr r r r r rrrrrrs  __pycache__/build.cpython-36.pyc000064400000002420147221650610012503 0ustar003 . g @s<ddlmZddlZddlZddlmZGdddeZdS))absolute_importN)rmtreec@s6eZdZd ddZddZddZdd Zd d ZdS) BuildDirectoryNcCsL|dkr|dkrd}|dkr)format __class____name__r )r r r r__repr__szBuildDirectory.__repr__cCs|jS)N)r )r r r r __enter__"szBuildDirectory.__enter__cCs |jdS)N)cleanup)r excvaluetbr r r__exit__%szBuildDirectory.__exit__cCs|jrt|jdS)N)r rr )r r r rr(szBuildDirectory.cleanup)NN)r __module__ __qualname__rrrrrr r r rr s  r) Z __future__rZos.pathrr Z pip.utilsrobjectrr r r rs  __pycache__/hashes.cpython-36.opt-1.pyc000064400000006227147221650610013627 0ustar003 . g2 @szddlmZddlZddlmZmZmZddlmZddl m Z m Z m Z dZ dddgZGd d d eZGd d d eZdS) )absolute_importN) HashMismatch HashMissingInstallationError) read_chunks) iteritemsiterkeys itervaluesZsha256Zsha384Zsha512c@sJeZdZdZdddZddZddZd d Zd d Zd dZ ddZ dS)HasheszaA wrapper that builds multiple hashes at once and checks them against known-good values NcCs|dkr in||_dS)zo :param hashes: A dict of algorithm names pointing to lists of allowed hex digests N)_allowed)selfhashesr/usr/lib/python3.6/hashes.py__init__szHashes.__init__c Csi}xJt|jD]<}ytj|||<Wqttfk rJtd|YqXqWx(|D] }xt|D]}|j|qdWqVWx*t |D]\}}|j |j|krdSqW|j |dS)zCheck good hashes against ones built from iterable of chunks of data. Raise HashMismatch if none match. zUnknown hash name: %sN) rr hashlibnew ValueError TypeErrorrr updater hexdigest_raise)r ZchunksgotsZ hash_namechunkhashZgotrrrcheck_against_chunks s zHashes.check_against_chunkscCst|j|dS)N)rr )r rrrrr7sz Hashes._raisecCs|jt|S)zaCheck good hashes against a file-like object Raise HashMismatch if none match. )rr)r filerrrcheck_against_file:szHashes.check_against_filec Cs t|d }|j|SQRXdS)Nrb)openr)r pathrrrrcheck_against_pathBs zHashes.check_against_pathcCs t|jS)z,Return whether I know any known-good hashes.)boolr )r rrr __nonzero__FszHashes.__nonzero__cCs|jS)N)r#)r rrr__bool__JszHashes.__bool__)N) __name__ __module__ __qualname____doc__rrrrr!r#r$rrrrr s r cs(eZdZdZfddZddZZS) MissingHasheszA workalike for Hashes used when we're missing a hash for a requirement It computes the actual hash of the requirement and raises a HashMissing exception showing it to the user. cstt|jtgiddS)z!Don't offer the ``hashes`` kwarg.)r N)superr)r FAVORITE_HASH)r ) __class__rrrUszMissingHashes.__init__cCst|tjdS)N)rr+r)r rrrrr[szMissingHashes._raise)r%r&r'r(rr __classcell__rr)r,rr)Ns r))Z __future__rrZpip.exceptionsrrrZ pip.utilsrZpip._vendor.sixrrr r+Z STRONG_HASHESobjectr r)rrrrs   :__pycache__/encoding.cpython-36.pyc000064400000001747147221650610013205 0ustar003 . g@sjddlZddlZddlZejdfejdfejdfejdfejdfejdfej dfgZ ej d Z d d Z dS) Nutf8utf16zutf16-bezutf16-leutf32zutf32-bezutf32-lescoding[:=]\s*([-\w.]+)cCsx0tD](\}}|j|r|t|dj|SqWxV|jdddD]@}|dddkrFtj|rFtj|jdjd}|j|SqFW|jtj dS) zCheck a bytes string for a BOM to correctly detect the encoding Fallback to locale.getpreferredencoding(False) like open() on Python3N r#asciiF) BOMS startswithlendecodesplit ENCODING_REsearchgroupslocalegetpreferredencoding)dataZbomencodingliner/usr/lib/python3.6/encoding.py auto_decodes r)codecsrreBOM_UTF8 BOM_UTF16 BOM_UTF16_BE BOM_UTF16_LE BOM_UTF32 BOM_UTF32_BE BOM_UTF32_LEr compilerrrrrrs  __pycache__/encoding.cpython-36.opt-1.pyc000064400000001747147221650610014144 0ustar003 . g@sjddlZddlZddlZejdfejdfejdfejdfejdfejdfej dfgZ ej d Z d d Z dS) Nutf8utf16zutf16-bezutf16-leutf32zutf32-bezutf32-lescoding[:=]\s*([-\w.]+)cCsx0tD](\}}|j|r|t|dj|SqWxV|jdddD]@}|dddkrFtj|rFtj|jdjd}|j|SqFW|jtj dS) zCheck a bytes string for a BOM to correctly detect the encoding Fallback to locale.getpreferredencoding(False) like open() on Python3N r#asciiF) BOMS startswithlendecodesplit ENCODING_REsearchgroupslocalegetpreferredencoding)dataZbomencodingliner/usr/lib/python3.6/encoding.py auto_decodes r)codecsrreBOM_UTF8 BOM_UTF16 BOM_UTF16_BE BOM_UTF16_LE BOM_UTF32 BOM_UTF32_BE BOM_UTF32_LEr compilerrrrrrs  __pycache__/ui.cpython-36.pyc000064400000022534147221650610012031 0ustar003 . gM-@sddlmZddlmZddlZddlZddlmZmZmZddlZddl Z ddl Z ddl m Z ddl mZddlmZddlmZdd lmZmZdd lmZmZmZdd lmZydd lmZWnek rdZYnXe jeZ d dZ!e!eeZ"Gddde#Z$Gddde#Z%Gddde#Z&Gddde&e$e%e"Z'Gddde&e$e%eeZ(e j)ddZ*Gddde#Z+Gddde#Z,Gdd d e#Z-e j)d!d"Z.dS)#)absolute_import)divisionN)signalSIGINTdefault_int_handler)WINDOWS) format_size)get_indentation)six)BarIncrementalBar) WritelnMixin HIDE_CURSOR SHOW_CURSOR)Spinner)coloramac Cst|jdd}|s|St|dtjt|dtjg}|tt|dg7}ytjj|j|Wntk rv|SX|SdS)NencodingZ empty_fillZfillphases)getattrfiler Z text_typelistjoinencodeUnicodeEncodeError)Z preferredZfallbackrZ charactersr/usr/lib/python3.6/ui.py_select_progress_classsrcs4eZdZdZfddZfddZddZZS)InterruptibleMixina Helper to ensure that self.finish() gets called on keyboard interrupt. This allows downloads to be interrupted without leaving temporary state (like hidden cursors) behind. This class is similar to the progress library's existing SigIntMixin helper, but as of version 1.2, that helper has the following problems: 1. It calls sys.exit(). 2. It discards the existing SIGINT handler completely. 3. It leaves its own handler in place even after an uninterrupted finish, which will have unexpected delayed effects if the user triggers an unrelated keyboard interrupt some time after a progress-displaying download has already completed, for example. cs4tt|j||tt|j|_|jdkr0t|_dS)z= Save the original SIGINT handler for later. N)superr__init__rr handle_sigintoriginal_handlerr)selfargskwargs) __class__rrrNs zInterruptibleMixin.__init__cstt|jtt|jdS)z Restore the original SIGINT handler after finishing. This should happen regardless of whether the progress display finishes normally, or gets interrupted. N)rrfinishrrr!)r")r%rrr&^szInterruptibleMixin.finishcCs|j|j||dS)z Call self.finish() before delegating to the original SIGINT handler. This handler should only be in place while the progress display is active. N)r&r!)r"Zsignumframerrrr hsz InterruptibleMixin.handle_sigint)__name__ __module__ __qualname____doc__rr&r __classcell__rr)r%rr<s  rcsJeZdZfddZeddZeddZeddZd d d ZZ S) DownloadProgressMixincs,tt|j||dtd|j|_dS)N )rr-rr message)r"r#r$)r%rrruszDownloadProgressMixin.__init__cCs t|jS)N)rindex)r"rrr downloadedysz DownloadProgressMixin.downloadedcCs |jdkrdStd|jdS)Ngz...z/s)Zavgr)r"rrrdownload_speed}s z$DownloadProgressMixin.download_speedcCs|jrd|jSdS)Nzeta %s)ZetaZeta_td)r"rrr pretty_etas z DownloadProgressMixin.pretty_etar3ccs*x|D]}|V|j|qW|jdS)N)nextr&)r"itnxrrriters zDownloadProgressMixin.iter)r3) r(r)r*rpropertyr2r4r6r;r,rr)r%rr-ss     r-cseZdZfddZZS) WindowsMixincs\trjrd_ttj||trXtrXtjj_fddj_fddj_ dS)NFcs jjjS)N)rwrappedisattyr)r"rrsz'WindowsMixin.__init__..cs jjjS)N)rr>flushr)r"rrr@s) rZ hide_cursorrr=rrZ AnsiToWin32rr?rA)r"r#r$)r%)r"rrs zWindowsMixin.__init__)r(r)r*rr,rr)r%rr=sr=c@seZdZejZdZdZdS)DownloadProgressBarz %(percent)d%%z0%(downloaded)s %(download_speed)s %(pretty_eta)sN)r(r)r*sysstdoutrr0suffixrrrrrBsrBc@s&eZdZejZdZddZddZdS)DownloadProgressSpinnerz!%(downloaded)s %(download_speed)scCs"t|dstj|j|_t|jS)N_phaser)hasattr itertoolscyclerrGr7)r"rrr next_phases z"DownloadProgressSpinner.next_phasecCsN|j|}|j}|j|}dj||r*dnd||r6dnd|g}|j|dS)Nr5r.)r0rKrErZwriteln)r"r0ZphaserElinerrrupdates    zDownloadProgressSpinner.updateN) r(r)r*rCrDrrErKrMrrrrrFsrFc csRtr dVnB|j s$tjtjkr,dVn"|jtz dVWd|jtXdS)N) rr?loggergetEffectiveLevelloggingINFOwriterr)rrrr hidden_cursors  rSc@s$eZdZddZddZddZdS) RateLimitercCs||_d|_dS)Nr)_min_update_interval_seconds _last_update)r"min_update_interval_secondsrrrrszRateLimiter.__init__cCstj}||j}||jkS)N)timerVrU)r"ZnowZdeltarrrreadys zRateLimiter.readycCstj|_dS)N)rXrV)r"rrrresetszRateLimiter.resetN)r(r)r*rrYrZrrrrrTsrTc@s.eZdZd ddZddZdd Zd d ZdS) InteractiveSpinnerN-\|/?cCs\||_|dkrtj}||_t||_d|_tj||_ |jj dt |jdd|_ dS)NFr.z ... r) _messagerCrD_filerT _rate_limiter _finishedrIrJ _spin_cyclerRr _width)r"r0rZ spin_charsrWrrrrs  zInteractiveSpinner.__init__cCs^|j s td|j}|jj|d|j||jj|t||_|jj|jjdS)Nr.) raAssertionErrorrcr_rRlenrAr`rZ)r"statusZbackuprrr_write s     zInteractiveSpinner._writecCs,|jr dS|jjsdS|jt|jdS)N)rar`rYrhr7rb)r"rrrspins  zInteractiveSpinner.spincCs4|jr dS|j||jjd|jjd|_dS)N T)rarhr_rRrA)r" final_statusrrrr&s    zInteractiveSpinner.finish)Nr\r])r(r)r*rrhrir&rrrrr[s   r[c@s.eZdZd ddZddZddZdd Zd S) NonInteractiveSpinner<cCs$||_d|_t||_|jddS)NFZstarted)r^rarTr`_update)r"r0rWrrrr*s zNonInteractiveSpinner.__init__cCs*|j s t|jjtjd|j|dS)Nz%s: %s)rarer`rZrNinfor^)r"rgrrrrn0s  zNonInteractiveSpinner._updatecCs&|jr dS|jjsdS|jddS)Nzstill running...)rar`rYrn)r"rrrri5s  zNonInteractiveSpinner.spincCs$|jr dS|jd|fd|_dS)Nzfinished with status '%s'T)rarn)r"rkrrrr&<szNonInteractiveSpinner.finishN)rm)r(r)r*rrnrir&rrrrrl)s rlccstjjr"tjtjkr"t|}nt|}y t tj |VWdQRXWn>t k rj|j dYn*t k r|j dYn X|j ddS)NZcancelederrordone) rCrDr?rNrOrPrQr[rlrSKeyboardInterruptr& Exception)r0Zspinnerrrr open_spinnerCs    rt)/Z __future__rrrIrCrrrrX contextlibrPZ pip.compatrZ pip.utilsrZpip.utils.loggingr Z pip._vendorr Zpip._vendor.progress.barr r Zpip._vendor.progress.helpersr rrZpip._vendor.progress.spinnerrrrsZ getLoggerr(rNrZ_BaseBarobjectrr-r=rBrFcontextmanagerrSrTr[rlrtrrrrsB          7 !0__pycache__/appdirs.cpython-36.opt-1.pyc000064400000017002147221650610014007 0ustar003 . gk" @sdZddlmZddlZddlZddlmZmZddlm Z m Z ddZ dd d Z dd d Z ddZddZddZeryddlZeZWnek reZYnXddZdS)zd This code was taken from https://github.com/ActiveState/appdirs and modified to suit our purposes. )absolute_importN)WINDOWS expanduser)PY2 text_typecCstr Unix: ~/.cache/ (XDG default) Windows: C:\Users\\AppData\Local\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir`). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. CSIDL_LOCAL_APPDATAZCachedarwinz~/Library/CachesZXDG_CACHE_HOMEz~/.cache)rospathnormpath_get_win_folderr isinstancer_win_path_to_bytesjoinsysplatformrgetenv)appnamer r/usr/lib/python3.6/appdirs.pyuser_cache_dirs rFcCshtr,|r dpd}tjjtjjt||}n8tjdkrJtjjtd|}ntjjtj dtd|}|S)aS Return full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\ ... ...Application Data\ Win XP (roaming): C:\Documents and Settings\\Local ... ...Settings\Application Data\ Win 7 (not roaming): C:\Users\\AppData\Local\ Win 7 (roaming): C:\Users\\AppData\Roaming\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". CSIDL_APPDATArrz~/Library/Application Support/Z XDG_DATA_HOMEz~/.local/share) rr r rr r rrrr)rroamingconstr rrr user_data_dir>s  rTcCsHtrt||d}n2tjdkr&t|}ntjdtd}tjj||}|S)arReturn full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default True) can be set False to not use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: same as user_data_dir Unix: ~/.config/ Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by default "~/.config/". )rrZXDG_CONFIG_HOMEz ~/.config) rrrrr rrr r)rrr rrruser_config_dirjs  rcstr&tjjtd}tjj|g}nVtjdkrBtjjdg}n:tjdd}|rnfdd|j tj D}ng}|j d|S) aReturn a list of potential user-shared config dirs for this application. "appname" is the name of application. Typical user config directories are: macOS: /Library/Application Support// Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in $XDG_CONFIG_DIRS Win XP: C:\Documents and Settings\All Users\Application ... ...Data\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: Hidden, but writeable on Win 7: C:\ProgramData\ CSIDL_COMMON_APPDATArz/Library/Application SupportZXDG_CONFIG_DIRSz/etc/xdgcsg|]}tjjt|qSr)r r rr).0x)rrr sz$site_config_dirs..z/etc) rr r r r rrrrsplitpathsepappend)rr ZpathlistZxdg_config_dirsr)rrsite_config_dirss    r#cCs:ddl}dddd|}|j|jd}|j||\}}|S)z This is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. rNZAppDatazCommon AppDataz Local AppData)rrrz@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders)_winregOpenKeyHKEY_CURRENT_USERZ QueryValueEx) csidl_namer$Zshell_folder_namekeyZ directoryZ_typerrr_get_win_folder_from_registrysr)cCsdddd|}tjd}tjjjd|dd|d}x|D]}t|dkr:d }Pq:W|rztjd}tjjj|j|drz|}|jS) N#)rrrirFT) ctypesZcreate_unicode_bufferZwindllZshell32ZSHGetFolderPathWordZkernel32ZGetShortPathNameWvalue)r'Z csidl_constZbufZ has_high_charcZbuf2rrr_get_win_folder_with_ctypess     r2c Cs6x0dD](}y |j|Sttfk r,YqXqW|S)aEncode Windows paths to bytes. Only used on Python 2. Motivation is to be consistent with other operating systems where paths are also returned as bytes. This avoids problems mixing bytes and Unicode elsewhere in the codebase. For more details and discussion see . If encoding using ASCII and MBCS fails, return the original Unicode path. ASCIIMBCS)r3r4)encodeUnicodeEncodeError LookupError)r encodingrrrrs   r)F)T)__doc__Z __future__rr rZ pip.compatrrZpip._vendor.sixrrrrrr#r)r2r.r ImportErrorrrrrrs$ 0 , !( build.py000064400000002440147221650610006221 0ustar00from __future__ import absolute_import import os.path import tempfile from pip.utils import rmtree class BuildDirectory(object): def __init__(self, name=None, delete=None): # If we were not given an explicit directory, and we were not given an # explicit delete option, then we'll default to deleting. if name is None and delete is None: delete = True if name is None: # We realpath here because some systems have their default tmpdir # symlinked to another directory. This tends to confuse build # scripts, so we canonicalize the path by traversing potential # symlinks here. name = os.path.realpath(tempfile.mkdtemp(prefix="pip-build-")) # If we were not given an explicit directory, and we were not given # an explicit delete option, then we'll default to deleting. if delete is None: delete = True self.name = name self.delete = delete def __repr__(self): return "<{} {!r}>".format(self.__class__.__name__, self.name) def __enter__(self): return self.name def __exit__(self, exc, value, tb): self.cleanup() def cleanup(self): if self.delete: rmtree(self.name) glibc.py000064400000005573147221650610006214 0ustar00from __future__ import absolute_import import re import ctypes import platform import warnings def glibc_version_string(): "Returns glibc version string, or None if not using glibc." # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen # manpage says, "If filename is NULL, then the returned handle is for the # main program". This way we can let the linker do the work to figure out # which libc our process is actually using. process_namespace = ctypes.CDLL(None) try: gnu_get_libc_version = process_namespace.gnu_get_libc_version except AttributeError: # Symbol doesn't exist -> therefore, we are not linked to # glibc. return None # Call gnu_get_libc_version, which returns a string like "2.5" gnu_get_libc_version.restype = ctypes.c_char_p version_str = gnu_get_libc_version() # py2 / py3 compatibility: if not isinstance(version_str, str): version_str = version_str.decode("ascii") return version_str # Separated out from have_compatible_glibc for easier unit testing def check_glibc_version(version_str, required_major, minimum_minor): # Parse string and check against requested version. # # We use a regexp instead of str.split because we want to discard any # random junk that might come after the minor version -- this might happen # in patched/forked versions of glibc (e.g. Linaro's version of glibc # uses version strings like "2.20-2014.11"). See gh-3588. m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) if not m: warnings.warn("Expected glibc version with 2 components major.minor," " got: %s" % version_str, RuntimeWarning) return False return (int(m.group("major")) == required_major and int(m.group("minor")) >= minimum_minor) def have_compatible_glibc(required_major, minimum_minor): version_str = glibc_version_string() if version_str is None: return False return check_glibc_version(version_str, required_major, minimum_minor) # platform.libc_ver regularly returns completely nonsensical glibc # versions. E.g. on my computer, platform says: # # ~$ python2.7 -c 'import platform; print(platform.libc_ver())' # ('glibc', '2.7') # ~$ python3.5 -c 'import platform; print(platform.libc_ver())' # ('glibc', '2.9') # # But the truth is: # # ~$ ldd --version # ldd (Debian GLIBC 2.22-11) 2.22 # # This is unfortunate, because it means that the linehaul data on libc # versions that was generated by pip 8.1.2 and earlier is useless and # misleading. Solution: instead of using platform, use our code that actually # works. def libc_ver(): glibc_version = glibc_version_string() if glibc_version is None: # For non-glibc platforms, fall back on platform.libc_ver return platform.libc_ver() else: return ("glibc", glibc_version) appdirs.py000064400000021153147221650610006566 0ustar00""" This code was taken from https://github.com/ActiveState/appdirs and modified to suit our purposes. """ from __future__ import absolute_import import os import sys from pip.compat import WINDOWS, expanduser from pip._vendor.six import PY2, text_type def user_cache_dir(appname): r""" Return full path to the user-specific cache dir for this application. "appname" is the name of application. Typical user cache directories are: macOS: ~/Library/Caches/ Unix: ~/.cache/ (XDG default) Windows: C:\Users\\AppData\Local\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir`). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. """ if WINDOWS: # Get the base path path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) # When using Python 2, return paths as bytes on Windows like we do on # other operating systems. See helper function docs for more details. if PY2 and isinstance(path, text_type): path = _win_path_to_bytes(path) # Add our app name and Cache directory to it path = os.path.join(path, appname, "Cache") elif sys.platform == "darwin": # Get the base path path = expanduser("~/Library/Caches") # Add our app name to it path = os.path.join(path, appname) else: # Get the base path path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache")) # Add our app name to it path = os.path.join(path, appname) return path def user_data_dir(appname, roaming=False): """ Return full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\ ... ...Application Data\ Win XP (roaming): C:\Documents and Settings\\Local ... ...Settings\Application Data\ Win 7 (not roaming): C:\\Users\\AppData\Local\ Win 7 (roaming): C:\\Users\\AppData\Roaming\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". """ if WINDOWS: const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" path = os.path.join(os.path.normpath(_get_win_folder(const)), appname) elif sys.platform == "darwin": path = os.path.join( expanduser('~/Library/Application Support/'), appname, ) else: path = os.path.join( os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")), appname, ) return path def user_config_dir(appname, roaming=True): """Return full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "roaming" (boolean, default True) can be set False to not use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: macOS: same as user_data_dir Unix: ~/.config/ Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by default "~/.config/". """ if WINDOWS: path = user_data_dir(appname, roaming=roaming) elif sys.platform == "darwin": path = user_data_dir(appname) else: path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config")) path = os.path.join(path, appname) return path # for the discussion regarding site_config_dirs locations # see def site_config_dirs(appname): """Return a list of potential user-shared config dirs for this application. "appname" is the name of application. Typical user config directories are: macOS: /Library/Application Support// Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in $XDG_CONFIG_DIRS Win XP: C:\Documents and Settings\All Users\Application ... ...Data\\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: Hidden, but writeable on Win 7: C:\ProgramData\\ """ if WINDOWS: path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) pathlist = [os.path.join(path, appname)] elif sys.platform == 'darwin': pathlist = [os.path.join('/Library/Application Support', appname)] else: # try looking in $XDG_CONFIG_DIRS xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') if xdg_config_dirs: pathlist = [ os.path.join(expanduser(x), appname) for x in xdg_config_dirs.split(os.pathsep) ] else: pathlist = [] # always look in /etc directly as well pathlist.append('/etc') return pathlist # -- Windows support functions -- def _get_win_folder_from_registry(csidl_name): """ This is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. """ import _winreg shell_folder_name = { "CSIDL_APPDATA": "AppData", "CSIDL_COMMON_APPDATA": "Common AppData", "CSIDL_LOCAL_APPDATA": "Local AppData", }[csidl_name] key = _winreg.OpenKey( _winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" ) directory, _type = _winreg.QueryValueEx(key, shell_folder_name) return directory def _get_win_folder_with_ctypes(csidl_name): csidl_const = { "CSIDL_APPDATA": 26, "CSIDL_COMMON_APPDATA": 35, "CSIDL_LOCAL_APPDATA": 28, }[csidl_name] buf = ctypes.create_unicode_buffer(1024) ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) # Downgrade to short path name if have highbit chars. See # . has_high_char = False for c in buf: if ord(c) > 255: has_high_char = True break if has_high_char: buf2 = ctypes.create_unicode_buffer(1024) if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): buf = buf2 return buf.value if WINDOWS: try: import ctypes _get_win_folder = _get_win_folder_with_ctypes except ImportError: _get_win_folder = _get_win_folder_from_registry def _win_path_to_bytes(path): """Encode Windows paths to bytes. Only used on Python 2. Motivation is to be consistent with other operating systems where paths are also returned as bytes. This avoids problems mixing bytes and Unicode elsewhere in the codebase. For more details and discussion see . If encoding using ASCII and MBCS fails, return the original Unicode path. """ for encoding in ('ASCII', 'MBCS'): try: return path.encode(encoding) except (UnicodeEncodeError, LookupError): pass return path encoding.py000064400000001713147221650610006712 0ustar00import codecs import locale import re BOMS = [ (codecs.BOM_UTF8, 'utf8'), (codecs.BOM_UTF16, 'utf16'), (codecs.BOM_UTF16_BE, 'utf16-be'), (codecs.BOM_UTF16_LE, 'utf16-le'), (codecs.BOM_UTF32, 'utf32'), (codecs.BOM_UTF32_BE, 'utf32-be'), (codecs.BOM_UTF32_LE, 'utf32-le'), ] ENCODING_RE = re.compile(b'coding[:=]\s*([-\w.]+)') def auto_decode(data): """Check a bytes string for a BOM to correctly detect the encoding Fallback to locale.getpreferredencoding(False) like open() on Python3""" for bom, encoding in BOMS: if data.startswith(bom): return data[len(bom):].decode(encoding) # Lets check the first two lines as in PEP263 for line in data.split(b'\n')[:2]: if line[0:1] == b'#' and ENCODING_RE.search(line): encoding = ENCODING_RE.search(line).groups()[0].decode('ascii') return data.decode(encoding) return data.decode(locale.getpreferredencoding(False)) filesystem.py000064400000001603147221650610007306 0ustar00import os import os.path from pip.compat import get_path_uid def check_path_owner(path): # If we don't have a way to check the effective uid of this process, then # we'll just assume that we own the directory. if not hasattr(os, "geteuid"): return True previous = None while path != previous: if os.path.lexists(path): # Check if path is writable by current user. if os.geteuid() == 0: # Special handling for root user in order to handle properly # cases where users use sudo without -H flag. try: path_uid = get_path_uid(path) except OSError: return False return path_uid == 0 else: return os.access(path, os.W_OK) else: previous, path = path, os.path.dirname(path) packaging.py000064400000004040147221650610007044 0ustar00from __future__ import absolute_import from email.parser import FeedParser import logging import sys from pip._vendor.packaging import specifiers from pip._vendor.packaging import version from pip._vendor import pkg_resources from pip import exceptions logger = logging.getLogger(__name__) def check_requires_python(requires_python): """ Check if the python version in use match the `requires_python` specifier. Returns `True` if the version of python in use matches the requirement. Returns `False` if the version of python in use does not matches the requirement. Raises an InvalidSpecifier if `requires_python` have an invalid format. """ if requires_python is None: # The package provides no information return True requires_python_specifier = specifiers.SpecifierSet(requires_python) # We only use major.minor.micro python_version = version.parse('.'.join(map(str, sys.version_info[:3]))) return python_version in requires_python_specifier def get_metadata(dist): if (isinstance(dist, pkg_resources.DistInfoDistribution) and dist.has_metadata('METADATA')): return dist.get_metadata('METADATA') elif dist.has_metadata('PKG-INFO'): return dist.get_metadata('PKG-INFO') def check_dist_requires_python(dist): metadata = get_metadata(dist) feed_parser = FeedParser() feed_parser.feed(metadata) pkg_info_dict = feed_parser.close() requires_python = pkg_info_dict.get('Requires-Python') try: if not check_requires_python(requires_python): raise exceptions.UnsupportedPythonVersion( "%s requires Python '%s' but the running Python is %s" % ( dist.project_name, requires_python, '.'.join(map(str, sys.version_info[:3])),) ) except specifiers.InvalidSpecifier as e: logger.warning( "Package %s has an invalid Requires-Python entry %s - %s" % ( dist.project_name, requires_python, e)) return setuptools_build.py000064400000000426147221650610010524 0ustar00# Shim to wrap setup.py invocation with setuptools SETUPTOOLS_SHIM = ( "import setuptools, tokenize;__file__=%r;" "f=getattr(tokenize, 'open', open)(__file__);" "code=f.read().replace('\\r\\n', '\\n');" "f.close();" "exec(compile(code, __file__, 'exec'))" ) logging.py000064400000006377147221650610006565 0ustar00from __future__ import absolute_import import contextlib import logging import logging.handlers import os try: import threading except ImportError: import dummy_threading as threading from pip.compat import WINDOWS from pip.utils import ensure_dir try: from pip._vendor import colorama # Lots of different errors can come from this, including SystemError and # ImportError. except Exception: colorama = None _log_state = threading.local() _log_state.indentation = 0 @contextlib.contextmanager def indent_log(num=2): """ A context manager which will cause the log output to be indented for any log messages emitted inside it. """ _log_state.indentation += num try: yield finally: _log_state.indentation -= num def get_indentation(): return getattr(_log_state, 'indentation', 0) class IndentingFormatter(logging.Formatter): def format(self, record): """ Calls the standard formatter, but will indent all of the log messages by our current indentation level. """ formatted = logging.Formatter.format(self, record) formatted = "".join([ (" " * get_indentation()) + line for line in formatted.splitlines(True) ]) return formatted def _color_wrap(*colors): def wrapped(inp): return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) return wrapped class ColorizedStreamHandler(logging.StreamHandler): # Don't build up a list of colors if we don't have colorama if colorama: COLORS = [ # This needs to be in order from highest logging level to lowest. (logging.ERROR, _color_wrap(colorama.Fore.RED)), (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)), ] else: COLORS = [] def __init__(self, stream=None): logging.StreamHandler.__init__(self, stream) if WINDOWS and colorama: self.stream = colorama.AnsiToWin32(self.stream) def should_color(self): # Don't colorize things if we do not have colorama if not colorama: return False real_stream = ( self.stream if not isinstance(self.stream, colorama.AnsiToWin32) else self.stream.wrapped ) # If the stream is a tty we should color it if hasattr(real_stream, "isatty") and real_stream.isatty(): return True # If we have an ASNI term we should color it if os.environ.get("TERM") == "ANSI": return True # If anything else we should not color it return False def format(self, record): msg = logging.StreamHandler.format(self, record) if self.should_color(): for level, color in self.COLORS: if record.levelno >= level: msg = color(msg) break return msg class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): def _open(self): ensure_dir(os.path.dirname(self.baseFilename)) return logging.handlers.RotatingFileHandler._open(self) class MaxLevelFilter(logging.Filter): def __init__(self, level): self.level = level def filter(self, record): return record.levelno < self.level deprecation.py000064400000004270147221650610007422 0ustar00""" A module that implements tooling to enable easy warnings about deprecations. """ from __future__ import absolute_import import logging import warnings class PipDeprecationWarning(Warning): pass class Pending(object): pass class RemovedInPip10Warning(PipDeprecationWarning): pass class RemovedInPip11Warning(PipDeprecationWarning, Pending): pass class Python26DeprecationWarning(PipDeprecationWarning): pass # Warnings <-> Logging Integration _warnings_showwarning = None def _showwarning(message, category, filename, lineno, file=None, line=None): if file is not None: if _warnings_showwarning is not None: _warnings_showwarning( message, category, filename, lineno, file, line, ) else: if issubclass(category, PipDeprecationWarning): # We use a specially named logger which will handle all of the # deprecation messages for pip. logger = logging.getLogger("pip.deprecations") # This is purposely using the % formatter here instead of letting # the logging module handle the interpolation. This is because we # want it to appear as if someone typed this entire message out. log_message = "DEPRECATION: %s" % message # PipDeprecationWarnings that are Pending still have at least 2 # versions to go until they are removed so they can just be # warnings. Otherwise, they will be removed in the very next # version of pip. We want these to be more obvious so we use the # ERROR logging level. if issubclass(category, Pending): logger.warning(log_message) else: logger.error(log_message) else: _warnings_showwarning( message, category, filename, lineno, file, line, ) def install_warning_logger(): # Enable our Deprecation Warnings warnings.simplefilter("default", PipDeprecationWarning, append=True) global _warnings_showwarning if _warnings_showwarning is None: _warnings_showwarning = warnings.showwarning warnings.showwarning = _showwarning ui.py000064400000026515147221650610005550 0ustar00from __future__ import absolute_import from __future__ import division import itertools import sys from signal import signal, SIGINT, default_int_handler import time import contextlib import logging from pip.compat import WINDOWS from pip.utils import format_size from pip.utils.logging import get_indentation from pip._vendor import six from pip._vendor.progress.bar import Bar, IncrementalBar from pip._vendor.progress.helpers import (WritelnMixin, HIDE_CURSOR, SHOW_CURSOR) from pip._vendor.progress.spinner import Spinner try: from pip._vendor import colorama # Lots of different errors can come from this, including SystemError and # ImportError. except Exception: colorama = None logger = logging.getLogger(__name__) def _select_progress_class(preferred, fallback): encoding = getattr(preferred.file, "encoding", None) # If we don't know what encoding this file is in, then we'll just assume # that it doesn't support unicode and use the ASCII bar. if not encoding: return fallback # Collect all of the possible characters we want to use with the preferred # bar. characters = [ getattr(preferred, "empty_fill", six.text_type()), getattr(preferred, "fill", six.text_type()), ] characters += list(getattr(preferred, "phases", [])) # Try to decode the characters we're using for the bar using the encoding # of the given file, if this works then we'll assume that we can use the # fancier bar and if not we'll fall back to the plaintext bar. try: six.text_type().join(characters).encode(encoding) except UnicodeEncodeError: return fallback else: return preferred _BaseBar = _select_progress_class(IncrementalBar, Bar) class InterruptibleMixin(object): """ Helper to ensure that self.finish() gets called on keyboard interrupt. This allows downloads to be interrupted without leaving temporary state (like hidden cursors) behind. This class is similar to the progress library's existing SigIntMixin helper, but as of version 1.2, that helper has the following problems: 1. It calls sys.exit(). 2. It discards the existing SIGINT handler completely. 3. It leaves its own handler in place even after an uninterrupted finish, which will have unexpected delayed effects if the user triggers an unrelated keyboard interrupt some time after a progress-displaying download has already completed, for example. """ def __init__(self, *args, **kwargs): """ Save the original SIGINT handler for later. """ super(InterruptibleMixin, self).__init__(*args, **kwargs) self.original_handler = signal(SIGINT, self.handle_sigint) # If signal() returns None, the previous handler was not installed from # Python, and we cannot restore it. This probably should not happen, # but if it does, we must restore something sensible instead, at least. # The least bad option should be Python's default SIGINT handler, which # just raises KeyboardInterrupt. if self.original_handler is None: self.original_handler = default_int_handler def finish(self): """ Restore the original SIGINT handler after finishing. This should happen regardless of whether the progress display finishes normally, or gets interrupted. """ super(InterruptibleMixin, self).finish() signal(SIGINT, self.original_handler) def handle_sigint(self, signum, frame): """ Call self.finish() before delegating to the original SIGINT handler. This handler should only be in place while the progress display is active. """ self.finish() self.original_handler(signum, frame) class DownloadProgressMixin(object): def __init__(self, *args, **kwargs): super(DownloadProgressMixin, self).__init__(*args, **kwargs) self.message = (" " * (get_indentation() + 2)) + self.message @property def downloaded(self): return format_size(self.index) @property def download_speed(self): # Avoid zero division errors... if self.avg == 0.0: return "..." return format_size(1 / self.avg) + "/s" @property def pretty_eta(self): if self.eta: return "eta %s" % self.eta_td return "" def iter(self, it, n=1): for x in it: yield x self.next(n) self.finish() class WindowsMixin(object): def __init__(self, *args, **kwargs): # The Windows terminal does not support the hide/show cursor ANSI codes # even with colorama. So we'll ensure that hide_cursor is False on # Windows. # This call neds to go before the super() call, so that hide_cursor # is set in time. The base progress bar class writes the "hide cursor" # code to the terminal in its init, so if we don't set this soon # enough, we get a "hide" with no corresponding "show"... if WINDOWS and self.hide_cursor: self.hide_cursor = False super(WindowsMixin, self).__init__(*args, **kwargs) # Check if we are running on Windows and we have the colorama module, # if we do then wrap our file with it. if WINDOWS and colorama: self.file = colorama.AnsiToWin32(self.file) # The progress code expects to be able to call self.file.isatty() # but the colorama.AnsiToWin32() object doesn't have that, so we'll # add it. self.file.isatty = lambda: self.file.wrapped.isatty() # The progress code expects to be able to call self.file.flush() # but the colorama.AnsiToWin32() object doesn't have that, so we'll # add it. self.file.flush = lambda: self.file.wrapped.flush() class DownloadProgressBar(WindowsMixin, InterruptibleMixin, DownloadProgressMixin, _BaseBar): file = sys.stdout message = "%(percent)d%%" suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, DownloadProgressMixin, WritelnMixin, Spinner): file = sys.stdout suffix = "%(downloaded)s %(download_speed)s" def next_phase(self): if not hasattr(self, "_phaser"): self._phaser = itertools.cycle(self.phases) return next(self._phaser) def update(self): message = self.message % self phase = self.next_phase() suffix = self.suffix % self line = ''.join([ message, " " if message else "", phase, " " if suffix else "", suffix, ]) self.writeln(line) ################################################################ # Generic "something is happening" spinners # # We don't even try using progress.spinner.Spinner here because it's actually # simpler to reimplement from scratch than to coerce their code into doing # what we need. ################################################################ @contextlib.contextmanager def hidden_cursor(file): # The Windows terminal does not support the hide/show cursor ANSI codes, # even via colorama. So don't even try. if WINDOWS: yield # We don't want to clutter the output with control characters if we're # writing to a file, or if the user is running with --quiet. # See https://github.com/pypa/pip/issues/3418 elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: yield else: file.write(HIDE_CURSOR) try: yield finally: file.write(SHOW_CURSOR) class RateLimiter(object): def __init__(self, min_update_interval_seconds): self._min_update_interval_seconds = min_update_interval_seconds self._last_update = 0 def ready(self): now = time.time() delta = now - self._last_update return delta >= self._min_update_interval_seconds def reset(self): self._last_update = time.time() class InteractiveSpinner(object): def __init__(self, message, file=None, spin_chars="-\\|/", # Empirically, 8 updates/second looks nice min_update_interval_seconds=0.125): self._message = message if file is None: file = sys.stdout self._file = file self._rate_limiter = RateLimiter(min_update_interval_seconds) self._finished = False self._spin_cycle = itertools.cycle(spin_chars) self._file.write(" " * get_indentation() + self._message + " ... ") self._width = 0 def _write(self, status): assert not self._finished # Erase what we wrote before by backspacing to the beginning, writing # spaces to overwrite the old text, and then backspacing again backup = "\b" * self._width self._file.write(backup + " " * self._width + backup) # Now we have a blank slate to add our status self._file.write(status) self._width = len(status) self._file.flush() self._rate_limiter.reset() def spin(self): if self._finished: return if not self._rate_limiter.ready(): return self._write(next(self._spin_cycle)) def finish(self, final_status): if self._finished: return self._write(final_status) self._file.write("\n") self._file.flush() self._finished = True # Used for dumb terminals, non-interactive installs (no tty), etc. # We still print updates occasionally (once every 60 seconds by default) to # act as a keep-alive for systems like Travis-CI that take lack-of-output as # an indication that a task has frozen. class NonInteractiveSpinner(object): def __init__(self, message, min_update_interval_seconds=60): self._message = message self._finished = False self._rate_limiter = RateLimiter(min_update_interval_seconds) self._update("started") def _update(self, status): assert not self._finished self._rate_limiter.reset() logger.info("%s: %s", self._message, status) def spin(self): if self._finished: return if not self._rate_limiter.ready(): return self._update("still running...") def finish(self, final_status): if self._finished: return self._update("finished with status '%s'" % (final_status,)) self._finished = True @contextlib.contextmanager def open_spinner(message): # Interactive spinner goes directly to sys.stdout rather than being routed # through the logging system, but it acts like it has level INFO, # i.e. it's only displayed if we're at level INFO or better. # Non-interactive spinner goes through the logging system, so it is always # in sync with logging configuration. if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: spinner = InteractiveSpinner(message) else: spinner = NonInteractiveSpinner(message) try: with hidden_cursor(sys.stdout): yield spinner except KeyboardInterrupt: spinner.finish("canceled") raise except Exception: spinner.finish("error") raise else: spinner.finish("done") FileUtils.pyo000064400000027746147221674750007234 0ustar00 .t_c@s'dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddl m Z mZejddefd YZd efd YZd efd YZdefdYZdefdYZdS(s FileUtils - Provides dmmgmnt file-related capabilities. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/FileUtils.py#1 $ i(tprint_functionNi(tCommand(tTimeoutt TimeoutErrortutilstFileBasecBsheZdZejdZedZdZdZ dZ edZ e j dZ RS(sThe FileBase object; provides basic file control. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileBasecCs|jS(N(t_FileBase__filePath(tself((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pytpath:scOsAtt|jtjj||_|jdd|_ dS(s: Arguments: None Returns: Nothing tfdN( tsuperRt__init__tosRtrealpathRtgettNonet _FileBase__fd(RtfilePathtargstkwargs((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR AscCs|S(N((R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt __enter__MscCstS(N(tFalse(Rt exceptionTypetexceptionValuet traceback((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt__exit__QscCs|jS(N(R(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt_fdXscCs ||_dS(N(R(Rtvalue((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR_s( t__name__t __module__t__doc__tloggingt getLoggertlogtpropertyRR RRRtsetter(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR-s  t FileTouchcBs8eZdZejdZdZdZdZRS(sThe FileTouch object; touches the file. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileTouchcOs tt|j|||dS(s: Arguments: None Returns: Nothing N(R R$R (RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR yscCstt|j|jdkrtjj|j}tj|tj snt dd|g}|j ntj|jtj s|j qn|S(s0Make certain the file exists and return ourself.tmkdirs-pN( R R$RRRR RtdirnametaccesstF_OKRtrunt _createFile(RtdirPathtcmd((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs cCs#td|jg}|jdS(sCreates the targe file.ttouchN(RRR)(RR,((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR*s( RRRRR R!R RR*(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR$hs  tFileOpencBseZdZejdZedZdZddZ ddZ ddZ e jdZdd Zd Zd Zd Zd ZdZddZdZedZRS(sThe FileOpen object; provides basic access to a file. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileOpencCs|jS(N(t_FileOpen__file(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pytfilescCs|jjdS(N(R0tflush(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR1sicCs|jj|S(N(R0tread(Rt numberOfBytes((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR2scCs|jj|S(N(R0treadline(RR3((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR4scCs-|dkr|jjS|jj|SdS(N(RR0t readlines(RtnumberOfBytesHint((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR5s  cCs|jj||dS(N(R0tseek(Rtoffsettwhence((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR7scCs0|dkr|jjn|jj|dS(N(RR0ttruncate(Rtsize((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR:s cCs|jj|dS(N(R0twrite(Rtstring((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR<scCs|jj|dS(N(R0t writeline(RtsequenceOfStrings((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt writelinesscCs |jjS(N(R0tnext(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRAscCs_tt|j|jdkr@tj|j|j|_ntj |j|j |_ |S(s!Open the file and return ourself.N( R R.RRRR topenRt_osModetfdopent_FileOpen__modeR/(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs cCs)|jjtt|j|||S(s Close the file.(R0tcloseR R.R(RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs trcOstt|j|||d}t|dkrPd|dkrPtj}nH|ddkrltj}n,|ddkrtjtj B}n tj}|ddkr|tj B}nd|_ ||_ ||_ dS(s: Arguments: None Returns: Nothing it+iRGtwtaN(R R.R RtlenR tO_RDWRtO_RDONLYtO_WRONLYtO_TRUNCtO_APPENDR/REt_FileOpen__osMode(RRtmodeRRtosMode((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR s"     cCs|S(N((R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt__iter__scCs|jS(N(RQ(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRCsN(RRRRR R!R"R0R1R2R4RR5R tSEEK_SETR7R:R<R@RARRR RTRC(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR.s"          tFileLockcBs;eZdZejdZddZdZdZ RS(sThe FileLock object; a context manager providing interlocked access on a file. The file is created, if necessary. Class attributes: log (logging.Logger) - logger for this class Attributes: _timeout - timeout in seconds (None = no timeout) sutils.FileLockcOs&tt|j||||_dS(s Arguments: filePath - (str) path to file mode - (str) open mode timeout - (int) timeout in seconds; may be None Returns: Nothing N(R RVR t_timeout(RRRRttimeoutRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR :s cCs tt|j|jtjkr7tj}d}ntj}d}|j dk r|j j dj d|jd|j d|t|j tdj d|jd|j tj|j|WdQXn8|j j d j d|jd|tj|j||S( s_If the open mode is read-only the file is locked shared else it is locked exclusively. tsharedt exclusives'attempting to lock {f} in {s}s mode {m}tftstms!Could not lock {f} in {s} secondsNsattempting to lock {f} mode {m}(R RVRRCR RMtfcntltLOCK_SHtLOCK_EXRWRR!tdebugtformatRRt_tflockR0(Rt flockModetlockModeString((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRGs(         cCs`tj|jtj|tk rD|jjdjd|jnt t |j |||S(s Unlocks and closes the file.sreleased lock {f}R[( R^RdR0tLOCK_UNRR!RaRbRR RVR(RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRds  "N( RRRRR R!RR RR(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRV&s   tFileTempcBs8eZdZejdZddddZdZRS(sThe FileTemp object; a context manager providing temporary files with specified (or default) owner and permissions. An optional destination parameter specifies the location to which the temp file should be moved at exit, if no exception is encountered. The move, if specified, is performed after performing the owner manipulations. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileTempcOs|tj}tt|j|ddd|d|sNttj}n|s]d}n||_||_ ||_ dS(s Arguments: owner - (str) the owner to set for the file ownerPerm - (str) the permissions to set for the owner destination (str) the path to which to move the temp file on exit Returns: Nothing isr+R itrwN( ttempfiletmkstempR RhR tstrR tgeteuidt_FileTemp__ownert_FileTemp__ownerPermt_FileTemp__destination(Rtownert ownerPermt destinationRRttmpFile((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR s '   cCs6|}|dkr|jdk rytd|j|jg}|jtddjd|jg|jg}|j|jj td|j|jg}|jWqt k r}|}qXn|dk s|jdkry#td|jg}|jWqqXnt t |j |||S(Ntchowntchmodt=tutmvtrm(RRpRRnRR)tjoinRoR0RFt ExceptionR RhR(RRRRt exceptionR,tex((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs* *   N( RRRRR R!RR R(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRhws  (Rt __future__RterrnoR^tgettexttgrpRR tstatRjttimeRRRtinstalltobjectRR$R.RVRh(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyts$          ;=QLogger.pyo000064400000007252147221674750006541 0ustar00 .t_c@s`dZddlZddlZddlZddlZddlmZdefdYZdS(si Logger - VDO manager logging $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Logger.py#3 $ iN(t MethodTypetLoggercBs~eZdZejjejdZe Z dZ e dZe de dZe dZe dZdZRS(sWrappers and configuration methods for the Python logger. Attributes: logfile (string): the path to the logfile if specified. myname (string): name of the command being run. quiet (bool): if True, don't print to stdout. icCs"|js|GHn|j|dS(s4Print a status message to stdout and log it as well.N(tquiettinfo(tclstloggertmsg((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pytannounce/s c Cs;||_||_|}d}|r*dnd|}tj}|jtjtjtj}|j tj |j||j|rtj ntj |j ||jdk rytjj|jrtjj|j rt|jd} tjd| }n!tjj|jddd d }tj d |} |j | |j|retj ntj|j |Wqtk r} |jd jd |jd| qXnyStjjdd}|j tj |j||jtj |j |Wn)tk r6} |jdj| nXdS(s8Configure the logging system according to the arguments.s: %(levelname)s - %(message)ss : %(name)sttwtstreamtmaxBytesi it backupCountis%(asctime)s %(name)ss.Unable to configure logging to {logfile}: {ex}tlogfiletextaddresss/dev/logs,Unable to configure logging for rsyslog: {0}Ni(i(tmynameR tloggingt getLoggertsetLeveltNOTSETt StreamHandlertsyststderrt setFormattert FormattertDEBUGtWARNINGt addHandlertNonetostpathtexiststisfiletopenthandlerstRotatingFileHandlertINFOt Exceptiontwarntformatt SysLogHandler( RtnameR tdebugt debuggingt formatBaset debugBaseRthandlert logstreamt formatterR((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyt configure7sB    +  cCs.tj|}t|j||j|_|S(s;Returns a Python logger decorated with the announce method.(RRRRt __class__(RR*R((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyRbscCs6g}|jdk r2|jdt|jn|S(sBReturn a list of strings containing the logging options specified.s --logfile=N(R Rtappendtstr(Rtoptions((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pytloggingOptionsjscCstt|jdS(N(tsuperRt__init__(tself((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyR9usN(t__name__t __module__t__doc__RRtbasenameRtargvRtFalseRRR t classmethodRR2RR7R9(((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyR s* ( R=Rtlogging.handlersRRttypesRtobjectR(((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyts     FileUtils.pyc000064400000027746147221674750007220 0ustar00 .t_c@s'dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddl m Z mZejddefd YZd efd YZd efd YZdefdYZdefdYZdS(s FileUtils - Provides dmmgmnt file-related capabilities. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/FileUtils.py#1 $ i(tprint_functionNi(tCommand(tTimeoutt TimeoutErrortutilstFileBasecBsheZdZejdZedZdZdZ dZ edZ e j dZ RS(sThe FileBase object; provides basic file control. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileBasecCs|jS(N(t_FileBase__filePath(tself((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pytpath:scOsAtt|jtjj||_|jdd|_ dS(s: Arguments: None Returns: Nothing tfdN( tsuperRt__init__tosRtrealpathRtgettNonet _FileBase__fd(RtfilePathtargstkwargs((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR AscCs|S(N((R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt __enter__MscCstS(N(tFalse(Rt exceptionTypetexceptionValuet traceback((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt__exit__QscCs|jS(N(R(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt_fdXscCs ||_dS(N(R(Rtvalue((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR_s( t__name__t __module__t__doc__tloggingt getLoggertlogtpropertyRR RRRtsetter(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR-s  t FileTouchcBs8eZdZejdZdZdZdZRS(sThe FileTouch object; touches the file. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileTouchcOs tt|j|||dS(s: Arguments: None Returns: Nothing N(R R$R (RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR yscCstt|j|jdkrtjj|j}tj|tj snt dd|g}|j ntj|jtj s|j qn|S(s0Make certain the file exists and return ourself.tmkdirs-pN( R R$RRRR RtdirnametaccesstF_OKRtrunt _createFile(RtdirPathtcmd((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs cCs#td|jg}|jdS(sCreates the targe file.ttouchN(RRR)(RR,((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR*s( RRRRR R!R RR*(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR$hs  tFileOpencBseZdZejdZedZdZddZ ddZ ddZ e jdZdd Zd Zd Zd Zd ZdZddZdZedZRS(sThe FileOpen object; provides basic access to a file. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileOpencCs|jS(N(t_FileOpen__file(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pytfilescCs|jjdS(N(R0tflush(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR1sicCs|jj|S(N(R0tread(Rt numberOfBytes((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR2scCs|jj|S(N(R0treadline(RR3((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR4scCs-|dkr|jjS|jj|SdS(N(RR0t readlines(RtnumberOfBytesHint((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR5s  cCs|jj||dS(N(R0tseek(Rtoffsettwhence((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR7scCs0|dkr|jjn|jj|dS(N(RR0ttruncate(Rtsize((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR:s cCs|jj|dS(N(R0twrite(Rtstring((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR<scCs|jj|dS(N(R0t writeline(RtsequenceOfStrings((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt writelinesscCs |jjS(N(R0tnext(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRAscCs_tt|j|jdkr@tj|j|j|_ntj |j|j |_ |S(s!Open the file and return ourself.N( R R.RRRR topenRt_osModetfdopent_FileOpen__modeR/(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs cCs)|jjtt|j|||S(s Close the file.(R0tcloseR R.R(RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs trcOstt|j|||d}t|dkrPd|dkrPtj}nH|ddkrltj}n,|ddkrtjtj B}n tj}|ddkr|tj B}nd|_ ||_ ||_ dS(s: Arguments: None Returns: Nothing it+iRGtwtaN(R R.R RtlenR tO_RDWRtO_RDONLYtO_WRONLYtO_TRUNCtO_APPENDR/REt_FileOpen__osMode(RRtmodeRRtosMode((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR s"     cCs|S(N((R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyt__iter__scCs|jS(N(RQ(R((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRCsN(RRRRR R!R"R0R1R2R4RR5R tSEEK_SETR7R:R<R@RARRR RTRC(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR.s"          tFileLockcBs;eZdZejdZddZdZdZ RS(sThe FileLock object; a context manager providing interlocked access on a file. The file is created, if necessary. Class attributes: log (logging.Logger) - logger for this class Attributes: _timeout - timeout in seconds (None = no timeout) sutils.FileLockcOs&tt|j||||_dS(s Arguments: filePath - (str) path to file mode - (str) open mode timeout - (int) timeout in seconds; may be None Returns: Nothing N(R RVR t_timeout(RRRRttimeoutRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR :s cCs tt|j|jtjkr7tj}d}ntj}d}|j dk r|j j dj d|jd|j d|t|j tdj d|jd|j tj|j|WdQXn8|j j d j d|jd|tj|j||S( s_If the open mode is read-only the file is locked shared else it is locked exclusively. tsharedt exclusives'attempting to lock {f} in {s}s mode {m}tftstms!Could not lock {f} in {s} secondsNsattempting to lock {f} mode {m}(R RVRRCR RMtfcntltLOCK_SHtLOCK_EXRWRR!tdebugtformatRRt_tflockR0(Rt flockModetlockModeString((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRGs(         cCs`tj|jtj|tk rD|jjdjd|jnt t |j |||S(s Unlocks and closes the file.sreleased lock {f}R[( R^RdR0tLOCK_UNRR!RaRbRR RVR(RRRR((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRds  "N( RRRRR R!RR RR(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRV&s   tFileTempcBs8eZdZejdZddddZdZRS(sThe FileTemp object; a context manager providing temporary files with specified (or default) owner and permissions. An optional destination parameter specifies the location to which the temp file should be moved at exit, if no exception is encountered. The move, if specified, is performed after performing the owner manipulations. Class attributes: log (logging.Logger) - logger for this class Attributes: None sutils.FileTempcOs|tj}tt|j|ddd|d|sNttj}n|s]d}n||_||_ ||_ dS(s Arguments: owner - (str) the owner to set for the file ownerPerm - (str) the permissions to set for the owner destination (str) the path to which to move the temp file on exit Returns: Nothing isr+R itrwN( ttempfiletmkstempR RhR tstrR tgeteuidt_FileTemp__ownert_FileTemp__ownerPermt_FileTemp__destination(Rtownert ownerPermt destinationRRttmpFile((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyR s '   cCs6|}|dkr|jdk rytd|j|jg}|jtddjd|jg|jg}|j|jj td|j|jg}|jWqt k r}|}qXn|dk s|jdkry#td|jg}|jWqqXnt t |j |||S(Ntchowntchmodt=tutmvtrm(RRpRRnRR)tjoinRoR0RFt ExceptionR RhR(RRRRt exceptionR,tex((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRs* *   N( RRRRR R!RR R(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyRhws  (Rt __future__RterrnoR^tgettexttgrpRR tstatRjttimeRRRtinstalltobjectRR$R.RVRh(((s7/usr/lib/python2.7/site-packages/vdo/utils/FileUtils.pyts$          ;=QTransaction.pyo000064400000013715147221674750007610 0ustar00 .t_c@sjdZddlmZddlZddlZddlZejddefdYZdZ dS(s~ Transaction - provides transactional support $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Transaction.py#1 $ i(twrapsNt TransactioncBsYeZdZiZedZdZddZdZ edZ dZ RS(s%Client-visible transaction object. cCs|jdS(s<Returns the current transaction for the current thread. i(t_threadTransactionList(tcls((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt transaction-scCs|jj|dS(sAdds callable undoStage to transaction stages. Arguments: undoStage (callable) - callable to execute as part of transaction roll-back N(t_Transaction__undoStagestappend(tselft undoStage((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt addUndoStage4scCs tdS(s+Sets the message to handle if there is an exception. If message is specified and an exception occurs the exception will be appended to the message using "; {0}" where "{0}" represents the exception. If message is not specified, the exception will be coerced to a string and passed to handleMessage. Specifying handleMessage as None will clear both handleMessage and message. Arguments: handleMessage (callable) - method to handle message message (string) - message N(tNotImplementedError(Rt handleMessagetmessage((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt setMessage>scCs tt|jg|_dS(N(tsuperRt__init__R(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRTscCsQd}tjj}y|j|}Wn$tk rLg}||j|dtffdYtfd}|S(sGMethod decorator providing transactional capabilities to the method. t _TransactioncsPeZdZedZedZdZfdZddZ RS(sYDecorator-local transaction object providing actual transaction capabilities. cSs |jj||jS(s`Adds, and returns, a transaction to the transaction list for the current thread. (RRR(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytaddTransactionscSs|jjdS(sBRemoves the current transaction for for the current thread. N(Rtpop(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytremoveTransactionscSs|jdk r_|jdk rI|jtdj|jt|q_|jt|n|j}|jx-|D]%}y |Wq}tk rq}Xq}WdS(sPerforms the undo processing of the transaction. Exceptions from the undo stages are ignored. Arguments: exception - the exception which resulted in undo being called s{0}; {1}N( t_Transaction__handleMessageRt_Transaction__messaget_tformattstrRtreverset Exception(Rt exceptiont undoStagesR((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytundos      cs)t|jd|_d|_dS(N(RRRR!R"(R(R(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRs cSs1||_|jdkr$d|_n ||_dS(N(R!RR"(RR R ((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyR s  N( RRRRRR R*RRR ((R(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRs   cszj}d}zVy||}Wn<tk rf}|j|t||tjdnXWdjX|S(sDWrapper method providing transactional processing capabilities. iN(RRR'R*ttypetsystexc_infoR (targstkwargsRtresulttex(Rtfunc(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytwraps  $ (RR(R2R3((RR2s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt transactionalzsJ( Rt functoolsRtgettextR,RtinstalltobjectRR4(((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyts    X__init__.pyc000064400000074651147221674750007054 0ustar00 ;Xc@sbdZddlmZddlmZmZmZddlm Z m Z ddl Z ddl m ZddlmZddlZddlZddlZejeZddlZddlZddlZddlZddlZeryddlZWq(ek rdZdZq(Xn ddlZddl Z erIddl!Z!nddl"Z"dd l#m$Z$dd l%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2dd l3m4Z4m5Z5m6Z6m7Z7m8Z8dd l9m:Z:dd lm;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZIddddddddddddddddddd d!d"d#d$d%d&gZJeKejeArejLnejMd'd(ZNd)d*d+d,d-d.d/gZOd0d1gZPdd2l9mQZQd3ZReBd3ZSeBd4ZTeKejUjVd5pEd6ZWd7eXfd8YZYeArejZj[Z\e]e\ejZj^gZ_d9Z`n d:Z`ddeaddead;Zbd<Zcd=ZdedZeydd>lfmgZdWnek rnXd?d@ZhdAdBZiedkr.dAdCZindDZjeArRdEZkdFZln(ddGlmmZmmnZndHZkdIZle;ekdJe;eldKdLZodMZpdNZqeBdNZrddOZsdPZtetjudQZvdRZwdSZxdZyeBdTZzdVZ{dWdAddXZ|dWdAdYZ}eAr?dWdAdZZ~ndWdAd[Z~e;e~d\e4d]d^d_d`dQdaZe]dbjZe]dcjZe]d3ddgZddedfZyddglmZWn&ek rdZeaZdhZn4XeZdNZeBdiZeAr(djZn dkZe;edldmZejdnkriddol mZnddpl m ZeZdqZyejdreZWnek reaZnXddsZerejZnejeZdtZduZdvZe4d]d`d_dwdxdydzed{ZdZdZdZdZdZdZdS(s4passlib.utils -- helpers for writing password hashesi(tJYTHON(t b2a_base64t a2b_base64tError(t b64encodet b64decodeN(tlookup(tupdate_wrappersnot present under Jython(twarn( t BASE64_CHARSt AB64_CHARSt HASH64_CHARSt BCRYPT_CHARSt Base64EnginetLazyBase64Engineth64th64bigtbcrypt64t ab64_encodet ab64_decodet b64s_encodet b64s_decode(tdeprecated_functiontdeprecated_methodtmemoized_propertyt classpropertyt hybrid_method(tExpectedStringError(tadd_doct join_bytestjoin_byte_valuestjoin_byte_elemstirangetimaptPY3tut join_unicodetunicodetbyte_elem_valuet nextgettertunicode_or_bytes_typestget_method_functiontsuppress_causeRtsys_bitstunix_crypt_schemestrounds_cost_valuestconsteqtsaslprept xor_bytest render_bytest is_same_codect is_ascii_safetto_bytest to_unicodet to_native_strt has_cryptt test_cryptt safe_crypttticktrngt getrandbytest getrandstrtgenerate_passwordtis_crypt_handlertis_crypt_contextthas_rounds_infot has_salt_infoig?t sha512_cryptt sha256_cryptt sha1_crypttbcryptt md5_cryptt bsdi_cryptt des_crypttlineartlog2(tMissingBackendErrortt tPASSLIB_MAX_PASSWORD_SIZEit SequenceMixincBsMeZdZdZdZdZdZdZdZdZ RS(s helper which lets result object act like a fixed-length sequence. subclass just needs to provide :meth:`_as_tuple()`. cCstddS(Nsimplement in subclass(tNotImplemented(tself((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt _as_tuplescCst|jS(N(treprRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__repr__scCs|j|S(N(RS(RRtidx((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt __getitem__scCst|jS(N(titerRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__iter__scCst|jS(N(tlenRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__len__scCs|j|kS(N(RS(RRtother((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__eq__scCs|j| S(N(R](RRR\((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__ne__s( t__name__t __module__t__doc__RSRURWRYR[R]R^(((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRPs      cCsetjt|j}|s"tS|j|}|rJ|jtkrJtS|t |djt kS(s*test if function accepts specified keywordi( tinspectt signatureR)t parameterstFalsetgettkindt _VAR_ANY_SETtTruetlistt _VAR_KEYWORD(tfunctkeytparamstarg((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytaccepts_keywordscCs1tjt|}||jkp0|jdk S(s*test if function accepts specified keywordN(Rbt getargspecR)targstkeywordstNone(RlRmtspec((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRpsc st|tr|g}nt|j}|rt|trK|g}nxE|D]:|rp|krpqRn|krR|jqRqRWn|rx|D] tfd|Drqn|r&xt|D]8\}} t| rPn|rt| |rPqqWt|}nu|rxltt |D]I\} } t| |r?t|| }||d| kst Pq?q?Wd}nd}|j |qWn|st ||_ndS(s helper to update mixin classes installed in target class. :param target: target class whose bases will be modified. :param add: class / classes to install into target's base class list. :param remove: class / classes to remove from target's base class list. :param append: by default, prepends mixins to front of list. if True, appends to end of list instead. :param after: optionally make sure all mixins are inserted after this class / classes. :param before: optionally make sure all mixins are inserted before this class / classes. :param dryrun: optionally perform all calculations / raise errors, but don't actually modify the class. c3s|]}t|VqdS(N(t issubclass(t.0tbase(tmixin(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys siiN( t isinstancettypeRjt __bases__tremovetanyt enumerateRvRZtreversedtAssertionErrortinsertttuple( ttargettaddR}tappendtbeforetaftertdryruntbasesRVRxtend_idx((Rys:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytupdate_mixin_classessB      ccs|dkrtdnt|tjrqt|}d}x||krm||}|||!V|}qBWnt|tjrt|}xdtrtj ||}yt |}Wnt k rPnXtj |f|VqWn t ddS(s8 split iterable into chunks of elements. issize must be positive integerissource must be iterableN(t ValueErrorRzt collectionstSequenceRZtIterableRXRit itertoolstislicetnextt StopIterationtchaint TypeError(tsourcetsizetendtitntitrt chunk_itrtfirst((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytbatchs&        cCs5t|tr6t|ts-tdnt}nBt|trlt|tsctdnt}n tdt|t|k}|r|}d}n|s|}d}n|rxht||D]\}}|||AO}qWn:x7t||D]&\}}|t|t|AO}qW|dkS(sCheck two strings/bytes for equality. This function uses an approach designed to prevent timing analysis, making it appropriate for cryptography. a and b must both be of the same type: either str (ASCII only), or any type that supports the buffer protocol (e.g. bytes). Note: If a and b are of different lengths, or if an error occurs, a timing attack could theoretically reveal information about the types and lengths of a and b--but not their values. s)inputs must be both unicode or both bytesii( RzR%RRetbytesR"RZtziptord(tlefttrightt is_py3_bytest same_sizettmptresulttltr((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR./s,     (tcompare_digestt,cCsX|j}|j|r(|d }n|s2gSg|j|D]}|j^qBS(sRsplit comma-separated string into list of elements, stripping whitespace. i(tstriptendswithtsplit(Rtseptelem((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt splitcommazs   tvaluecst|ts+tdt|fntjtjtfd|D}tj d|}|sxt Stj }||dr||dst d|ntj }n|}tj}tj}tj}tj}tj} tj} tj} tj} tj} xv|D]n}| s=td| sVtd||rut d |n||rt d |n||rt d |n||rt d |n| |rt d |n| |rt d|n| |r/t d|n| |rNt d|n| |rmt d|n||rt d|qqW|S(sNormalizes unicode strings using SASLPrep stringprep profile. The SASLPrep profile is defined in :rfc:`4013`. It provides a uniform scheme for normalizing unicode usernames and passwords before performing byte-value sensitive operations such as hashing. Among other things, it normalizes diacritic representations, removes non-printing characters, and forbids invalid characters such as ``\n``. Properly internationalized applications should run user passwords through this function before hashing. :arg source: unicode string to normalize & validate :param param: Optional noun identifying source parameter in error messages (Defaults to the string ``"value"``). This is mainly useful to make the caller's error messages make more sense contextually. :raises ValueError: if any characters forbidden by the SASLPrep profile are encountered. :raises TypeError: if input is not :class:`!unicode` :returns: normalized unicode string .. note:: This function is not available under Jython, as the Jython stdlib is missing the :mod:`!stringprep` module (`Jython issue 1758320 `_). .. versionadded:: 1.6 s$input must be unicode string, not %sc3s3|])}|s|r'tn|VqdS(N(t_USPACE(Rwtc(t in_table_b1t in_table_c12(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys stNFKCiismalformed bidi sequence in s$failed to strip B.1 in mapping stages(failed to replace C.1.2 in mapping stages$unassigned code points forbidden in s control characters forbidden in s$private use characters forbidden in s"non-char code points forbidden in ssurrogate codes forbidden in s!non-plaintext chars forbidden in s!non-canonical chars forbidden in s1display-modifying / deprecated chars forbidden instagged characters forbidden in sforbidden bidi character in (RzR%RR{t stringprepRRR$t unicodedatat normalizet_UEMPTYt in_table_d1Rt in_table_d2t in_table_a1tin_table_c21_c22t in_table_c3t in_table_c4t in_table_c5t in_table_c6t in_table_c7t in_table_c8t in_table_c9R(Rtparamtdatat is_ral_chartis_forbidden_bidi_charRRRRRRRRRR((RRs:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR/sf,                          cCstdtdS(sstub for saslprep()s>saslprep() support requires the 'stringprep' module, which is N(tNotImplementedErrort_stringprep_missing_reason(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR/scGsHt|tr!|jd}n|td|D}|jdS(s&Peform ``%`` formating using bytes in a uniform manner across Python 2/3. This function is motivated by the fact that :class:`bytes` instances do not support ``%`` or ``{}`` formatting under Python 3. This function is an attempt to provide a replacement: it converts everything to unicode (decoding bytes instances as ``latin-1``), performs the required formatting, then encodes the result to ``latin-1``. Calling ``render_bytes(source, *args)`` should function roughly the same as ``source % args`` under Python 2. slatin-1css3|])}t|tr'|jdn|VqdS(slatin-1N(RzRtdecode(RwRo((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(RzRRRtencode(RRrR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR1s  cCstj|dS(Ntbig(tintt from_bytes(R((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt bytes_to_int"scCs|j|dS(NR(R4(Rtcount((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt int_to_bytes$s(thexlifyt unhexlifycCstt|dS(Ni(RR(R((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR)scCstd|d>|S(Ns%%0%dxi(R(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR+ss/decode byte string as single big-endian integers/encode integer as single big-endian byte stringcCs#tt|t|At|S(s;Perform bitwise-xor of two byte strings (must be same size)(RRRZ(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR01scCsBt|}||kr6||d|}||| S|| SdS(s;repeat or truncate string, so it has length iN(RZ(RRtcurtmult((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt repeat_string5s    tcCs^t|}||krR|dkrBt|tr9tnt}n||||S|| SdS(s>right-pad or truncate string, so it has length N(RZRtRzR%t_UNULLt_BNULL(RRtpadR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytright_pad_stringAs    t aA:#!tasciicCstj|tkS(sRTest if codec is compatible with 7-bit ascii (e.g. latin-1, utf-8; but not utf-16)(t_ASCII_TEST_UNICODERt_ASCII_TEST_BYTES(tcodec((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytis_ascii_codecQscCs<||krtS|o|s tSt|jt|jkS(s3Check if two codec names are aliases for same codec(RiRet _lookup_codectname(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR2Us   sics5t|trtnttfd|DS(s<Check if string (bytes or unicode) contains only 7-bit asciic3s|]}|kVqdS(N((RwR(R(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys bs(RzRt_B80t_U80tall(R((Rs:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR3_ssutf-8cCs}|s tt|trN|rGt|| rG|j|j|S|Sn+t|trj|j|St||dS(sHelper to normalize input to bytes. :arg source: Source bytes/unicode to process. :arg encoding: Target encoding (defaults to ``"utf-8"``). :param param: Optional name of variable/noun to reference when raising errors :param source_encoding: If this is specified, and the source is bytes, the source will be transcoded from *source_encoding* to *encoding* (via unicode). :raises TypeError: if source is not unicode or bytes. :returns: * unicode strings will be encoded using *encoding*, and returned. * if *source_encoding* is not specified, byte strings will be returned unchanged. * if *source_encoding* is specified, byte strings will be transcoded to *encoding*. N(RRzRR2RRR%R(RtencodingRtsource_encoding((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR4ds  cCsN|s tt|tr|St|tr;|j|St||dS(sHelper to normalize input to unicode. :arg source: source bytes/unicode to process. :arg encoding: encoding to use when decoding bytes instances. :param param: optional name of variable/noun to reference when raising errors. :raises TypeError: if source is not unicode or bytes. :returns: * returns unicode strings unchanged. * returns bytes strings decoded using *encoding* N(RRzR%RRR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR5s   cCsBt|tr|j|St|tr/|St||dS(N(RzRRR%R(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR6s  cCsBt|tr|St|tr/|j|St||dS(N(RzRR%RR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR6s  s>Take in unicode or bytes, return native string. Python 2: encodes unicode using specified encoding, leaves bytes alone. Python 3: leaves unicode alone, decodes bytes using specified encoding. :raises TypeError: if source is not unicode or bytes. :arg source: source unicode or bytes string. :arg encoding: encoding to use when encoding unicode or decoding bytes. this defaults to ``"utf-8"``. :param param: optional name of variable/noun to reference when raising errors. :returns: :class:`str` instance t deprecateds1.6tremoveds1.7cCst||ddS(s'deprecated, use to_native_str() insteadRthash(R6(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt to_hash_strss true t yes y on 1 enable enableds#false f no n off 0 disable disabledtnonetbooleancCs|ttdgkstt|tr|jj}|tkrLtS|t kr\tS|t krl|St d||fn-t|t r|S|dkr|St |SdS(s\ helper to convert value to boolean. recognizes strings such as "true", "false" sunrecognized %s value: %rN( RiReRtRRzR(tlowerRt _true_sett _false_sett _none_setRtbool(RRRtclean((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytas_bools    (tcryptcCsdS(N(Rt(tsecretR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9ss*:!cCst|tra|}y|jd}Wntk r<dSX|jd|ksatdnt|kr|tdnt|tr|jd}nt ||}| s|dt krdS|S(Nsutf-8s"utf-8 spec says this can't happen!snull character in secretRi( RzRRtUnicodeDecodeErrorRtRRt_NULLRt_cryptt_invalid_prefixes(RRtorigR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9s    cCst|tr!|jd}nt|kr<tdnt|tr]|jd}nt||}|svdS|jd}|dtkrdS|S(Nsutf-8snull character in secretRi( RzR%RRRRRtRR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9s sWrapper around stdlib's crypt. This is a wrapper around stdlib's :func:`!crypt.crypt`, which attempts to provide uniform behavior across Python 2 and 3. :arg secret: password, as bytes or unicode (unicode will be encoded as ``utf-8``). :arg hash: hash or config string, as ascii bytes or unicode. :returns: resulting hash as ascii unicode; or ``None`` if the password couldn't be hashed due to one of the issues: * :func:`crypt()` not available on platform. * Under Python 3, if *secret* is specified as bytes, it must be use ``utf-8`` or it can't be passed to :func:`crypt()`. * Some OSes will return ``None`` if they don't recognize the algorithm being used (though most will simply fall back to des-crypt). * Some OSes will return an error string if the input config is recognized but malformed; current code converts these to ``None`` as well. cCs%|r |stt|||kS(scheck if :func:`crypt.crypt` supports specific hash :arg secret: password to test :arg hash: known hash of password to use as reference :returns: True or False (RR9(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR8Astwin32(tclock(ttimecCsBtjd|}|r>td|jdjdDSdS(shelper to parse version strings(\d+(?:\.\d+)+)css|]}t|VqdS(N(R(RwR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys Ysit.N(tretsearchRtgroupRRt(Rtm((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt parse_versionUs&ic Csddlm}t|drdt|drdy|j}Wqdtk r`|jd}qdXntd|ttdrtjndt t t j t j trtjd jd nd f}t||jd jd S(s.generate prng seed value from system resourcesi(tsha512tgetstatet getrandbitsiis%s %s %s %.15f %.15f %stgetpidi slatin-1isutf-8iiN(thashlibR thasattrR RR R#tosR RttidtobjectRRt has_urandomturandomRRRt hexdigest(RR ttext((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytgenseedqs     (cs)s tSfd}t|S(s]return byte-string containing *count* number of randomly generated bytes, using specified rngc3sMjd>}d}x-|krH|d@V|dL}|d7}qWdS(Niiii(R (RR(RR;(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pythelpers   (t_BEMPTYR(R;RR((RR;s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR<s csdkrtdntdkrBtdndkrVSfd}ttrt|St|SdS(s|return string containing *count* number of chars/bytes, whose elements are drawn from specified charset, using specified rngiscount must be >= 0salphabet must not be emptyic3sTjd}d}x1|krO|V|}|d7}qWdS(Nii(t randrange(RR(tcharsetRtlettersR;(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRs   N(RRZRzR%R$R(R;RRR((RRRR;s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR=s      t42346789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrstuvwxyzs2.0t replacements/passlib.pwd.genword() / passlib.pwd.genphrase()i cCstt||S(swgenerate random password using given length & charset :param size: size of password. :param charset: optional string specified set of characters to draw from. the default charset contains all normal alphanumeric characters, except for the characters ``1IiLl0OoS5``, which were omitted due to their visual similarity. :returns: :class:`!str` containing randomly generated password. .. note:: Using the default character set, on a OS with :class:`!SystemRandom` support, this function should generate passwords with 5.7 bits of entropy per character. (R=R;(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR>sRt setting_kwdst context_kwdstverifyRtidentifycstfdtDS(s4check if object follows the :ref:`password-hash-api`c3s|]}t|VqdS(N(R(RwR(tobj(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(Rt_handler_attrs(R#((R#s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR?st needs_updatet genconfigtgenhashtencryptcstfdtDS(sOcheck if object appears to be a :class:`~passlib.context.CryptContext` instancec3s|]}t|VqdS(N(R(RwR(R#(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(Rt_context_attrs(R#((R#s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR@scCs%d|jko$t|dddk S(s_check if handler provides the optional :ref:`rounds information ` attributestroundst min_roundsN(RtgetattrRt(thandler((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRAscCs%d|jko$t|dddk S(s[check if handler provides the optional :ref:`salt information ` attributestsaltt min_salt_sizeN(RR,Rt(R-((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRB st(snames setting_kwdsR R!shashR"(R%R&R'R!R(R"(Ratpasslib.utils.compatRtbinasciiRRRt_BinAsciiErrortbase64RRRtcodecsRRt functoolsRRRbtloggingt getLoggerR_tlogtmathRtsystrandomRRt ImportErrorRtRRRttypestwarningsRtpasslib.utils.binaryR R R R R RRRRRRRRtpasslib.utils.decorRRRRRt passlib.excRRRRRR R!R"R#R$R%R&R'R(R)R*t__all__RtmaxsizetmaxintR+R,R-RLRRRtenvironRftMAX_PASSWORD_SIZERRPt Parametert VAR_KEYWORDRktsettVAR_POSITIONALRhRpReRRR.t str_consteqthmacRRR/R1RRRRR0RRRRRRRRR2RRR3R4R5R6RRRRRRRRR7R9RiRRR8tplatformRttimerR:R RRRRt SystemRandomR;tRandomR<R=t _52charsetR>R$R?R)R@RARB(((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytsJ              X(d .       V  >                 %            !    Timeout.pyo000064400000005215147221674750006745 0ustar00 .t_c@sBdZddlZdefdYZdefdYZdS(s Timeout - context manager that implements a timeout. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Timeout.py#1 $ iNt TimeoutErrorcBs#eZdZddZdZRS(s(Exception raised when a block times out.cOs;tt|j|||dkr.d}n||_dS(Nttimeout(tsuperRt__init__tNonet_msg(tselftmsgtargstkwargs((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyR s  cCs|jS(N(R(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt__str__%sN(t__name__t __module__t__doc__RRR (((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRs tTimeoutcBs5eZdZdZdZddZdZRS(sContext manager for running a block of commands under a timeout. If the block times out, a TimeoutError is raised. Arguments: seconds (int) - timeout in seconds msg (str) - message to supply to TimeoutError cs5tjtjfd_tjjS(Ncs jS(N(t_timeout(t_signumt_frame(R(s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt;s(tsignaltSIGALRMt_Timeout__oldHandlertalarmt_Timeout__seconds(R((Rs5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt __enter__8s cCs'tjdtjtj|jtS(Ni(RRRRtFalse(Rt exceptionTypetexceptionValuet traceback((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt__exit__As cCs||_||_d|_dS(N(Rt _Timeout__msgRR(RtsecondsR((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRJs  cCst|jdS(s+ Method invoked if the alarm goes off. N(RR(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRRsN(R R R RRRRR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyR)s  (R Rt ExceptionRtobjectR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyts  Transaction.py000064400000016245147221674750007432 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ Transaction - provides transactional support $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Transaction.py#1 $ """ from functools import wraps import gettext import sys import threading gettext.install('Transaction') class Transaction(object): """Client-visible transaction object. """ # A dictionary mapping thread identifier to a list of the thread's # transactions. __transactionLists = {} ###################################################################### # Public methods ###################################################################### @classmethod def transaction(cls): """Returns the current transaction for the current thread. """ return cls._threadTransactionList()[-1] ###################################################################### def addUndoStage(self, undoStage): """Adds callable undoStage to transaction stages. Arguments: undoStage (callable) - callable to execute as part of transaction roll-back """ self.__undoStages.append(undoStage) ###################################################################### def setMessage(self, handleMessage, message = None): """Sets the message to handle if there is an exception. If message is specified and an exception occurs the exception will be appended to the message using "; {0}" where "{0}" represents the exception. If message is not specified, the exception will be coerced to a string and passed to handleMessage. Specifying handleMessage as None will clear both handleMessage and message. Arguments: handleMessage (callable) - method to handle message message (string) - message """ raise NotImplementedError ###################################################################### # Overridden methods ###################################################################### def __init__(self): super(Transaction, self).__init__() self.__undoStages = [] ###################################################################### # Protected methods ###################################################################### @classmethod def _threadTransactionList(cls): """Returns the transaction list for the current thread, creating it if need be. Returns: list of Transactions """ transactionList = None threadId = threading.currentThread().ident try: transactionList = cls.__transactionLists[threadId] except KeyError: transactionList = [] cls.__transactionLists[threadId] = transactionList return transactionList ###################################################################### def _undoStages(self): """Returns the list of undo stages for the transaction. Returns: list of undo stages """ return self.__undoStages ###################################################################### # Private methods ###################################################################### ######################################################################## def transactional(func): """Method decorator providing transactional capabilities to the method. """ ###################################################################### class _Transaction(Transaction): """Decorator-local transaction object providing actual transaction capabilities. """ #################################################################### # Public methods #################################################################### @classmethod def addTransaction(cls): """Adds, and returns, a transaction to the transaction list for the current thread. """ cls._threadTransactionList().append(cls()) return cls.transaction() #################################################################### @classmethod def removeTransaction(cls): """Removes the current transaction for for the current thread. """ cls._threadTransactionList().pop() #################################################################### def undo(self, exception): """Performs the undo processing of the transaction. Exceptions from the undo stages are ignored. Arguments: exception - the exception which resulted in undo being called """ # Handle any message that was set for the transaction. if self.__handleMessage is not None: if self.__message is not None: self.__handleMessage(_("{0}; {1}").format(self.__message, str(exception))) else: self.__handleMessage(str(exception)) # Perform the undo processing. undoStages = self._undoStages()[:] undoStages.reverse() for undoStage in undoStages: try: undoStage() except Exception: pass #################################################################### # Overridden methods #################################################################### def __init__(self): super(_Transaction, self).__init__() self.__handleMessage = None self.__message = None #################################################################### def setMessage(self, handleMessage, message = None): self.__handleMessage = handleMessage if self.__handleMessage is None: self.__message = None else: self.__message = message #################################################################### # Protected methods #################################################################### #################################################################### # Private methods #################################################################### ###################################################################### @wraps(func) def wrap(*args, **kwargs): """Wrapper method providing transactional processing capabilities. """ transaction = _Transaction.addTransaction() result = None try: result = func(*args, **kwargs) except Exception as ex: transaction.undo(ex) # Re-raise the Exception, preserving the stack trace from its origin. #pylint: disable=E0710 raise type(ex), ex, sys.exc_info()[2] finally: _Transaction.removeTransaction() return result return wrap FileUtils.py000064400000035530147221674750007043 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ FileUtils - Provides dmmgmnt file-related capabilities. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/FileUtils.py#1 $ """ from __future__ import print_function import errno import fcntl import gettext import grp import logging import os import stat import tempfile import time from .Command import Command from .Timeout import Timeout, TimeoutError gettext.install("utils") ######################################################################## class FileBase(object): """The FileBase object; provides basic file control. Class attributes: log (logging.Logger) - logger for this class Attributes: None """ log = logging.getLogger('utils.FileBase') ###################################################################### # Public methods ###################################################################### @property def path(self): return self.__filePath ###################################################################### # Overridden methods ###################################################################### def __init__(self, filePath, *args, **kwargs): """ Arguments: None Returns: Nothing """ super(FileBase, self).__init__() self.__filePath = os.path.realpath(filePath) self.__fd = kwargs.get("fd", None) ###################################################################### def __enter__(self): return self ###################################################################### def __exit__(self, exceptionType, exceptionValue, traceback): # Don't suppress exceptions. return False ###################################################################### # Protected methods ###################################################################### @property def _fd(self): return self.__fd ###################################################################### # pylint: disable=E0102 # pylint: disable=E1101 @_fd.setter def _fd(self, value): self.__fd = value ###################################################################### # Private methods ###################################################################### ######################################################################## class FileTouch(FileBase): """The FileTouch object; touches the file. Class attributes: log (logging.Logger) - logger for this class Attributes: None """ log = logging.getLogger('utils.FileTouch') ###################################################################### # Public methods ###################################################################### ###################################################################### # Overridden methods ###################################################################### def __init__(self, filePath, *args, **kwargs): """ Arguments: None Returns: Nothing """ super(FileTouch, self).__init__(filePath, *args, **kwargs) ###################################################################### def __enter__(self): """Make certain the file exists and return ourself.""" super(FileTouch, self).__enter__() if self._fd is None: # Make certain the file exists and that we have access to it. dirPath = os.path.dirname(self.path) # Make certain the directory exists. # N.B.: The names may not be sanitized for use with a shell! if not os.access(dirPath, os.F_OK): cmd = Command(["mkdir", "-p", dirPath]) cmd.run() # Make certain the target exists. if not os.access(self.path, os.F_OK): self._createFile() return self ###################################################################### # Protected methods ###################################################################### def _createFile(self): """Creates the targe file.""" # N.B.: The names may not be sanitized for use with a shell! cmd = Command(["touch", self.path]) cmd.run() ###################################################################### # Private methods ###################################################################### ######################################################################## class FileOpen(FileTouch): """The FileOpen object; provides basic access to a file. Class attributes: log (logging.Logger) - logger for this class Attributes: None """ log = logging.getLogger('utils.FileOpen') ###################################################################### # Public methods ###################################################################### @property def file(self): return self.__file ###################################################################### def flush(self): self.file.flush() ###################################################################### def read(self, numberOfBytes = -1): return self.file.read(numberOfBytes) ###################################################################### def readline(self, numberOfBytes = -1): return self.file.readline(numberOfBytes) ###################################################################### def readlines(self, numberOfBytesHint = None): # The documentation for readlines is not consistent with the other # read methods as to what constitutes a valid default parameter. # Testing shows that neither None nor -1 are acceptable so we # use None and specifically check for it. if numberOfBytesHint is None: return self.file.readlines() else: return self.file.readlines(numberOfBytesHint) ###################################################################### def seek(self, offset, whence = os.SEEK_SET): self.file.seek(offset, whence) ###################################################################### def truncate(self, size = None): # The documentation for truncate indicates that without an argument # it truncates to the current file position. Testing shows that # neither None nor -1 are acceptable as parameters so we use None # and specifically check for it. if size is None: self.file.truncate() else: self.file.truncate(size) ###################################################################### def write(self, string): self.file.write(string) ###################################################################### def writelines(self, sequenceOfStrings): self.file.writeline(sequenceOfStrings) ###################################################################### # Overridden methods ###################################################################### def next(self): return self.file.next() ###################################################################### def __enter__(self): """Open the file and return ourself.""" super(FileOpen, self).__enter__() if self._fd is None: self._fd = os.open(self.path, self._osMode) self.__file = os.fdopen(self._fd, self.__mode) return self ###################################################################### def __exit__(self, exceptionType, exceptionValue, traceback): """ Close the file.""" self.file.close() return super(FileOpen, self).__exit__(exceptionType, exceptionValue, traceback) ###################################################################### def __init__(self, filePath, mode = "r", *args, **kwargs): """ Arguments: None Returns: Nothing """ super(FileOpen, self).__init__(filePath, *args, **kwargs) osMode = None if (len(mode) > 1) and ("+" in mode[1:]): osMode = os.O_RDWR elif mode[0] == "r": osMode = os.O_RDONLY elif mode[0] == "w": osMode = os.O_WRONLY | os.O_TRUNC else: osMode = os.O_RDWR if mode[0] == "a": osMode = osMode | os.O_APPEND self.__file = None self.__mode = mode self.__osMode = osMode ###################################################################### def __iter__(self): return self ###################################################################### # Protected methods ###################################################################### @property def _osMode(self): return self.__osMode ###################################################################### # Private methods ###################################################################### ######################################################################## class FileLock(FileOpen): """The FileLock object; a context manager providing interlocked access on a file. The file is created, if necessary. Class attributes: log (logging.Logger) - logger for this class Attributes: _timeout - timeout in seconds (None = no timeout) """ log = logging.getLogger('utils.FileLock') ###################################################################### # Public methods ###################################################################### ###################################################################### # Overridden methods ###################################################################### def __init__(self, filePath, mode, timeout=None, *args, **kwargs): """ Arguments: filePath - (str) path to file mode - (str) open mode timeout - (int) timeout in seconds; may be None Returns: Nothing """ super(FileLock, self).__init__(filePath, mode) self._timeout = timeout ###################################################################### def __enter__(self): """If the open mode is read-only the file is locked shared else it is locked exclusively. """ super(FileLock, self).__enter__() if self._osMode == os.O_RDONLY: flockMode = fcntl.LOCK_SH lockModeString = "shared" else: flockMode = fcntl.LOCK_EX lockModeString = "exclusive" if self._timeout is not None: self.log.debug("attempting to lock {f} in {s}s mode {m}" .format(f=self.path, s=self._timeout, m=lockModeString)) with Timeout(self._timeout, _( "Could not lock {f} in {s} seconds").format(f=self.path, s=self._timeout)): fcntl.flock(self.file, flockMode) else: self.log.debug("attempting to lock {f} mode {m}" .format(f=self.path, m=lockModeString)) fcntl.flock(self.file, flockMode) return self ###################################################################### def __exit__(self, exceptionType, exceptionValue, traceback): """ Unlocks and closes the file.""" fcntl.flock(self.file, fcntl.LOCK_UN) if exceptionType is not TimeoutError: self.log.debug("released lock {f}".format(f=self.path)) return super(FileLock, self).__exit__(exceptionType, exceptionValue, traceback) ###################################################################### # Protected methods ###################################################################### ###################################################################### # Private methods ###################################################################### ######################################################################## class FileTemp(FileOpen): """The FileTemp object; a context manager providing temporary files with specified (or default) owner and permissions. An optional destination parameter specifies the location to which the temp file should be moved at exit, if no exception is encountered. The move, if specified, is performed after performing the owner manipulations. Class attributes: log (logging.Logger) - logger for this class Attributes: None """ log = logging.getLogger('utils.FileTemp') ###################################################################### # Public methods ###################################################################### ###################################################################### # Overridden methods ###################################################################### def __init__(self, owner = None, ownerPerm = None, destination = None, *args, **kwargs): """ Arguments: owner - (str) the owner to set for the file ownerPerm - (str) the permissions to set for the owner destination (str) the path to which to move the temp file on exit Returns: Nothing """ tmpFile = tempfile.mkstemp() super(FileTemp, self).__init__(tmpFile[1], "r+", fd = tmpFile[0]) if not owner: owner = str(os.geteuid()) if not ownerPerm: ownerPerm = "rw" self.__owner = owner self.__ownerPerm = ownerPerm self.__destination = destination ###################################################################### def __exit__(self, exceptionType, exceptionValue, traceback): exception = exceptionType if (exception is None) and (self.__destination is not None): try: cmd = Command(["chown", self.__owner, self.path]) cmd.run() cmd = Command(["chmod", "=".join(["u", self.__ownerPerm]), self.path]) cmd.run() self.file.close() # need to close the file to save data before move. cmd = Command(["mv", self.path, self.__destination]) cmd.run() except Exception as ex: exception = ex if (exception is not None) or (self.__destination is None): try: cmd = Command(["rm", self.path]) cmd.run() except: pass return super(FileTemp, self).__exit__(exceptionType, exceptionValue, traceback) ###################################################################### # Protected methods ###################################################################### ###################################################################### # Private methods ###################################################################### Logger.py000064400000010457147221674750006363 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ Logger - VDO manager logging $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Logger.py#3 $ """ import logging import logging.handlers import os import sys from types import MethodType class Logger(object): """Wrappers and configuration methods for the Python logger. Attributes: logfile (string): the path to the logfile if specified. myname (string): name of the command being run. quiet (bool): if True, don't print to stdout. """ myname = os.path.basename(sys.argv[0]) quiet = False logfile = None ###################################################################### # Public methods ###################################################################### @classmethod def announce(cls, logger, msg): """Print a status message to stdout and log it as well.""" if not cls.quiet: print(msg) logger.info(msg) ###################################################################### @classmethod def configure(cls, name, logfile = None, debug = False): """Configure the logging system according to the arguments.""" cls.myname = name cls.logfile = logfile debugging = debug formatBase = ': %(levelname)s - %(message)s' debugBase = (': %(name)s' if debugging else '') + formatBase logger = logging.getLogger() logger.setLevel(logging.NOTSET) handler = logging.StreamHandler(sys.stderr) handler.setFormatter(logging.Formatter(cls.myname + debugBase)) handler.setLevel(logging.DEBUG if debugging else logging.WARNING) logger.addHandler(handler) if cls.logfile is not None: try: if os.path.exists(cls.logfile) and not os.path.isfile(cls.logfile): # Support /dev/stderr and the like. logstream = open(cls.logfile, "w") handler = logging.StreamHandler(stream=logstream) else: handler = logging.handlers.RotatingFileHandler(cls.logfile, maxBytes=10*1024*1024, backupCount=5) formatter = logging.Formatter('%(asctime)s %(name)s' + formatBase) handler.setFormatter(formatter) handler.setLevel(logging.DEBUG if debugging else logging.INFO) logger.addHandler(handler) except Exception as ex: logger.warn('Unable to configure logging to {logfile}: {ex}' .format(logfile=cls.logfile, ex=ex)) try: handler = logging.handlers.SysLogHandler(address='/dev/log') handler.setFormatter(logging.Formatter(cls.myname + formatBase)) handler.setLevel(logging.WARNING) logger.addHandler(handler) except Exception as ex: logger.warn('Unable to configure logging for rsyslog: {0}'.format(ex)) ###################################################################### @classmethod def getLogger(cls, name): """Returns a Python logger decorated with the announce method.""" logger = logging.getLogger(name) logger.announce = MethodType(cls.announce, logger, logger.__class__) return logger ###################################################################### @classmethod def loggingOptions(cls): """Return a list of strings containing the logging options specified.""" options = [ ] if cls.logfile is not None: options.append("--logfile=" + str(cls.logfile)) return options ###################################################################### # Overridden methods ###################################################################### def __init__(self): super(Logger, self).__init__() Command.py000064400000026673147221674750006531 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ Command - runs commands and manages their results $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Command.py#3 $ """ from .Logger import Logger from subprocess import Popen, PIPE import copy import logging import os import pipes import time class CommandError(Exception): """Exception raised to indicate an error running a command. Arguments: exitCode (int): The exit code of the command stdout (string): The output from the command stderr (string): The error output from the command message (string): The (localized) error text; will be formatted with the remaining arguments args: Arguments for formatting the message """ ###################################################################### # Public methods ###################################################################### def getExitCode(self): return self._exitCode ###################################################################### def getStandardError(self): return self._stderr ###################################################################### def logOutputs(self, logMethod): """Log the outputs of the failed command which generated this exception. Arguments: logMethod (callable): The method to log with """ logMethod(self._stdout) logMethod(self._stderr) ###################################################################### def setMessage(self, message, *args): """Set the error message in this exception. Arguments: message (string): The (localized) message text; will be formatted with *args args: Values to pass to the format of message """ self._message = message.format(*args) ###################################################################### # Overridden methods ###################################################################### def __init__(self, exitCode, stdout, stderr, message, *args): super(CommandError, self).__init__() self._exitCode = exitCode self._stdout = stdout self._stderr = stderr self.setMessage(message, args) ###################################################################### def __str__(self): return self._message ######################################################################## class Command(object): """Command encapsulates shell commands, runs them, and manages the result. Attributes: noRun (bool): if True, don't run the command, and always succeed shell (bool): if True, run this command using shell -c verbose (int): if > 0, print commands to stdout before executing them _commandList (list): command and its arguments """ defaultNoRun = False defaultVerbose = 0 log = logging.getLogger(Logger.myname + '.Command') ###################################################################### # Public methods ###################################################################### @classmethod def noRunMode(cls): """Returns True iff Commands default to noRun.""" return cls.defaultNoRun ###################################################################### @classmethod def setDefaults(cls, verbose = False, noRun = False): """Sets the verbose and noRun default values. Arguments: verbose: (boolean) If True, operate verbosely. noRun: (boolean) If True, do not actually execute. """ if noRun: cls.defaultNoRun = noRun cls.defaultVerbose = True if verbose: cls.defaultVerbose = verbose ###################################################################### def commandName(self): """Returns an identifier (argv[0]) for error messages.""" return self._commandList[0] ###################################################################### def run(self, **kwargs): """Run a command. Returns the output of running the command. Arguments: noThrow: If True, will return an empty string instead of throwing on error. retries: The number of times to try the command before giving up. Defaults to 1. shell: Indicate that this is a shell command stdin: If not None, the stream from which the command should take its input, defaults to None. strip: If True, strip leading and trailing whitespace from the command output before returning it. Exceptions: CommandError: if the command failed and noThrow is False """ retries = kwargs.get('retries', 1) stdin = kwargs.get('stdin', None) if not self.shell: self.shell = kwargs.get('shell', False) commandLine = self._getCommandLine() if retries > 1: self.log.debug("Waiting for '{0}'".format(commandLine)) try: for count in range(retries): if retries > 1: self.log.debug(" ... {0}/{1}".format(count, retries)) if self.verbose > 0: print(' ' + commandLine) self.log.info(commandLine) if self.noRun: return try: output = self._execute(stdin) return output.strip() if kwargs.get('strip', False) else output except CommandError as e: if count == (retries - 1): if retries > 1: e.setMessage(_("{0}: timed out after {1} seconds"), self.commandName(), retries) raise e time.sleep(1) except CommandError as e: if kwargs.get('noThrow', False): return '' raise e ###################################################################### # Overridden methods ###################################################################### def __init__(self, commandList, environment=None): super(Command, self).__init__() self.noRun = Command.defaultNoRun self.shell = False self.verbose = Command.defaultVerbose self._commandList = commandList if environment: self.env = copy.deepcopy(os.environ) for var, value in environment.items(): self.env[var] = value else: self.env = None ###################################################################### def __str__(self): ' '.join(self._commandList) ###################################################################### # Protected methods ###################################################################### def _checkResults(self, exitCode=0, stdout='', stderr=''): """Sets the result values of this object. Raises an exception if there was an error, or returns the output of the command if there was not. Arguments: exitCode (int): the process exit code stdout (str): the standard output stderr (str): the standard error logResults (bool): if True, the results will be logged Exceptions: CommandError: if exitCode is non-zero """ try: if (exitCode == 0): self.log.debug(_("{0}: command succeeded").format(self.commandName())) return stdout failureType = _('exit status') if exitCode > 0 else _('signal') status = _("{0}: command failed, {1} {2}").format(self.commandName(), failureType, abs(exitCode)) self.log.debug(status) raise CommandError(exitCode, stdout, stderr, status) finally: self.log.debug('stdout: ' + stdout.rstrip()) self.log.debug('stderr: ' + stderr.rstrip()) ###################################################################### def _execute(self, stdin): """Execute the command once. Returns the output of the command. Arguments: stdin: If not None, the stream from which the command should take its input. Exceptions: CommandError: if the command failed """ command = self._getCommandLine() if self.shell else self._commandList try: p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True, env=self.env, shell=self.shell) stdoutdata, stderrdata = p.communicate(stdin) return self._checkResults(p.returncode, "".join(stdoutdata), "".join(stderrdata)) except OSError as e: self._checkResults(e.errno, '', ': '.join([self.commandName(), e.strerror])) except CommandError as e: error = e._stderr.split(os.linesep)[0] if error: e.setMessage(error) raise e ###################################################################### def _getCommandLine(self): """Returns the appropriately quoted command line.""" return ' '.join(self._commandList if self.shell else map(pipes.quote, self._commandList)) ######################################################################## def runCommand(commandList, **kwargs): """Run a command. Returns the output of the command (but see Keyword Arguments). Arguments: commandList: The command as a list of strings. Keyword Arguments: environment: A dict of environment variables and their values to use for the command. noThrow: If True, will return an empty string instead of throwing on error. retries: The number of times to try the command before giving up. Defaults to 1. shell: Indicate that this is a shell command. stdin: If not None, the stream from which the command should take its input, defaults to None. strip: If True, strip leading and trailing whitespace from the command output before returning it. Exceptions: CommandError: if the command failed and noThrow is False """ return Command(commandList, kwargs.pop('environment', None)).run(**kwargs) ######################################################################## def tryCommandsUntilSuccess(commands, **kwargs): """Try each of a series of commands in turn until one succeeds. If all the commands fail, give up and raise an exception. Arguments: commands: A list of command lists Keyword Arguments: Supports all of the arguments which may be passed to runCommand(). Returns: the output of the first successful command Exceptions: CommandError: if none of the commands succeeds and the noThrow keyword option is False (or omitted); the error will be the one raised by the last command in the list """ error = None noThrow = kwargs.pop('noThrow', False) for command in commands: try: return runCommand(command, **kwargs) except CommandError as e: error = e if noThrow: error = None # Pylint thinks we can raise None here. if error is not None: #pylint: disable=E0702 raise error Timeout.pyc000064400000005215147221674750006731 0ustar00 .t_c@sBdZddlZdefdYZdefdYZdS(s Timeout - context manager that implements a timeout. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Timeout.py#1 $ iNt TimeoutErrorcBs#eZdZddZdZRS(s(Exception raised when a block times out.cOs;tt|j|||dkr.d}n||_dS(Nttimeout(tsuperRt__init__tNonet_msg(tselftmsgtargstkwargs((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyR s  cCs|jS(N(R(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt__str__%sN(t__name__t __module__t__doc__RRR (((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRs tTimeoutcBs5eZdZdZdZddZdZRS(sContext manager for running a block of commands under a timeout. If the block times out, a TimeoutError is raised. Arguments: seconds (int) - timeout in seconds msg (str) - message to supply to TimeoutError cs5tjtjfd_tjjS(Ncs jS(N(t_timeout(t_signumt_frame(R(s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt;s(tsignaltSIGALRMt_Timeout__oldHandlertalarmt_Timeout__seconds(R((Rs5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt __enter__8s cCs'tjdtjtj|jtS(Ni(RRRRtFalse(Rt exceptionTypetexceptionValuet traceback((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyt__exit__As cCs||_||_d|_dS(N(Rt _Timeout__msgRR(RtsecondsR((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRJs  cCst|jdS(s+ Method invoked if the alarm goes off. N(RR(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyRRsN(R R R RRRRR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyR)s  (R Rt ExceptionRtobjectR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Timeout.pyts  Transaction.pyc000064400000013715147221674750007574 0ustar00 .t_c@sjdZddlmZddlZddlZddlZejddefdYZdZ dS(s~ Transaction - provides transactional support $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Transaction.py#1 $ i(twrapsNt TransactioncBsYeZdZiZedZdZddZdZ edZ dZ RS(s%Client-visible transaction object. cCs|jdS(s<Returns the current transaction for the current thread. i(t_threadTransactionList(tcls((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt transaction-scCs|jj|dS(sAdds callable undoStage to transaction stages. Arguments: undoStage (callable) - callable to execute as part of transaction roll-back N(t_Transaction__undoStagestappend(tselft undoStage((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt addUndoStage4scCs tdS(s+Sets the message to handle if there is an exception. If message is specified and an exception occurs the exception will be appended to the message using "; {0}" where "{0}" represents the exception. If message is not specified, the exception will be coerced to a string and passed to handleMessage. Specifying handleMessage as None will clear both handleMessage and message. Arguments: handleMessage (callable) - method to handle message message (string) - message N(tNotImplementedError(Rt handleMessagetmessage((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt setMessage>scCs tt|jg|_dS(N(tsuperRt__init__R(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRTscCsQd}tjj}y|j|}Wn$tk rLg}||j|dtffdYtfd}|S(sGMethod decorator providing transactional capabilities to the method. t _TransactioncsPeZdZedZedZdZfdZddZ RS(sYDecorator-local transaction object providing actual transaction capabilities. cSs |jj||jS(s`Adds, and returns, a transaction to the transaction list for the current thread. (RRR(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytaddTransactionscSs|jjdS(sBRemoves the current transaction for for the current thread. N(Rtpop(R((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytremoveTransactionscSs|jdk r_|jdk rI|jtdj|jt|q_|jt|n|j}|jx-|D]%}y |Wq}tk rq}Xq}WdS(sPerforms the undo processing of the transaction. Exceptions from the undo stages are ignored. Arguments: exception - the exception which resulted in undo being called s{0}; {1}N( t_Transaction__handleMessageRt_Transaction__messaget_tformattstrRtreverset Exception(Rt exceptiont undoStagesR((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytundos      cs)t|jd|_d|_dS(N(RRRR!R"(R(R(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRs cSs1||_|jdkr$d|_n ||_dS(N(R!RR"(RR R ((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyR s  N( RRRRRR R*RRR ((R(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyRs   cszj}d}zVy||}Wn<tk rf}|j|t||tjdnXWdjX|S(sDWrapper method providing transactional processing capabilities. iN(RRR'R*ttypetsystexc_infoR (targstkwargsRtresulttex(Rtfunc(s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pytwraps  $ (RR(R2R3((RR2s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyt transactionalzsJ( Rt functoolsRtgettextR,RtinstalltobjectRR4(((s9/usr/lib/python2.7/site-packages/vdo/utils/Transaction.pyts    X__init__.pyo000064400000074057147221674750007070 0ustar00 ;Xc@sbdZddlmZddlmZmZmZddlm Z m Z ddl Z ddl m ZddlmZddlZddlZddlZejeZddlZddlZddlZddlZddlZeryddlZWq(ek rdZdZq(Xn ddlZddl Z erIddl!Z!nddl"Z"dd l#m$Z$dd l%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2dd l3m4Z4m5Z5m6Z6m7Z7m8Z8dd l9m:Z:dd lm;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZIddddddddddddddddddd d!d"d#d$d%d&gZJeKejeArejLnejMd'd(ZNd)d*d+d,d-d.d/gZOd0d1gZPdd2l9mQZQd3ZReBd3ZSeBd4ZTeKejUjVd5pEd6ZWd7eXfd8YZYeArejZj[Z\e]e\ejZj^gZ_d9Z`n d:Z`ddeaddead;Zbd<Zcd=ZdedZeydd>lfmgZdWnek rnXd?d@ZhdAdBZiedkr.dAdCZindDZjeArRdEZkdFZln(ddGlmmZmmnZndHZkdIZle;ekdJe;eldKdLZodMZpdNZqeBdNZrddOZsdPZtetjudQZvdRZwdSZxdZyeBdTZzdVZ{dWdAddXZ|dWdAdYZ}eAr?dWdAdZZ~ndWdAd[Z~e;e~d\e4d]d^d_d`dQdaZe]dbjZe]dcjZe]d3ddgZddedfZyddglmZWn&ek rdZeaZdhZn4XeZdNZeBdiZeAr(djZn dkZe;edldmZejdnkriddol mZnddpl m ZeZdqZyejdreZWnek reaZnXddsZerejZnejeZdtZduZdvZe4d]d`d_dwdxdydzed{ZdZdZdZdZdZdZdS(s4passlib.utils -- helpers for writing password hashesi(tJYTHON(t b2a_base64t a2b_base64tError(t b64encodet b64decodeN(tlookup(tupdate_wrappersnot present under Jython(twarn( t BASE64_CHARSt AB64_CHARSt HASH64_CHARSt BCRYPT_CHARSt Base64EnginetLazyBase64Engineth64th64bigtbcrypt64t ab64_encodet ab64_decodet b64s_encodet b64s_decode(tdeprecated_functiontdeprecated_methodtmemoized_propertyt classpropertyt hybrid_method(tExpectedStringError(tadd_doct join_bytestjoin_byte_valuestjoin_byte_elemstirangetimaptPY3tut join_unicodetunicodetbyte_elem_valuet nextgettertunicode_or_bytes_typestget_method_functiontsuppress_causeRtsys_bitstunix_crypt_schemestrounds_cost_valuestconsteqtsaslprept xor_bytest render_bytest is_same_codect is_ascii_safetto_bytest to_unicodet to_native_strt has_cryptt test_cryptt safe_crypttticktrngt getrandbytest getrandstrtgenerate_passwordtis_crypt_handlertis_crypt_contextthas_rounds_infot has_salt_infoig?t sha512_cryptt sha256_cryptt sha1_crypttbcryptt md5_cryptt bsdi_cryptt des_crypttlineartlog2(tMissingBackendErrortt tPASSLIB_MAX_PASSWORD_SIZEit SequenceMixincBsMeZdZdZdZdZdZdZdZdZ RS(s helper which lets result object act like a fixed-length sequence. subclass just needs to provide :meth:`_as_tuple()`. cCstddS(Nsimplement in subclass(tNotImplemented(tself((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt _as_tuplescCst|jS(N(treprRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__repr__scCs|j|S(N(RS(RRtidx((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt __getitem__scCst|jS(N(titerRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__iter__scCst|jS(N(tlenRS(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__len__scCs|j|kS(N(RS(RRtother((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__eq__scCs|j| S(N(R](RRR\((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt__ne__s( t__name__t __module__t__doc__RSRURWRYR[R]R^(((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRPs      cCsetjt|j}|s"tS|j|}|rJ|jtkrJtS|t |djt kS(s*test if function accepts specified keywordi( tinspectt signatureR)t parameterstFalsetgettkindt _VAR_ANY_SETtTruetlistt _VAR_KEYWORD(tfunctkeytparamstarg((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytaccepts_keywordscCs1tjt|}||jkp0|jdk S(s*test if function accepts specified keywordN(Rbt getargspecR)targstkeywordstNone(RlRmtspec((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRpsc st|tr|g}nt|j}|rt|trK|g}nxE|D]:|rp|krpqRn|krR|jqRqRWn|rx|D]tfd|Drqn|r&xt|D]8\}} t| rPn|rt| |rPqqWt|}n[|r{xRtt |D]/\} } t| |r?t|| }Pq?q?Wd}nd}|j |qWn|st ||_ndS(s helper to update mixin classes installed in target class. :param target: target class whose bases will be modified. :param add: class / classes to install into target's base class list. :param remove: class / classes to remove from target's base class list. :param append: by default, prepends mixins to front of list. if True, appends to end of list instead. :param after: optionally make sure all mixins are inserted after this class / classes. :param before: optionally make sure all mixins are inserted before this class / classes. :param dryrun: optionally perform all calculations / raise errors, but don't actually modify the class. c3s|]}t|VqdS(N(t issubclass(t.0tbase(tmixin(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys siN( t isinstancettypeRjt __bases__tremovetanyt enumerateRvRZtreversedtinsertttuple( ttargettaddR}tappendtbeforetaftertdryruntbasesRVRxtend_idx((Rys:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytupdate_mixin_classess@      ccs|dkrtdnt|tjrqt|}d}x||krm||}|||!V|}qBWnt|tjrt|}xdtrtj ||}yt |}Wnt k rPnXtj |f|VqWn t ddS(s8 split iterable into chunks of elements. issize must be positive integerissource must be iterableN(t ValueErrorRzt collectionstSequenceRZtIterableRXRit itertoolstislicetnextt StopIterationtchaint TypeError(tsourcetsizetendtitntitrt chunk_itrtfirst((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytbatchs&        cCs5t|tr6t|ts-tdnt}nBt|trlt|tsctdnt}n tdt|t|k}|r|}d}n|s|}d}n|rxht||D]\}}|||AO}qWn:x7t||D]&\}}|t|t|AO}qW|dkS(sCheck two strings/bytes for equality. This function uses an approach designed to prevent timing analysis, making it appropriate for cryptography. a and b must both be of the same type: either str (ASCII only), or any type that supports the buffer protocol (e.g. bytes). Note: If a and b are of different lengths, or if an error occurs, a timing attack could theoretically reveal information about the types and lengths of a and b--but not their values. s)inputs must be both unicode or both bytesii( RzR%RRetbytesR"RZtziptord(tlefttrightt is_py3_bytest same_sizettmptresulttltr((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR./s,     (tcompare_digestt,cCsX|j}|j|r(|d }n|s2gSg|j|D]}|j^qBS(sRsplit comma-separated string into list of elements, stripping whitespace. i(tstriptendswithtsplit(Rtseptelem((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt splitcommazs   tvaluecsbt|ts+tdt|fntjtjtfd|D}tj d|}|sxt Stj }||dr||dst d|ntj }n|}tj}tj}tj}tj}tj} tj} tj} tj} tj} xD|D]<}||rCt d|n||rbt d|n||rt d |n||rt d |n| |rt d |n| |rt d |n| |rt d |n| |rt d|n| |r;t d|n||rt d|qqW|S(sNormalizes unicode strings using SASLPrep stringprep profile. The SASLPrep profile is defined in :rfc:`4013`. It provides a uniform scheme for normalizing unicode usernames and passwords before performing byte-value sensitive operations such as hashing. Among other things, it normalizes diacritic representations, removes non-printing characters, and forbids invalid characters such as ``\n``. Properly internationalized applications should run user passwords through this function before hashing. :arg source: unicode string to normalize & validate :param param: Optional noun identifying source parameter in error messages (Defaults to the string ``"value"``). This is mainly useful to make the caller's error messages make more sense contextually. :raises ValueError: if any characters forbidden by the SASLPrep profile are encountered. :raises TypeError: if input is not :class:`!unicode` :returns: normalized unicode string .. note:: This function is not available under Jython, as the Jython stdlib is missing the :mod:`!stringprep` module (`Jython issue 1758320 `_). .. versionadded:: 1.6 s$input must be unicode string, not %sc3s3|])}|s|r'tn|VqdS(N(t_USPACE(Rwtc(t in_table_b1t in_table_c12(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys stNFKCiismalformed bidi sequence in s$unassigned code points forbidden in s control characters forbidden in s$private use characters forbidden in s"non-char code points forbidden in ssurrogate codes forbidden in s!non-plaintext chars forbidden in s!non-canonical chars forbidden in s1display-modifying / deprecated chars forbidden instagged characters forbidden in sforbidden bidi character in (RzR%RR{t stringprepRRR$t unicodedatat normalizet_UEMPTYt in_table_d1Rt in_table_d2t in_table_a1tin_table_c21_c22t in_table_c3t in_table_c4t in_table_c5t in_table_c6t in_table_c7t in_table_c8t in_table_c9(Rtparamtdatat is_ral_chartis_forbidden_bidi_charRRRRRRRRRR((RRs:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR/sb,                          cCstdtdS(sstub for saslprep()s>saslprep() support requires the 'stringprep' module, which is N(tNotImplementedErrort_stringprep_missing_reason(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR/scGsHt|tr!|jd}n|td|D}|jdS(s&Peform ``%`` formating using bytes in a uniform manner across Python 2/3. This function is motivated by the fact that :class:`bytes` instances do not support ``%`` or ``{}`` formatting under Python 3. This function is an attempt to provide a replacement: it converts everything to unicode (decoding bytes instances as ``latin-1``), performs the required formatting, then encodes the result to ``latin-1``. Calling ``render_bytes(source, *args)`` should function roughly the same as ``source % args`` under Python 2. slatin-1css3|])}t|tr'|jdn|VqdS(slatin-1N(RzRtdecode(RwRo((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(RzRRRtencode(RRrR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR1s  cCstj|dS(Ntbig(tintt from_bytes(R((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt bytes_to_int"scCs|j|dS(NR(R4(Rtcount((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt int_to_bytes$s(thexlifyt unhexlifycCstt|dS(Ni(RR(R((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR)scCstd|d>|S(Ns%%0%dxi(R(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR+ss/decode byte string as single big-endian integers/encode integer as single big-endian byte stringcCs#tt|t|At|S(s;Perform bitwise-xor of two byte strings (must be same size)(RRRZ(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR01scCsBt|}||kr6||d|}||| S|| SdS(s;repeat or truncate string, so it has length iN(RZ(RRtcurtmult((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt repeat_string5s    tcCs^t|}||krR|dkrBt|tr9tnt}n||||S|| SdS(s>right-pad or truncate string, so it has length N(RZRtRzR%t_UNULLt_BNULL(RRtpadR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytright_pad_stringAs    t aA:#!tasciicCstj|tkS(sRTest if codec is compatible with 7-bit ascii (e.g. latin-1, utf-8; but not utf-16)(t_ASCII_TEST_UNICODERt_ASCII_TEST_BYTES(tcodec((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytis_ascii_codecQscCs<||krtS|o|s tSt|jt|jkS(s3Check if two codec names are aliases for same codec(RiRet _lookup_codectname(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR2Us   sics5t|trtnttfd|DS(s<Check if string (bytes or unicode) contains only 7-bit asciic3s|]}|kVqdS(N((RwR(R(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys bs(RzRt_B80t_U80tall(R((Rs:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR3_ssutf-8cCsqt|trB|r;t|| r;|j|j|S|Sn+t|tr^|j|St||dS(sHelper to normalize input to bytes. :arg source: Source bytes/unicode to process. :arg encoding: Target encoding (defaults to ``"utf-8"``). :param param: Optional name of variable/noun to reference when raising errors :param source_encoding: If this is specified, and the source is bytes, the source will be transcoded from *source_encoding* to *encoding* (via unicode). :raises TypeError: if source is not unicode or bytes. :returns: * unicode strings will be encoded using *encoding*, and returned. * if *source_encoding* is not specified, byte strings will be returned unchanged. * if *source_encoding* is specified, byte strings will be transcoded to *encoding*. N(RzRR2RRR%R(RtencodingRtsource_encoding((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR4ds cCsBt|tr|St|tr/|j|St||dS(sHelper to normalize input to unicode. :arg source: source bytes/unicode to process. :arg encoding: encoding to use when decoding bytes instances. :param param: optional name of variable/noun to reference when raising errors. :raises TypeError: if source is not unicode or bytes. :returns: * returns unicode strings unchanged. * returns bytes strings decoded using *encoding* N(RzR%RRR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR5s  cCsBt|tr|j|St|tr/|St||dS(N(RzRRR%R(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR6s  cCsBt|tr|St|tr/|j|St||dS(N(RzRR%RR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR6s  s>Take in unicode or bytes, return native string. Python 2: encodes unicode using specified encoding, leaves bytes alone. Python 3: leaves unicode alone, decodes bytes using specified encoding. :raises TypeError: if source is not unicode or bytes. :arg source: source unicode or bytes string. :arg encoding: encoding to use when encoding unicode or decoding bytes. this defaults to ``"utf-8"``. :param param: optional name of variable/noun to reference when raising errors. :returns: :class:`str` instance t deprecateds1.6tremoveds1.7cCst||ddS(s'deprecated, use to_native_str() insteadRthash(R6(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt to_hash_strss true t yes y on 1 enable enableds#false f no n off 0 disable disabledtnonetbooleancCst|trj|jj}|tkr1tS|tkrAtS|tkrQ|St d||fn-t|t r}|S|dkr|St |SdS(s\ helper to convert value to boolean. recognizes strings such as "true", "false" sunrecognized %s value: %rN( RzR(tlowerRt _true_setRit _false_setRet _none_setRtboolRt(RRRtclean((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytas_bools    (tcryptcCsdS(N(Rt(tsecretR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9ss*:!cCst|tr@|}y|jd}Wq@tk r<dSXnt|kr[tdnt|tr||jd}nt||}| s|dtkrdS|S(Nsutf-8snull character in secretRi( RzRRtUnicodeDecodeErrorRtt_NULLRt_cryptt_invalid_prefixes(RRtorigR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9s  cCst|tr!|jd}nt|kr<tdnt|tr]|jd}nt||}|svdS|jd}|dtkrdS|S(Nsutf-8snull character in secretRi( RzR%RRRRRtRR(RRR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR9s sWrapper around stdlib's crypt. This is a wrapper around stdlib's :func:`!crypt.crypt`, which attempts to provide uniform behavior across Python 2 and 3. :arg secret: password, as bytes or unicode (unicode will be encoded as ``utf-8``). :arg hash: hash or config string, as ascii bytes or unicode. :returns: resulting hash as ascii unicode; or ``None`` if the password couldn't be hashed due to one of the issues: * :func:`crypt()` not available on platform. * Under Python 3, if *secret* is specified as bytes, it must be use ``utf-8`` or it can't be passed to :func:`crypt()`. * Some OSes will return ``None`` if they don't recognize the algorithm being used (though most will simply fall back to des-crypt). * Some OSes will return an error string if the input config is recognized but malformed; current code converts these to ``None`` as well. cCst|||kS(scheck if :func:`crypt.crypt` supports specific hash :arg secret: password to test :arg hash: known hash of password to use as reference :returns: True or False (R9(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR8Astwin32(tclock(ttimecCsBtjd|}|r>td|jdjdDSdS(shelper to parse version strings(\d+(?:\.\d+)+)css|]}t|VqdS(N(R(RwR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys Ysit.N(tretsearchRtgroupRRt(Rtm((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyt parse_versionUs&ic Csddlm}t|drdt|drdy|j}Wqdtk r`|jd}qdXntd|ttdrtjndt t t j t j trtjd jd nd f}t||jd jd S(s.generate prng seed value from system resourcesi(tsha512tgetstatet getrandbitsiis%s %s %s %.15f %.15f %stgetpidi slatin-1isutf-8iiN(thashlibR thasattrR RR R#tosR RttidtobjectRRt has_urandomturandomRRRt hexdigest(RR ttext((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytgenseedqs     (cs)s tSfd}t|S(s]return byte-string containing *count* number of randomly generated bytes, using specified rngc3sMjd>}d}x-|krH|d@V|dL}|d7}qWdS(Niiii(R (RR(RR;(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pythelpers   (t_BEMPTYR(R;RR((RR;s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR<s csdkrtdntdkrBtdndkrVSfd}ttrt|St|SdS(s|return string containing *count* number of chars/bytes, whose elements are drawn from specified charset, using specified rngiscount must be >= 0salphabet must not be emptyic3sTjd}d}x1|krO|V|}|d7}qWdS(Nii(t randrange(RR(tcharsetRtlettersR;(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRs   N(RRZRzR%R$R(R;RRR((RRRR;s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR=s      t42346789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrstuvwxyzs2.0t replacements/passlib.pwd.genword() / passlib.pwd.genphrase()i cCstt||S(swgenerate random password using given length & charset :param size: size of password. :param charset: optional string specified set of characters to draw from. the default charset contains all normal alphanumeric characters, except for the characters ``1IiLl0OoS5``, which were omitted due to their visual similarity. :returns: :class:`!str` containing randomly generated password. .. note:: Using the default character set, on a OS with :class:`!SystemRandom` support, this function should generate passwords with 5.7 bits of entropy per character. (R=R;(RR((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR>sRt setting_kwdst context_kwdstverifyRtidentifycstfdtDS(s4check if object follows the :ref:`password-hash-api`c3s|]}t|VqdS(N(R(RwR(tobj(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(Rt_handler_attrs(R"((R"s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR?st needs_updatet genconfigtgenhashtencryptcstfdtDS(sOcheck if object appears to be a :class:`~passlib.context.CryptContext` instancec3s|]}t|VqdS(N(R(RwR(R"(s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pys s(Rt_context_attrs(R"((R"s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyR@scCs%d|jko$t|dddk S(s_check if handler provides the optional :ref:`rounds information ` attributestroundst min_roundsN(RtgetattrRt(thandler((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRAscCs%d|jko$t|dddk S(s[check if handler provides the optional :ref:`salt information ` attributestsaltt min_salt_sizeN(RR+Rt(R,((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pyRB st(snames setting_kwdsRR shashR!(R$R%R&R R'R!(Ratpasslib.utils.compatRtbinasciiRRRt_BinAsciiErrortbase64RRRtcodecsRRt functoolsRRRbtloggingt getLoggerR_tlogtmathRtsystrandomRRt ImportErrorRtRRRttypestwarningsRtpasslib.utils.binaryR R R R R RRRRRRRRtpasslib.utils.decorRRRRRt passlib.excRRRRRR R!R"R#R$R%R&R'R(R)R*t__all__RtmaxsizetmaxintR+R,R-RLRRRtenvironRftMAX_PASSWORD_SIZERRPt Parametert VAR_KEYWORDRktsettVAR_POSITIONALRhRpReRRR.t str_consteqthmacRRR/R1RRRRR0RRRRRRRRR2RRR3R4R5R6RRRRRRRRR7R9RiRRR8tplatformRttimerR:RRRRRt SystemRandomR;tRandomR<R=t _52charsetR>R#R?R(R@RARB(((s:/usr/lib/python2.7/site-packages/passlib/utils/__init__.pytsJ              X(d .       V  >                 %            !    Command.pyo000064400000025602147221674750006677 0ustar00 .t_c@sdZddlmZddlmZmZddlZddlZddlZddlZddl Z de fdYZ de fd YZ d Zd ZdS( s Command - runs commands and manages their results $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Command.py#3 $ i(tLoggeri(tPopentPIPENt CommandErrorcBsDeZdZdZdZdZdZdZdZRS(sException raised to indicate an error running a command. Arguments: exitCode (int): The exit code of the command stdout (string): The output from the command stderr (string): The error output from the command message (string): The (localized) error text; will be formatted with the remaining arguments args: Arguments for formatting the message cCs|jS(N(t _exitCode(tself((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt getExitCode0scCs|jS(N(t_stderr(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pytgetStandardError4scCs||j||jdS(sLog the outputs of the failed command which generated this exception. Arguments: logMethod (callable): The method to log with N(t_stdoutR(Rt logMethod((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt logOutputs8s cGs|j||_dS(sSet the error message in this exception. Arguments: message (string): The (localized) message text; will be formatted with *args args: Values to pass to the format of message N(tformatt_message(Rtmessagetargs((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt setMessageBscGsBtt|j||_||_||_|j||dS(N(tsuperRt__init__RR RR(RtexitCodetstdouttstderrRR((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyROs    cCs|jS(N(R (R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt__str__Ws( t__name__t __module__t__doc__RRR RRR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyR"s    tCommandcBseZdZeZdZejej dZ e dZ e eedZ dZdZd dZdZdd d d Zd Zd ZRS(sVCommand encapsulates shell commands, runs them, and manages the result. Attributes: noRun (bool): if True, don't run the command, and always succeed shell (bool): if True, run this command using shell -c verbose (int): if > 0, print commands to stdout before executing them _commandList (list): command and its arguments is.CommandcCs|jS(s+Returns True iff Commands default to noRun.(t defaultNoRun(tcls((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt noRunModekscCs1|r||_t|_n|r-||_ndS(sSets the verbose and noRun default values. Arguments: verbose: (boolean) If True, operate verbosely. noRun: (boolean) If True, do not actually execute. N(RtTruetdefaultVerbose(RtverbosetnoRun((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt setDefaultsqs   cCs |jdS(s3Returns an identifier (argv[0]) for error messages.i(t _commandList(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt commandNamescKs|jdd}|jdd }|jsE|jdt|_n|j}|dkry|jjdj|nyxt|D]}|dkr|jjdj||n|j dkrd|GH|jj |n|j rd Sy3|j |}|jd tr |j S|SWqtk r}||dkr~|dkru|jtd |j|n|ntjdqXqWWn/tk r}|jd trd S|nXd S(sRun a command. Returns the output of running the command. Arguments: noThrow: If True, will return an empty string instead of throwing on error. retries: The number of times to try the command before giving up. Defaults to 1. shell: Indicate that this is a shell command stdin: If not None, the stream from which the command should take its input, defaults to None. strip: If True, strip leading and trailing whitespace from the command output before returning it. Exceptions: CommandError: if the command failed and noThrow is False tretriesitstdintshellsWaiting for '{0}'s ... {0}/{1}is Ntstrips {0}: timed out after {1} secondstnoThrowt(tgettNoneR'tFalset_getCommandLinetlogtdebugR trangeR tinfoR!t_executeR(RRt_R$ttimetsleep(RtkwargsR%R&t commandLinetcounttoutputte((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pytruns<      $  cCstt|jtj|_t|_tj|_||_ |rt j t j |_x3|jD]\}}||j|s     9 Logger.pyc000064400000007252147221674750006525 0ustar00 .t_c@s`dZddlZddlZddlZddlZddlmZdefdYZdS(si Logger - VDO manager logging $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Logger.py#3 $ iN(t MethodTypetLoggercBs~eZdZejjejdZe Z dZ e dZe de dZe dZe dZdZRS(sWrappers and configuration methods for the Python logger. Attributes: logfile (string): the path to the logfile if specified. myname (string): name of the command being run. quiet (bool): if True, don't print to stdout. icCs"|js|GHn|j|dS(s4Print a status message to stdout and log it as well.N(tquiettinfo(tclstloggertmsg((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pytannounce/s c Cs;||_||_|}d}|r*dnd|}tj}|jtjtjtj}|j tj |j||j|rtj ntj |j ||jdk rytjj|jrtjj|j rt|jd} tjd| }n!tjj|jddd d }tj d |} |j | |j|retj ntj|j |Wqtk r} |jd jd |jd| qXnyStjjdd}|j tj |j||jtj |j |Wn)tk r6} |jdj| nXdS(s8Configure the logging system according to the arguments.s: %(levelname)s - %(message)ss : %(name)sttwtstreamtmaxBytesi it backupCountis%(asctime)s %(name)ss.Unable to configure logging to {logfile}: {ex}tlogfiletextaddresss/dev/logs,Unable to configure logging for rsyslog: {0}Ni(i(tmynameR tloggingt getLoggertsetLeveltNOTSETt StreamHandlertsyststderrt setFormattert FormattertDEBUGtWARNINGt addHandlertNonetostpathtexiststisfiletopenthandlerstRotatingFileHandlertINFOt Exceptiontwarntformatt SysLogHandler( RtnameR tdebugt debuggingt formatBaset debugBaseRthandlert logstreamt formatterR((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyt configure7sB    +  cCs.tj|}t|j||j|_|S(s;Returns a Python logger decorated with the announce method.(RRRRt __class__(RR*R((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyRbscCs6g}|jdk r2|jdt|jn|S(sBReturn a list of strings containing the logging options specified.s --logfile=N(R Rtappendtstr(Rtoptions((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pytloggingOptionsjscCstt|jdS(N(tsuperRt__init__(tself((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyR9usN(t__name__t __module__t__doc__RRtbasenameRtargvRtFalseRRR t classmethodRR2RR7R9(((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyR s* ( R=Rtlogging.handlersRRttypesRtobjectR(((s4/usr/lib/python2.7/site-packages/vdo/utils/Logger.pyts     YAMLObject.pyc000064400000016340147221674750007175 0ustar00 .t_c@sHdZddlZddlZejddejfdYZdS(s} YAMLObject - Provides mapping to/from YAML. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/YAMLObject.py#2 $ iNtutilst YAMLObjectcBseZdZejZedZedZdZ edZ e dZ e dZ dZe dZd ZRS( sProvides conversion of objects to and from YAML representations. The attributes that are included in the YAML representation are taken from an instance's __dict__ filtered through the list returned from the _yamlAttributeKeys property. The list from the _yamlAttributeKeys property is used to check for missing attributes when generating the YAML representation. It is also used to check for missing or extraneous attributes when constructing an instance from the YAML representation. Subclasses must override _yamlAttributeKeys. Subclasses must specify the class attribute yaml_tag which indicates the type of the instance in the YAML representation. Class attributes: yaml_tag (unicode string) - YAML representation identfifier; must be specified by subclasses yaml_loader - The loader to use; set to yaml.SafeLoader to allow yaml.load_safe() to instantiate objects ccs1|j}|V|j|}|j|dS(sConstructs and returns an instance from its YAML representation. Returns: instance constructed from YAML representation. N(t_yamlMakeInstancetconstruct_mappingt_yamlSetAttributes(tclstloadertnodetinstancetmapping((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyt from_yaml>s cCs|j}|j|j|S(sgReturns a YAML representation of the instance. Returns: YAML representation of instance (t _yamlDatatrepresent_mappingtyaml_tag(RtdumpertdatatyamlData((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pytto_yamlKs cCs tt|ji|_dS(N(tsuperRt__init__t_preservedExtraAttributes(tself((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRVscCs|S(sReturns an instance of the class specifying placeholder values for any arguments required by the __init__ method. The default implementation is to instantiate without arguments. Subclasses must override if their __init__ method takes arguments. ((R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR]scCsftg|jjD]6\}}||jkr||jkr||f^q}|j|j|S(s Returns a dictionary containing the data to include in generating the instance's YAML representation. The base implementation uses the contents of the instance's __dict__ filtered through the list of keys returned from _yamlAttributeKeys excluding any that require special handling (subclasses must override this method to add those) and adds any entries from the preserved extra attributes. Returns: dictionary of data to use in generating the instance's YAML representation (tdictt__dict__t iteritemst_yamlAttributeKeyst_yamlSpeciallyHandledAttributestupdateR(RtkeytvalueR((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR hs $cCs tdS(sReturns a list of the keys for the attributes to include in the instance's YAML representation. Must be overridden by subclasses. Returns: list of keys for attributes to include in the instance's YAML representation N(tNotImplementedError(R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs cCstg|jD]'\}}||jkr||f^q}|jj|g|jD]*}||jkr]||jkr]|^q]}x"|D]}t||||qWdS(sSets the instance's internal attributes from the YAML attributes. By default, the attributes are set via invoking setattr() targeted to the instance. If a subclass uses different internal names or computes the attributes in some way it must override this method to handle the attributes appropriately. The subclass must also account for the possibility that the attributes it receives may not contain the entirety of such specially handled attributes; in other words, it must check for each attribute's existence in the attributes dictionary it receives. Any unspecified attributes must be given a default value in whatever manner the subclass chooses. Any entries in the specified attributes which are unknown to the entity being constructed are preserved for later use in generating YAML output. Arguments: attributes (dictionary) - the attributes from the YAML representation N(RtitemsRRRtkeysRtsetattr(Rt attributesRRtextraR ((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs$ cCsgS(sReturns a list of attributes that are specially handled by subclasses. These attributes are skipped by _yamlData and _yamlSetAttributes implemented by YAMLObject. Subclasses must override both _yamlData and _yamlSetAttributes to handle these attributes. ((R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs cCsAt|t|s*ttdn|jj|jdS(sUpdates the current object (self) from the specified instance. This is for classes that perform indirect construction using the results of the YAML load. Instances of such classes are required to invoke this method themselves. The specified instance must be the same class (or a subclass) of the current object to guarantee that any attributes the current object attempts to update will be available from the instance. Arguments: instance (YAMLObject) - object source for update Raises: TypeError - specified instance is not the same class (or a subclass) of the current object s(attempt to update from incompatible typeN(t isinstancettypet TypeErrort_RR(RR((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyt_yamlUpdateFromInstances(t__name__t __module__t__doc__tyamlt SafeLoadert yaml_loadert classmethodR RRRtpropertyR RRRR((((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR"s      (R+tgettextR,tinstallR(((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyts   YAMLObject.py000064400000017275147221674750007042 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ YAMLObject - Provides mapping to/from YAML. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/YAMLObject.py#2 $ """ import gettext import yaml gettext.install("utils") ######################################################################## class YAMLObject(yaml.YAMLObject): """Provides conversion of objects to and from YAML representations. The attributes that are included in the YAML representation are taken from an instance's __dict__ filtered through the list returned from the _yamlAttributeKeys property. The list from the _yamlAttributeKeys property is used to check for missing attributes when generating the YAML representation. It is also used to check for missing or extraneous attributes when constructing an instance from the YAML representation. Subclasses must override _yamlAttributeKeys. Subclasses must specify the class attribute yaml_tag which indicates the type of the instance in the YAML representation. Class attributes: yaml_tag (unicode string) - YAML representation identfifier; must be specified by subclasses yaml_loader - The loader to use; set to yaml.SafeLoader to allow yaml.load_safe() to instantiate objects """ yaml_loader = yaml.SafeLoader ###################################################################### # Overridden methods ###################################################################### @classmethod def from_yaml(cls, loader, node): """Constructs and returns an instance from its YAML representation. Returns: instance constructed from YAML representation. """ instance = cls._yamlMakeInstance() yield instance mapping = loader.construct_mapping(node) instance._yamlSetAttributes(mapping) ###################################################################### @classmethod def to_yaml(cls, dumper, data): """Returns a YAML representation of the instance. Returns: YAML representation of instance """ yamlData = data._yamlData return dumper.represent_mapping(data.yaml_tag, yamlData) ###################################################################### def __init__(self): super(YAMLObject, self).__init__() self._preservedExtraAttributes = {} ###################################################################### # Protected methods ###################################################################### @classmethod def _yamlMakeInstance(cls): """Returns an instance of the class specifying placeholder values for any arguments required by the __init__ method. The default implementation is to instantiate without arguments. Subclasses must override if their __init__ method takes arguments. """ return cls() ###################################################################### @property def _yamlData(self): """Returns a dictionary containing the data to include in generating the instance's YAML representation. The base implementation uses the contents of the instance's __dict__ filtered through the list of keys returned from _yamlAttributeKeys excluding any that require special handling (subclasses must override this method to add those) and adds any entries from the preserved extra attributes. Returns: dictionary of data to use in generating the instance's YAML representation """ data = dict([(key, value) for key, value in self.__dict__.iteritems() if ((key in self._yamlAttributeKeys) and (key not in self._yamlSpeciallyHandledAttributes))]) data.update(self._preservedExtraAttributes) return data ###################################################################### @property def _yamlAttributeKeys(self): """Returns a list of the keys for the attributes to include in the instance's YAML representation. Must be overridden by subclasses. Returns: list of keys for attributes to include in the instance's YAML representation """ raise NotImplementedError ###################################################################### def _yamlSetAttributes(self, attributes): """Sets the instance's internal attributes from the YAML attributes. By default, the attributes are set via invoking setattr() targeted to the instance. If a subclass uses different internal names or computes the attributes in some way it must override this method to handle the attributes appropriately. The subclass must also account for the possibility that the attributes it receives may not contain the entirety of such specially handled attributes; in other words, it must check for each attribute's existence in the attributes dictionary it receives. Any unspecified attributes must be given a default value in whatever manner the subclass chooses. Any entries in the specified attributes which are unknown to the entity being constructed are preserved for later use in generating YAML output. Arguments: attributes (dictionary) - the attributes from the YAML representation """ extra = dict([(key, value) for key, value in attributes.items() if key not in self._yamlAttributeKeys]) self._preservedExtraAttributes.update(extra) keys = [key for key in attributes.keys() if (key in self._yamlAttributeKeys) and (key not in self._yamlSpeciallyHandledAttributes)] for key in keys: setattr(self, key, attributes[key]) ###################################################################### @property def _yamlSpeciallyHandledAttributes(self): """Returns a list of attributes that are specially handled by subclasses. These attributes are skipped by _yamlData and _yamlSetAttributes implemented by YAMLObject. Subclasses must override both _yamlData and _yamlSetAttributes to handle these attributes. """ return [] ###################################################################### def _yamlUpdateFromInstance(self, instance): """Updates the current object (self) from the specified instance. This is for classes that perform indirect construction using the results of the YAML load. Instances of such classes are required to invoke this method themselves. The specified instance must be the same class (or a subclass) of the current object to guarantee that any attributes the current object attempts to update will be available from the instance. Arguments: instance (YAMLObject) - object source for update Raises: TypeError - specified instance is not the same class (or a subclass) of the current object """ if (not isinstance(instance, type(self))): raise TypeError(_("attempt to update from incompatible type")) self._preservedExtraAttributes.update(instance._preservedExtraAttributes) Timeout.py000064400000006151147221674750006566 0ustar00# # Copyright (c) 2018 Red Hat, Inc. # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """ Timeout - context manager that implements a timeout. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Timeout.py#1 $ """ import signal ######################################################################## class TimeoutError(Exception): """Exception raised when a block times out.""" def __init__(self, msg = None, *args, **kwargs): super(TimeoutError, self).__init__(*args, **kwargs) if msg is None: msg = "timeout" self._msg = msg def __str__(self): return self._msg ######################################################################## class Timeout(object): """Context manager for running a block of commands under a timeout. If the block times out, a TimeoutError is raised. Arguments: seconds (int) - timeout in seconds msg (str) - message to supply to TimeoutError """ ###################################################################### # Public methods ###################################################################### ###################################################################### # Overridden methods ###################################################################### def __enter__(self): # Establish the alarm handler and set the alarm to go off. self.__oldHandler = signal.signal(signal.SIGALRM, lambda _signum, _frame : self._timeout()) signal.alarm(self.__seconds) return self ###################################################################### def __exit__(self, exceptionType, exceptionValue, traceback): # Turn off the alarm and re-establish the previous alarm handler. signal.alarm(0) signal.signal(signal.SIGALRM, self.__oldHandler) # Don't suppress exceptions. return False ###################################################################### def __init__(self, seconds, msg = None): self.__seconds = seconds self.__msg = msg self.__oldHandler = None ###################################################################### # Protected methods ###################################################################### def _timeout(self): """ Method invoked if the alarm goes off. """ raise TimeoutError(self.__msg) ###################################################################### # Private methods ###################################################################### YAMLObject.pyo000064400000016340147221674750007211 0ustar00 .t_c@sHdZddlZddlZejddejfdYZdS(s} YAMLObject - Provides mapping to/from YAML. $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/YAMLObject.py#2 $ iNtutilst YAMLObjectcBseZdZejZedZedZdZ edZ e dZ e dZ dZe dZd ZRS( sProvides conversion of objects to and from YAML representations. The attributes that are included in the YAML representation are taken from an instance's __dict__ filtered through the list returned from the _yamlAttributeKeys property. The list from the _yamlAttributeKeys property is used to check for missing attributes when generating the YAML representation. It is also used to check for missing or extraneous attributes when constructing an instance from the YAML representation. Subclasses must override _yamlAttributeKeys. Subclasses must specify the class attribute yaml_tag which indicates the type of the instance in the YAML representation. Class attributes: yaml_tag (unicode string) - YAML representation identfifier; must be specified by subclasses yaml_loader - The loader to use; set to yaml.SafeLoader to allow yaml.load_safe() to instantiate objects ccs1|j}|V|j|}|j|dS(sConstructs and returns an instance from its YAML representation. Returns: instance constructed from YAML representation. N(t_yamlMakeInstancetconstruct_mappingt_yamlSetAttributes(tclstloadertnodetinstancetmapping((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyt from_yaml>s cCs|j}|j|j|S(sgReturns a YAML representation of the instance. Returns: YAML representation of instance (t _yamlDatatrepresent_mappingtyaml_tag(RtdumpertdatatyamlData((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pytto_yamlKs cCs tt|ji|_dS(N(tsuperRt__init__t_preservedExtraAttributes(tself((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRVscCs|S(sReturns an instance of the class specifying placeholder values for any arguments required by the __init__ method. The default implementation is to instantiate without arguments. Subclasses must override if their __init__ method takes arguments. ((R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR]scCsftg|jjD]6\}}||jkr||jkr||f^q}|j|j|S(s Returns a dictionary containing the data to include in generating the instance's YAML representation. The base implementation uses the contents of the instance's __dict__ filtered through the list of keys returned from _yamlAttributeKeys excluding any that require special handling (subclasses must override this method to add those) and adds any entries from the preserved extra attributes. Returns: dictionary of data to use in generating the instance's YAML representation (tdictt__dict__t iteritemst_yamlAttributeKeyst_yamlSpeciallyHandledAttributestupdateR(RtkeytvalueR((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR hs $cCs tdS(sReturns a list of the keys for the attributes to include in the instance's YAML representation. Must be overridden by subclasses. Returns: list of keys for attributes to include in the instance's YAML representation N(tNotImplementedError(R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs cCstg|jD]'\}}||jkr||f^q}|jj|g|jD]*}||jkr]||jkr]|^q]}x"|D]}t||||qWdS(sSets the instance's internal attributes from the YAML attributes. By default, the attributes are set via invoking setattr() targeted to the instance. If a subclass uses different internal names or computes the attributes in some way it must override this method to handle the attributes appropriately. The subclass must also account for the possibility that the attributes it receives may not contain the entirety of such specially handled attributes; in other words, it must check for each attribute's existence in the attributes dictionary it receives. Any unspecified attributes must be given a default value in whatever manner the subclass chooses. Any entries in the specified attributes which are unknown to the entity being constructed are preserved for later use in generating YAML output. Arguments: attributes (dictionary) - the attributes from the YAML representation N(RtitemsRRRtkeysRtsetattr(Rt attributesRRtextraR ((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs$ cCsgS(sReturns a list of attributes that are specially handled by subclasses. These attributes are skipped by _yamlData and _yamlSetAttributes implemented by YAMLObject. Subclasses must override both _yamlData and _yamlSetAttributes to handle these attributes. ((R((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyRs cCsAt|t|s*ttdn|jj|jdS(sUpdates the current object (self) from the specified instance. This is for classes that perform indirect construction using the results of the YAML load. Instances of such classes are required to invoke this method themselves. The specified instance must be the same class (or a subclass) of the current object to guarantee that any attributes the current object attempts to update will be available from the instance. Arguments: instance (YAMLObject) - object source for update Raises: TypeError - specified instance is not the same class (or a subclass) of the current object s(attempt to update from incompatible typeN(t isinstancettypet TypeErrort_RR(RR((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyt_yamlUpdateFromInstances(t__name__t __module__t__doc__tyamlt SafeLoadert yaml_loadert classmethodR RRRtpropertyR RRRR((((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyR"s      (R+tgettextR,tinstallR(((s8/usr/lib/python2.7/site-packages/vdo/utils/YAMLObject.pyts   Command.pyc000064400000025602147221674750006663 0ustar00 .t_c@sdZddlmZddlmZmZddlZddlZddlZddlZddl Z de fdYZ de fd YZ d Zd ZdS( s Command - runs commands and manages their results $Id: //eng/vdo-releases/magnesium/src/python/vdo/utils/Command.py#3 $ i(tLoggeri(tPopentPIPENt CommandErrorcBsDeZdZdZdZdZdZdZdZRS(sException raised to indicate an error running a command. Arguments: exitCode (int): The exit code of the command stdout (string): The output from the command stderr (string): The error output from the command message (string): The (localized) error text; will be formatted with the remaining arguments args: Arguments for formatting the message cCs|jS(N(t _exitCode(tself((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt getExitCode0scCs|jS(N(t_stderr(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pytgetStandardError4scCs||j||jdS(sLog the outputs of the failed command which generated this exception. Arguments: logMethod (callable): The method to log with N(t_stdoutR(Rt logMethod((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt logOutputs8s cGs|j||_dS(sSet the error message in this exception. Arguments: message (string): The (localized) message text; will be formatted with *args args: Values to pass to the format of message N(tformatt_message(Rtmessagetargs((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt setMessageBscGsBtt|j||_||_||_|j||dS(N(tsuperRt__init__RR RR(RtexitCodetstdouttstderrRR((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyROs    cCs|jS(N(R (R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt__str__Ws( t__name__t __module__t__doc__RRR RRR(((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyR"s    tCommandcBseZdZeZdZejej dZ e dZ e eedZ dZdZd dZdZdd d d Zd Zd ZRS(sVCommand encapsulates shell commands, runs them, and manages the result. Attributes: noRun (bool): if True, don't run the command, and always succeed shell (bool): if True, run this command using shell -c verbose (int): if > 0, print commands to stdout before executing them _commandList (list): command and its arguments is.CommandcCs|jS(s+Returns True iff Commands default to noRun.(t defaultNoRun(tcls((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt noRunModekscCs1|r||_t|_n|r-||_ndS(sSets the verbose and noRun default values. Arguments: verbose: (boolean) If True, operate verbosely. noRun: (boolean) If True, do not actually execute. N(RtTruetdefaultVerbose(RtverbosetnoRun((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt setDefaultsqs   cCs |jdS(s3Returns an identifier (argv[0]) for error messages.i(t _commandList(R((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pyt commandNamescKs|jdd}|jdd }|jsE|jdt|_n|j}|dkry|jjdj|nyxt|D]}|dkr|jjdj||n|j dkrd|GH|jj |n|j rd Sy3|j |}|jd tr |j S|SWqtk r}||dkr~|dkru|jtd |j|n|ntjdqXqWWn/tk r}|jd trd S|nXd S(sRun a command. Returns the output of running the command. Arguments: noThrow: If True, will return an empty string instead of throwing on error. retries: The number of times to try the command before giving up. Defaults to 1. shell: Indicate that this is a shell command stdin: If not None, the stream from which the command should take its input, defaults to None. strip: If True, strip leading and trailing whitespace from the command output before returning it. Exceptions: CommandError: if the command failed and noThrow is False tretriesitstdintshellsWaiting for '{0}'s ... {0}/{1}is Ntstrips {0}: timed out after {1} secondstnoThrowt(tgettNoneR'tFalset_getCommandLinetlogtdebugR trangeR tinfoR!t_executeR(RRt_R$ttimetsleep(RtkwargsR%R&t commandLinetcounttoutputte((s5/usr/lib/python2.7/site-packages/vdo/utils/Command.pytruns<      $  cCstt|jtj|_t|_tj|_||_ |rt j t j |_x3|jD]\}}||j|s     9 pbkdf2.py000064400000015260147221702050006272 0ustar00"""passlib.pbkdf2 - PBKDF2 support this module is getting increasingly poorly named. maybe rename to "kdf" since it's getting more key derivation functions added. """ #============================================================================= # imports #============================================================================= from __future__ import division # core import logging; log = logging.getLogger(__name__) # site # pkg from passlib.exc import ExpectedTypeError from passlib.utils.decor import deprecated_function from passlib.utils.compat import native_string_types from passlib.crypto.digest import norm_hash_name, lookup_hash, pbkdf1 as _pbkdf1, pbkdf2_hmac, compile_hmac # local __all__ = [ # hash utils "norm_hash_name", # prf utils "get_prf", # kdfs "pbkdf1", "pbkdf2", ] #============================================================================= # issue deprecation warning for module #============================================================================= from warnings import warn warn("the module 'passlib.utils.pbkdf2' is deprecated as of Passlib 1.7, " "and will be removed in Passlib 2.0, please use 'passlib.crypto' instead", DeprecationWarning) #============================================================================= # hash helpers #============================================================================= norm_hash_name = deprecated_function(deprecated="1.7", removed="1.8", func_module=__name__, replacement="passlib.crypto.digest.norm_hash_name")(norm_hash_name) #============================================================================= # prf lookup #============================================================================= #: cache mapping prf name/func -> (func, digest_size) _prf_cache = {} #: list of accepted prefixes _HMAC_PREFIXES = ("hmac_", "hmac-") def get_prf(name): """Lookup pseudo-random family (PRF) by name. :arg name: This must be the name of a recognized prf. Currently this only recognizes names with the format :samp:`hmac-{digest}`, where :samp:`{digest}` is the name of a hash function such as ``md5``, ``sha256``, etc. todo: restore text about callables. :raises ValueError: if the name is not known :raises TypeError: if the name is not a callable or string :returns: a tuple of :samp:`({prf_func}, {digest_size})`, where: * :samp:`{prf_func}` is a function implementing the specified PRF, and has the signature ``prf_func(secret, message) -> digest``. * :samp:`{digest_size}` is an integer indicating the number of bytes the function returns. Usage example:: >>> from passlib.utils.pbkdf2 import get_prf >>> hmac_sha256, dsize = get_prf("hmac-sha256") >>> hmac_sha256 >>> dsize 32 >>> digest = hmac_sha256('password', 'message') .. deprecated:: 1.7 This function is deprecated, and will be removed in Passlib 2.0. This only related replacement is :func:`passlib.crypto.digest.compile_hmac`. """ global _prf_cache if name in _prf_cache: return _prf_cache[name] if isinstance(name, native_string_types): if not name.startswith(_HMAC_PREFIXES): raise ValueError("unknown prf algorithm: %r" % (name,)) digest = lookup_hash(name[5:]).name def hmac(key, msg): return compile_hmac(digest, key)(msg) record = (hmac, hmac.digest_info.digest_size) elif callable(name): # assume it's a callable, use it directly digest_size = len(name(b'x', b'y')) record = (name, digest_size) else: raise ExpectedTypeError(name, "str or callable", "prf name") _prf_cache[name] = record return record #============================================================================= # pbkdf1 support #============================================================================= def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"): """pkcs#5 password-based key derivation v1.5 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate (if ``None``, uses digest's native size) :param hash: hash function to use. must be name of a hash recognized by hashlib. :returns: raw bytes of generated key .. note:: This algorithm has been deprecated, new code should use PBKDF2. Among other limitations, ``keylen`` cannot be larger than the digest size of the specified hash. .. deprecated:: 1.7 This has been relocated to :func:`passlib.crypto.digest.pbkdf1`, and this version will be removed in Passlib 2.0. *Note the call signature has changed.* """ return _pbkdf1(hash, secret, salt, rounds, keylen) #============================================================================= # pbkdf2 #============================================================================= def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"): """pkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this must be a string starting with ``"hmac-"``, followed by the name of a known digest. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) .. rst-class:: warning .. versionchanged 1.7: This argument no longer supports arbitrary PRF callables -- These were rarely / never used, and created too many unwanted codepaths. :returns: raw bytes of generated key .. deprecated:: 1.7 This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`, and will be removed in Passlib 2.0. *Note the call signature has changed.* """ if callable(prf) or (isinstance(prf, native_string_types) and not prf.startswith(_HMAC_PREFIXES)): raise NotImplementedError("non-HMAC prfs are not supported as of Passlib 1.7") digest = prf[5:] return pbkdf2_hmac(digest, secret, salt, rounds, keylen) #============================================================================= # eof #============================================================================= pbkdf2.pyo000064400000013743147221702050006455 0ustar00 5Xc @ sdZddlmZddlZejeZddlmZddl m Z ddl m Z ddl mZmZmZmZmZdd d d gZdd lmZed ee dddddeddeZiadZdZdddZdddZdS(spasslib.pbkdf2 - PBKDF2 support this module is getting increasingly poorly named. maybe rename to "kdf" since it's getting more key derivation functions added. i(tdivisionN(tExpectedTypeError(tdeprecated_function(tnative_string_types(tnorm_hash_namet lookup_hashtpbkdf1t pbkdf2_hmact compile_hmacRtget_prfRtpbkdf2(twarnsthe module 'passlib.utils.pbkdf2' is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0, please use 'passlib.crypto' insteadt deprecateds1.7tremoveds1.8t func_modulet replacements$passlib.crypto.digest.norm_hash_namethmac_shmac-c s|tkrt|St|tr|jtsHtd|fnt|djfd}||jj f}nBt |rt |dd}||f}nt |dd|t|<|S(sLookup pseudo-random family (PRF) by name. :arg name: This must be the name of a recognized prf. Currently this only recognizes names with the format :samp:`hmac-{digest}`, where :samp:`{digest}` is the name of a hash function such as ``md5``, ``sha256``, etc. todo: restore text about callables. :raises ValueError: if the name is not known :raises TypeError: if the name is not a callable or string :returns: a tuple of :samp:`({prf_func}, {digest_size})`, where: * :samp:`{prf_func}` is a function implementing the specified PRF, and has the signature ``prf_func(secret, message) -> digest``. * :samp:`{digest_size}` is an integer indicating the number of bytes the function returns. Usage example:: >>> from passlib.utils.pbkdf2 import get_prf >>> hmac_sha256, dsize = get_prf("hmac-sha256") >>> hmac_sha256 >>> dsize 32 >>> digest = hmac_sha256('password', 'message') .. deprecated:: 1.7 This function is deprecated, and will be removed in Passlib 2.0. This only related replacement is :func:`passlib.crypto.digest.compile_hmac`. sunknown prf algorithm: %ric st||S(N(R(tkeytmsg(tdigest(s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pythmachstxtysstr or callablesprf name( t _prf_cachet isinstanceRt startswitht_HMAC_PREFIXESt ValueErrorRtnamet digest_infot digest_sizetcallabletlenR(RRtrecordR((Rs8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyR 9s)   tsha1cC st|||||S(sLpkcs#5 password-based key derivation v1.5 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate (if ``None``, uses digest's native size) :param hash: hash function to use. must be name of a hash recognized by hashlib. :returns: raw bytes of generated key .. note:: This algorithm has been deprecated, new code should use PBKDF2. Among other limitations, ``keylen`` cannot be larger than the digest size of the specified hash. .. deprecated:: 1.7 This has been relocated to :func:`passlib.crypto.digest.pbkdf1`, and this version will be removed in Passlib 2.0. *Note the call signature has changed.* (t_pbkdf1(tsecrettsalttroundstkeylenthash((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyRwss hmac-sha1cC sZt|s+t|tr:|jt r:tdn|d}t|||||S(sWpkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this must be a string starting with ``"hmac-"``, followed by the name of a known digest. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) .. rst-class:: warning .. versionchanged 1.7: This argument no longer supports arbitrary PRF callables -- These were rarely / never used, and created too many unwanted codepaths. :returns: raw bytes of generated key .. deprecated:: 1.7 This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`, and will be removed in Passlib 2.0. *Note the call signature has changed.* s1non-HMAC prfs are not supported as of Passlib 1.7i(RRRRRtNotImplementedErrorR(R$R%R&R'tprfR((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyR s%+ (Rshmac-(t__doc__t __future__Rtloggingt getLoggert__name__tlogt passlib.excRtpasslib.utils.decorRtpasslib.utils.compatRtpasslib.crypto.digestRRRR#RRt__all__twarningsR tDeprecationWarningRRR tNoneR (((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyts* (  >des.py000064400000004163147221702050005675 0ustar00""" passlib.utils.des - DEPRECATED LOCATION, WILL BE REMOVED IN 2.0 This has been moved to :mod:`passlib.crypto.des`. """ #============================================================================= # import from new location #============================================================================= from warnings import warn warn("the 'passlib.utils.des' module has been relocated to 'passlib.crypto.des' " "as of passlib 1.7, and the old location will be removed in passlib 2.0", DeprecationWarning) #============================================================================= # relocated functions #============================================================================= from passlib.utils.decor import deprecated_function from passlib.crypto.des import expand_des_key, des_encrypt_block, des_encrypt_int_block expand_des_key = deprecated_function(deprecated="1.7", removed="1.8", replacement="passlib.crypto.des.expand_des_key")(expand_des_key) des_encrypt_block = deprecated_function(deprecated="1.7", removed="1.8", replacement="passlib.crypto.des.des_encrypt_block")(des_encrypt_block) des_encrypt_int_block = deprecated_function(deprecated="1.7", removed="1.8", replacement="passlib.crypto.des.des_encrypt_int_block")(des_encrypt_int_block) #============================================================================= # deprecated functions -- not carried over to passlib.crypto.des #============================================================================= import struct _unpack_uint64 = struct.Struct(">Q").unpack @deprecated_function(deprecated="1.6", removed="1.8", replacement="passlib.crypto.des.des_encrypt_int_block()") def mdes_encrypt_int_block(key, input, salt=0, rounds=1): # pragma: no cover -- deprecated & unused if isinstance(key, bytes): if len(key) == 7: key = expand_des_key(key) key = _unpack_uint64(key)[0] return des_encrypt_int_block(key, input, salt, rounds) #============================================================================= # eof #============================================================================= decor.pyo000064400000017703147221702050006401 0ustar00 Xc@`sdZddlmZmZmZddlZejeZddl m Z m Z ddl Z ddl mZddlmZddd d d d gZdefd YZdefdYZdZd efdYZdddededdZdddeddZdS(s7 passlib.utils.decor -- helper decorators & properties i(tabsolute_importtdivisiontprint_functionN(twrapstupdate_wrapper(twarn(tPY3t classpropertyt hybrid_methodtmemoize_single_valuetmemoized_propertytdeprecated_functiontdeprecated_methodcB`s/eZdZdZdZedZRS(sjFunction decorator which acts like a combination of classmethod+property (limited to read-only properties)cC`s ||_dS(N(tim_func(tselftfunc((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__init__#scC`s |j|S(N(R (Rtobjtcls((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__get__&scC`s|jS(spy3 compatible alias(R (R((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__func__)s(t__name__t __module__t__doc__RRtpropertyR(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s  cB`s eZdZdZdZRS(s decorator which invokes function with class if called as class method, and with object if called at instance level. cC`s||_t||dS(N(RR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR4s cC`sH|dkr|}ntr.tj|j|Stj|j||SdS(N(tNoneRttypest MethodTypeR(RRR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR8s   (RRRRR(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR.s c`s@itfd}fd}||_|S(s decorator for function which takes no args, and memoizes result. exposes a ``.clear_cache`` method to clear the cached value. c`s5y tSWntk rnX}t<|S(N(tTruetKeyError(tvalue(tcacheR(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pytwrapperLs   c`sjtddS(N(tpopRR((R(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt clear_cacheUs(RR"(RR R"((RRs7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR Ds   cB`sMeZdZdZdZes6edZndZddZ RS(sM decorator which invokes method once, then replaces attr with result cC`s%||_|j|_|j|_dS(N(RRR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR_s  cC`s6|dkr|S|j|}t||j||S(N(RRtsetattrR(RRRR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyRds  cC`s|jS(s py2 alias(R(R((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR mscC`s|jj|jddS(s class-level helper to clear stored value (if any). usage: :samp:`type(self).{attr}.clear_cache(self)` N(t__dict__R!RR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR"rscC`s|jj|j|S(s class-level helper to peek at stored value usage: :samp:`value = type(self).{attr}.clear_cache(self)` (R$tgetR(RRtdefault((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt peek_cachezsN( RRRRRRRR R"RR'(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR [s   c`sdkrkrdndr4d7nrGd7nr^d7nd7nfd}|S( sbdecorator to deprecate a function. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when function was first deprecated :kwd removed: version when function will be removed :kwd replacement: alternate name / instructions for replacing this function. :kwd updoc: add notice to docstring (default ``True``) s5the method %(mod)s.%(klass)s.%(name)s() is deprecateds-the function %(mod)s.%(name)s() is deprecateds as of Passlib %(deprecated)ss,, and will be removed in Passlib %(removed)ss, use %s insteadt.c `sottr3jdtjntdpEjdjddrfd}nfd}t | rsr|j rd|j krpd}s rG|d 7}r|d f7}n r:r)|d 7}n|d 7}n|d 7}n|j j dj dst|j d7_ n|j d|f7_ nrt|}n|S(Ntmodtnamet deprecatedtremovedc`sij}r|dn |dj}|jd|jd|jt|tdd||S(NitklassR)t stackleveli(tcopyt __class__tupdateRRRtDeprecationWarning(targstkwdsttmpR-(Rtis_classmethodtmsgtopts(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s  c`s ttdd||S(NR.i(RR2(R3R4(Rttext(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR ss.. deprecated::ts s!and will be removed in version %ss, suse %s insteadR(t s s .. deprecated:: %s ( t isinstancet classmethodRRttypeRtdictRRRRtstriptendswith(RR ttxt(t _is_methodR+t func_moduleR7R,t replacementtupdoc(RR6R8R9s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pytbuilds>         N(R(R7R+R,RFRERCRDRG((RCR+RDR7R,RERFs7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s     !*cC`st|||||dtS(sZdecorator to deprecate a method. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when method was first deprecated :kwd removed: version when method will be removed :kwd replacement: alternate name / instructions for replacing this method. :kwd updoc: add notice to docstring (default ``True``) RC(R R(R7R+R,RFRE((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s (Rt __future__RRRtloggingt getLoggerRtlogt functoolsRRRtwarningsRtpasslib.utils.compatRt__all__tobjectRRR R RRtFalseR R (((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyts,    <  A binary.pyo000064400000057410147221702050006570 0ustar00 5Xc@`sdZddlmZmZmZddlmZmZmZ m Z ddl m Z mZmZddlZejeZddlmZddlmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#ddl$m%Z%d d d d d ddddddddddddddddgZ&e!dZ'e!dZ(e!d Z)e!d!Z*e'e!d"Z+e!d#Z,e!d$Z-e!d%Z.eed&Z/d'Z0d(Z1d"Z2e3ee/Z4e5d)Z6d*Z7d+Z8d,Z9d"Z:d-Z;d.Z<d/Z=d0Z e6id1d26d3d46Z>e2d5Z?d6Zde@fd7YZAdeAfd8YZBeBe)ZCeBe)d9eDZEeBe*d9eDZFdS(:sC passlib.utils.binary - binary data encoding/decoding/manipulation i(tabsolute_importtdivisiontprint_function(t b64encodet b64decodet b32decodet b32encode(t b2a_base64t a2b_base64tErrorN(texc( tPY3t bascii_to_strtirangetimaptiter_byte_charstjoin_byte_valuestjoin_byte_elemst nextgettertsuppress_causetutunicodetunicode_or_bytes_types(tmemoized_propertyt BASE64_CHARStPADDED_BASE64_CHARSt AB64_CHARSt HASH64_CHARSt BCRYPT_CHARSt HEX_CHARStLOWER_HEX_CHARStUPPER_HEX_CHARStALL_BYTE_VALUEStcompile_byte_translationt ab64_encodet ab64_decodet b64s_encodet b64s_decodeRRt Base64EnginetLazyBase64Engineth64th64bigtbcrypt64s@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/s@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./s@./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzs@./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789t=t0123456789abcdefABCDEFt0123456789ABCDEFt0123456789abcdefittcC`s|dkrt}ntt|}xc|jD]U\}}t|tr_t|}nt|tr|j d}n||| output byte (str or int). :param source: optional existing byte translation string to use as base. (must be 255-length byte string). defaults to identity mapping. :returns: 255-length byte string for passing to bytes().translate. tasciiN( tNonet_TRANSLATE_SOURCEtlistRtitemst isinstanceRtordRtencodetB_EMPTYtjoin(tmappingtsourcettargettktv((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR!ns  cC`st|jtS(sr encode using shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. (Rtrstript _BASE64_STRIP(tdata((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR$scC`st|trKy|jd}WqKtk rGttdqKXnt|d@}|dkrjn>|dkr|t7}n%|dkr|t7}n tdyt |SWn%t k r}tt |nXdS(sq decode from shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. R1s4string argument should contain only ASCII charactersiiisinvalid base64 inputN( R6RR8tUnicodeEncodeErrorRt ValueErrortlent _BASE64_PAD2t _BASE64_PAD1Rt_BinAsciiErrort TypeError(RBtoffterr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR%s"       s= s==cC`st|jddS(s encode using shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars. it is primarily used by Passlib's custom pbkdf2 hashes. t+t.(R$treplace(RB((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR"scC`sat|trKy|jd}WqKtk rGttdqKXnt|jddS(s decode from shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars, but supports decoding normal ``+/`` altchars as well. it is primarily used by Passlib's custom pbkdf2 hashes. R1s4string argument should contain only ASCII charactersRMRL(R6RR8RCRRDR%RN(RB((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR#s  cC`stt|jtS(sh wrapper around :func:`base64.b32encode` which strips padding, and returns a native string. (R t _b32encodeR@tB_EQUAL(R<((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRstBt8tOt0icC`set|tr!|jd}n|jt}t|d@}|rX|t| 7}nt|tS(s wrapper around :func:`base64.b32decode` which handles common mistyped chars. padding optional, ignored if present. R1i( R6RR8t translatet_b32_translateREt_b32_decode_padt _b32decodetTrue(R<t remainder((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRscB`s:eZdZdZdZdZdZdZdZ e dZ e dZ dZdZdZdZdZdZd Zed Zed Zd Zd ZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'RS(scProvides routines for encoding/decoding base64 data using arbitrary character mappings, selectable endianness, etc. :arg charmap: A string of 64 unique characters, which will be used to encode successive 6-bit chunks of data. A character's position within the string should correspond to its 6-bit value. :param big: Whether the encoding should be big-endian (default False). .. note:: This class does not currently handle base64's padding characters in any way what so ever. Raw Bytes <-> Encoded Bytes =========================== The following methods convert between raw bytes, and strings encoded using the engine's specific base64 variant: .. automethod:: encode_bytes .. automethod:: decode_bytes .. automethod:: encode_transposed_bytes .. automethod:: decode_transposed_bytes .. .. automethod:: check_repair_unused .. automethod:: repair_unused Integers <-> Encoded Bytes ========================== The following methods allow encoding and decoding unsigned integers to and from the engine's specific base64 variant. Endianess is determined by the engine's ``big`` constructor keyword. .. automethod:: encode_int6 .. automethod:: decode_int6 .. automethod:: encode_int12 .. automethod:: decode_int12 .. automethod:: encode_int24 .. automethod:: decode_int24 .. automethod:: encode_int64 .. automethod:: decode_int64 Informational Attributes ======================== .. attribute:: charmap unicode string containing list of characters used in encoding; position in string matches 6bit value of character. .. attribute:: bytemap bytes version of :attr:`charmap` .. attribute:: big boolean flag indicating this using big-endian encoding. cC`st|tr!|jd}n$t|tsEtj|dnt|dkrftdntt|dkrtdn||_ |j |_ t dt |D}|j |_||_|r|j|_|j|_n|j|_|j|_dS(Nslatin-1tcharmapi@s'charmap must be 64 characters in lengths-charmap must not contain duplicate characterscs`s!|]\}}||fVqdS(N((t.0tidxtvalue((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys ]s(R6RR8tbytesR tExpectedStringErrorRERDtsettbytemapt __getitem__t _encode64tdictt enumeratet _decode64tbigt_encode_bytes_bigt _encode_bytest_decode_bytes_bigt _decode_bytest_encode_bytes_littlet_decode_bytes_little(tselfR[Rhtlookup((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt__init__Qs$      cC`s|jjdS(scharmap as unicodeslatin-1(Rbtdecode(Ro((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR[sscC`st|ts+tdt|fntt|d\}}tratt|}ntd|D}|j |||}t t |j |}|S(sencode bytes to base64 string. :arg source: byte string to encode. :returns: byte string containing encoded data. ssource must be bytes, not %sics`s|]}t|VqdS(N(R7(R\telem((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys s( R6R_RIttypetdivmodRER RtiterRjRRRd(RoR<tchunksttailt next_valuetgentout((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_bytes{scc`sd}xq||kry|}|}|}|d@V|d@d>|d?BV|d@d>|d?BV|d?V|d7}q W|r|}|dkr|d@V|d?Vq|}|d@V|d@d>|d?BV|d?Vnd S( s>helper used by encode_bytes() to handle little-endian encodingii?iiiiiiN((RoRyRwRxR]tv1tv2tv3((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRms&           cc`sd}xq||kry|}|}|}|d?V|d@d>|d?BV|d@d>|d?BV|d@V|d7}q W|r|}|dkr|d?V|d@d>Vq|}|d?V|d@d>|d?BV|d@d>Vnd S( s;helper used by encode_bytes() to handle big-endian encodingiiiiiii?iN((RoRyRwRxR]R}R~R((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRis&          cC`st|ts+tdt|fntt|d\}}|dkratdntt|j |}yt |j |||SWn-t k r}td|j dfnXdS(sdecode bytes from base64 string. :arg source: byte string to decode. :returns: byte string containing decoded data. ssource must be bytes, not %siis(input string length cannot be == 1 mod 4sinvalid character: %riN(R6R_RIRtRuRERDRRRgRRltKeyErrortargs(RoR<RwRxRyRK((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_bytess c c`sd}xu||kr}|}|}|}|}||d@d>BV|d?|d@d>BV|d?|d>BV|d7}q W|r|}|}||d@d>BV|dkr|}|d?|d@d>BVqndS( s>helper used by decode_bytes() to handle little-endian encodingiiiiiiiN(( RoRyRwRxR]R}R~Rtv4((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRns"        c c`sd}xu||kr}|}|}|}|}|d>|d?BV|d@d>|d?BV|d@d>|BV|d7}q W|r|}|}|d>|d?BV|dkr|}|d@d>|d?BVqndS( s;helper used by decode_bytes() to handle big-endian encodingiiiiiiiN(( RoRyRwRxR]R}R~RR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRks"        c`sUtfdt|jD}|jfdt|jDt|S(s2helper to generate set of valid last chars & bytesc3`s%|]\}}|@s|VqdS(N((R\titc(tbits(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys Gsc3`s%|]\}}|@s|VqdS(N((R\RR(R(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys Hs(RaRfRbtupdateR[t frozenset(RoRtpset((Rs8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt __make_padsetEs%&cC`s)|jrdnd}||j|fS(sDmask to clear padding bits, and valid last bytes (for strings 2 % 4)iii<(Rht_Base64Engine__make_padset(RoR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _padinfo2KscC`s)|jrdnd}||j|fS(sDmask to clear padding bits, and valid last bytes (for strings 3 % 4)iii0(RhR(RoR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _padinfo3RscC`st|d@}|dkr.|j\}}n:|dkrL|j\}}n|s\t|fStd|d}||krt|fSt|tr|j}||j||@}n4|j |j ||@}t rt |g}nt |d |fS(shelper to detect & clear invalid unused bits in last character. :arg source: encoded data (as ascii bytes or unicode). :returns: `(True, result)` if the string was repaired, `(False, source)` if the string was ok as-is. iissource length must != 1 mod 4i(RERRtFalseRDR6RR[tindexRdRgR R_RY(RoR<Rxtmasktpadsettlasttcm((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytcheck_repair_unusedYs&         cC`s|j|dS(Ni(R(RoR<((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt repair_unusedsc`sTtts+tdtfntfd|D}|j|S(s>encode byte string, first transposing source using offset listssource must be bytes, not %sc3`s|]}|VqdS(N((R\RJ(R<(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys s(R6R_RIRtRR|(RoR<toffsetsttmp((R<s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytencode_transposed_bytesscC`sV|j|}dgt|}x't||D]\}}|||||}qWWn$t k rtd|fnX|r|r||L}q|d|>dM}n|S(sdecode base64 string -> integer :arg source: base64 string to decode. :arg bits: number of bits in resulting integer. :raises ValueError: * if the string contains invalid base64 characters. * if the string is not long enough - it must be at least ``int(ceil(bits/6))`` in length. :returns: a integer in the range ``0 <= n < 2**bits`` ssource must be bytes, not %sissource must be %d charsisinvalid character in string: %ri( R6R_RIRtRhRERDRgtreversedR( RoR<RRhtpadtcharsRrR{R((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _decode_ints&     cC`st|ts+tdt|fnt|dkrLtdntr_|d}ny|j|SWntk rtdnXdS(s(decode single character -> 6 bit integerssource must be bytes, not %sissource must be exactly 1 byteisinvalid characterN( R6R_RIRtRERDR RgR(RoR<((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int6s  cC`st|ts+tdt|fnt|dkrLtdn|j}yM|jr||d||dd>S||d||dd>SWntk rtdnXdS( s'decodes 2 char string -> 12-bit integerssource must be bytes, not %sissource must be exactly 2 bytesiiisinvalid characterN( R6R_RIRtRERDRgRhR(RoR<Rr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int12s   $ cC`st|ts+tdt|fnt|dkrLtdn|j}y|jr||d||dd>||dd>||d d >S||d ||dd>||dd>||dd >SWntk r td nXd S( s'decodes 4 char string -> 24-bit integerssource must be bytes, not %sissource must be exactly 4 bytesiiiii iisinvalid characterN( R6R_RIRtRERDRgRhR(RoR<Rr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int24s  DH cC`s|j|dS(s&decode 5 char string -> 30 bit integeri(R(RoR<((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int30scC`s|j|dS(sdecode 11 char base64 string -> 64-bit integer this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. i@(R(RoR<((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int64sc`sy| d}||7}|jrAt|ddd}|Kntd|d}tt|jfd|DS(sencode integer into base64 format :arg value: non-negative integer to encode :arg bits: number of bits to encode :returns: a string of length ``int(ceil(bits/6.0))``. iiic3`s|]}|?d@VqdS(i?N((R\RJ(R^(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys "s(RhR RRRd(RoR^RRtitr((R^s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _encode_ints     cC`sP|dks|dkr'tdntr?|j||d!S|j|SdS(s0encodes 6-bit integer -> single hash64 characterii?svalue out of rangeiN(RDR RbRd(RoR^((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int6(s cC`sm|dks|dkr'tdn|d@|d?d@g}|jrWt|}ntt|j|S(s'encodes 12-bit integer -> 2 char stringiisvalue out of rangei?i(RDRhRRRRd(RoR^traw((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int121s  cC`s|dks|dkr'tdn|d@|d?d@|d?d@|d?d@g}|jrmt|}ntt|j|S(s'encodes 24-bit integer -> 4 char stringiisvalue out of rangei?ii i(RDRhRRRRd(RoR^R((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int24:s cC`s7|dks|dkr'tdn|j|dS(s&decode 5 char string -> 30 bit integerii?svalue out of rangei(RDR(RoR^((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int30DscC`s7|dks|dkr'tdn|j|dS(sencode 64-bit integer -> 11 char hash64 string this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. ilsvalue out of rangei@(RDR(RoR^((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int64JsN((t__name__t __module__t__doc__R2RbRhRdRgRjRlRRqtpropertyR[R|RmRiRRnRkRRRRRRRRRRRRRRRRRRRR(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR&sD? "  ' +  # *  )    (      cB`s/eZdZdZdZdZdZRS(s<Base64Engine which delays initialization until it's accessedcO`s||f|_dS(N(t _lazy_opts(RoRtkwds((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRq\scC`s;|j\}}tt|j|||`t|_dS(N(RtsuperR'RqR&t __class__(RoRR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _lazy_init_scC`s,|jds|jntj||S(Nt_(t startswithRtobjectt__getattribute__(Rotattr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRes N(RRRR2RRqRR(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR'Xs   Rh(GRt __future__RRRtbase64RRRRXRROtbinasciiRRR RHtloggingt getLoggerRtlogtpasslibR tpasslib.utils.compatR R R RRRRRRRRRtpasslib.utils.decorRt__all__RRRRRRRRR R9tB_NULLRPR4R3R2R!R$R%RARGRFR"R#RVRWRR&R'R(RYR)R*(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytsn" R         !      ] md4.py000064400000002302147221702050005577 0ustar00""" passlib.utils.md4 - DEPRECATED MODULE, WILL BE REMOVED IN 2.0 MD4 should now be looked up through ``passlib.crypto.digest.lookup_hash("md4").const``, which provides unified handling stdlib implementation (if present). """ #============================================================================= # issue deprecation warning for module #============================================================================= from warnings import warn warn("the module 'passlib.utils.md4' is deprecated as of Passlib 1.7, " "and will be removed in Passlib 2.0, please use " "'lookup_hash(\"md4\").const()' from 'passlib.crypto' instead", DeprecationWarning) #============================================================================= # backwards compat exports #============================================================================= __all__ = ["md4"] # this should use hashlib version if available, # and fall back to builtin version. from passlib.crypto.digest import lookup_hash md4 = lookup_hash("md4").const del lookup_hash #============================================================================= # eof #============================================================================= handlers.pyo000064400000227327147221702050007112 0ustar00 Xc@s:dZddlmZddlZddlZejeZddlZddl Z ddl m Z ddl j Z ddljZddl mZmZmZddlmZddlmZddlmZmZmZmZmZmZmZmZmZm Z m!Z!dd l"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dd l*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m0Z0m3Z3m4Z4m5Z5dd l6m7Z7m8Z8d d ddddddddddddgZ9e$Z:e#Z;e%Z<e'Z=e(Z>dZ?ddZ@dZAdZBe-dZCe-d ZDd!ZEd"ZFeCeGd#ZHeCd$eGeGd%ZId$eGd&eGd'ZJe-dd(ZKe-dd$d)ZLd&d*ZMdeGd&eNd+ZOd,efd-YZPd.ePfd/YZQdePfd0YZRdeRfd1YZSd2eRfd3YZTdeRfd4YZUdeRfd5YZVdeRfd6YZWdeRfd7YZXdeXfd8YZYdeRfd9YZZd:eRfd;YZ[e j\Z]d<efd=YZ^d>e^fd?YZ_de^eRfd@YZ`deafdAYZbdS(BsRpasslib.handler - code for implementing handlers, and global registry for handlersi(twith_statementN(twarn(tMissingBackendErrortPasslibConfigWarningtPasslibHashWarning(t PasswordHash(tget_crypt_handler( tconsteqt getrandstrt getrandbytestrngt to_native_strtis_crypt_handlert to_unicodetMAX_PASSWORD_SIZEtaccepts_keywordtas_booltupdate_mixin_classes(t BASE64_CHARSt HASH64_CHARStPADDED_BASE64_CHARSt HEX_CHARStUPPER_HEX_CHARStLOWER_HEX_CHARStALL_BYTE_VALUES( tjoin_byte_valuestirangetutnative_string_typest uascii_to_strt join_unicodetunicodet str_to_uasciiRtunicode_or_bytes_typestPY2t int_types(t classpropertytdeprecated_methodt parse_mc2t parse_mc3t render_mc2t render_mc3tGenericHandlert StaticHandlertHasUserContexttHasRawChecksumt HasManyIdentstHasSaltt HasRawSaltt HasRoundstHasManyBackendst PrefixWrappercCs@|r8|r8ddl}t||jt|dSdSdS(shelper for bitsize() methodsiNii(tmathtinttlogtlen(tcounttcharsR4((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_bitsizeJs   icCstj}| }zix^|rv|jjdd}|jdsS|jd r`td|S|d7}|j}qW|SWd~XdS(si try to guess stacklevel for application warning. looks for first frame not part of passlib. t__name__tspasslib.tests.spasslib.iN(tinspectt currentframet f_globalstgett startswithtmaxtf_back(tstarttframeR8tname((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytguess_app_stacklevelRs     cCs-tdtd|jtdtddS(Nspassing settings to %(handler)s.hash() is deprecated, and won't be supported in Passlib 2.0; use '%(handler)s.using(**settings).hash(secret)' insteadthandlert stackleveli(RtdictRFtDeprecationWarningRG(RHtkwds((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytwarn_hash_settings_deprecationdscs2t|jtfdtDS(s helper to extract settings kwds from mix of context & settings kwds. pops settings keys from kwds, returns them as a dict. c3s0|]&}|kr|j|fVqdS(N(tpop(t.0tkey(t context_keysRL(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys os(tsett context_kwdsRJtlist(RHRL((RQRLs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytextract_settings_kwdsist$t0cCsLt|ts$tj|dnt|tkrHtjtndS(s%ensure secret has correct type & sizetsecretN(t isinstanceR!texctExpectedStringErrorR7RtPasswordSizeError(RX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_secretwscCsjt|tr|St|trTy|jdSWqftk rP|jdSXntj|ddS(s+convert hash to unicode for identify methodsutf-8slatin-1thashN(RYRtbytestdecodetUnicodeDecodeErrorRZR[(R^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytto_unicode_for_identify~s cCst|dd}|j|s3tj|n|t|j|}t|dkrz|\}}||pvdfSt|dkr|ddfStj|dS(sparse hash using 2-part modular crypt format. this expects a hash of the format :samp:`{prefix}{salt}[${checksum}]`, such as md5_crypt, and parses it into salt / checksum portions. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param handler: handler class to pass to error constructors. :returns: a ``(salt, chk | None)`` tuple. tasciiR^iiiN(R RARZtInvalidHashErrorR7tsplittNonetMalformedHashError(R^tprefixtsepRHtpartstsalttchk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR&s i c Cs%t|dd}|j|s3tj|n|t|j|}t|dkrp|\}}} n6t|dkr|\}}d} ntj||jtr|tkrtj |n?|rt ||}n'|dkr tj|dn|}||| p!dfS(srparse hash using 3-part modular crypt format. this expects a hash of the format :samp:`{prefix}[{rounds}]${salt}[${checksum}]`, such as sha1_crypt, and parses it into rounds / salt / checksum portions. tries to convert the rounds to an integer, and throws error if it has zero-padding. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param rounds_base: the numeric base the rounds are encoded in (defaults to base 10). :param default_rounds: the default rounds value to return if the rounds field was omitted. if this is ``None`` (the default), the rounds field is *required*. :param handler: handler class to pass to error constructors. :returns: a ``(rounds : int, salt, chk | None)`` tuple. RcR^iisempty rounds fieldN( R RARZRdR7ReRfRgt_UZEROtZeroPaddedRoundsErrorR5( R^RhRit rounds_basetdefault_roundsRHRjtroundsRkRl((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR's$   tvaluecCst|jtr4|tkr4tj|d|n<|rGt||S|dkrltj|d|n|SdS(s helper to parse an integer config field :arg source: unicode source string :param base: numeric base :param default: optional default if source is empty :param param: name of variable, for error msgs :param handler: handler class, for error msgs szero-padded %s fieldsempty %s fieldN(RARmRZRgR5Rf(tsourcetbasetdefaulttparamRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parse_ints   cCs7|r||||g}n ||g}tt|S(sformat hash using 2-part modular crypt format; inverse of parse_mc2() returns native string with format :samp:`{ident}{salt}[${checksum}]`, such as used by md5_crypt. :arg ident: identifier prefix (unicode) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :returns: config or hash (native str) (RR(tidentRktchecksumRiRj((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR( s cCs|dkrtd}n+|dkr:td|}n t|}|rg||||||g}n||||g}tt|S(s.format hash using 3-part modular crypt format; inverse of parse_mc3() returns native string with format :samp:`{ident}[{rounds}$]{salt}[${checksum}]`, such as used by sha1_crypt. :arg ident: identifier prefix (unicode) :arg rounds: rounds field (int or None) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :param rounds_base: base to encode rounds value (defaults to base 10) :returns: config or hash (native str) R<is%xN(RfRRRR(RxRqRkRyRiRoRj((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)!s   cCstS(s assert helper that quickly validates default value. designed to get out of the way and reduce overhead when asserts are stripped. (tTrue(RHRutnormRv((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_default_valueBscCst|ts'tj|d|n||krzd|j|||f}|rkt|tj|}qzt|n|r||krd|j|||f}|rt|tj|}qt|n|S(s helper to normalize and validate an integer value (e.g. rounds, salt_size) :arg value: value provided to constructor :arg default: default value if none provided. if set to ``None``, value is required. :arg param: name of parameter (xxx: move to first arg?) :param min: minimum value (defaults to 1) :param max: maximum value (default ``None`` means no maximum) :returns: validated value tintegers+%s: %s (%d) is too low, must be at least %ds0%s: %s (%d) is too large, cannot be more than %d(RYR#RZtExpectedTypeErrorRFRRt ValueError(RHRrtminRBRvtrelaxedtmsg((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt norm_integerKs    tMinimalHandlercBs&eZdZeZeedZRS(s helper class for implementing hash handlers. provides nothing besides a base implementation of the .using() subclass constructor. cCsD|j}|jsd|}nt||ftd|jdtS(Nst __module__t _configured(R;RttypeRJRRz(tclsRRF((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytusings   (R;Rt__doc__tFalseRt classmethodR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRrst TruncateMixincBs;eZdZeZeZeddZedZ RS(s PasswordHash mixin which provides a method that will check if secret would be truncated, and can be configured to throw an error. .. warning:: Hashers using this mixin will generally need to override the default PasswordHash.truncate_error policy of "True", and will similarly want to override .truncate_verify_reject as well. TODO: This should be done explicitly, but for now this mixin sets these flags implicitly. cKsUtt|j|}|dk rQt|dd}|dk rQ||_qQn|S(NRvttruncate_error(tsuperRRRfRR(RRRLtsubcls((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   cCs4|jr0t||jkr0tj|ndS(s make sure secret won't be truncated. NOTE: this should only be called for .hash(), not for .verify(), which should honor the .truncate_verify_reject policy. N(RR7t truncate_sizeRZtPasswordTruncateError(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_check_truncate_policysN( R;RRRRttruncate_verify_rejectRRfRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cBsseZdZdZdZdZdZdZdZ e Z dZ de dZ e dZedZedZdZedZdZedZed Zed d d d edZed d d d edZeddZddZdZdZedZ e!e"ddZ#ee$e dZ%edZ&RS(s4helper class for implementing hash handlers. GenericHandler-derived classes will have (at least) the following constructor options, though others may be added by mixins and by the class itself: :param checksum: this should contain the digest portion of a parsed hash (mainly provided when the constructor is called by :meth:`from_string()`). defaults to ``None``. :param use_defaults: If ``False`` (the default), a :exc:`TypeError` should be thrown if any settings required by the handler were not explicitly provided. If ``True``, the handler should attempt to provide a default for any missing values. This means generate missing salts, fill in default cost parameters, etc. This is typically only set to ``True`` when the constructor is called by :meth:`hash`, allowing user-provided values to be handled in a more permissive manner. :param relaxed: If ``False`` (the default), a :exc:`ValueError` should be thrown if any settings are out of bounds or otherwise invalid. If ``True``, they should be corrected if possible, and a warning issue. If not possible, only then should an error be raised. (e.g. under ``relaxed=True``, rounds values will be clamped to min/max rounds). This is mainly used when parsing the config strings of certain hashes, whose specifications implementations to be tolerant of incorrect values in salt strings. Class Attributes ================ .. attribute:: ident [optional] If this attribute is filled in, the default :meth:`identify` method will use it as a identifying prefix that can be used to recognize instances of this handler's hash. Filling this out is recommended for speed. This should be a unicode str. .. attribute:: _hash_regex [optional] If this attribute is filled in, the default :meth:`identify` method will use it to recognize instances of the hash. If :attr:`ident` is specified, this will be ignored. This should be a unique regex object. .. attribute:: checksum_size [optional] Specifies the number of characters that should be expected in the checksum string. If omitted, no check will be performed. .. attribute:: checksum_chars [optional] A string listing all the characters allowed in the checksum string. If omitted, no check will be performed. This should be a unicode str. .. attribute:: _stub_checksum Placeholder checksum that will be used by genconfig() in lieu of actually generating a hash for the empty string. This should be a string of the same datatype as :attr:`checksum`. Instance Attributes =================== .. attribute:: checksum The checksum string provided to the constructor (after passing it through :meth:`_norm_checksum`). Required Subclass Methods ========================= The following methods must be provided by handler subclass: .. automethod:: from_string .. automethod:: to_string .. automethod:: _calc_checksum Default Methods =============== The following methods have default implementations that should work for most cases, though they may be overridden if the hash subclass needs to: .. automethod:: _norm_checksum .. automethod:: genconfig .. automethod:: genhash .. automethod:: identify .. automethod:: hash .. automethod:: verify cKsD||_tt|j||dk r@|j||_ndS(N(t use_defaultsRR*t__init__Rft_norm_checksumRy(tselfRyRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRLs  cs|j}|r9t|tstj|ddqn[t|tst|tr||r|tdt|jd}qtj|ddn|j }|rt ||krtj |d|n|s|j rt fd|Drtd|jfqn|S( sovalidates checksum keyword against class requirements, returns normalized version of checksum. R_Rys%checksum should be unicode, not bytesRcRtrawc3s|]}|kVqdS(N((ROtc(tcs(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys tss!invalid characters in %s checksum(t_checksum_is_bytesRYR_RZR~RRRR`t checksum_sizeR7tChecksumSizeErrortchecksum_charstanyRRF(RRyRRtcc((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRUs"    "cCst|}|stS|j}|dk r8|j|S|j}|dk r`|j|dk Sy|j|tSWnt k rtSXdS(N( RbRRxRfRAt _hash_regextmatcht from_stringRzR(RR^Rxtpat((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytidentify|s        cKstd|fdS(sV return parsed instance from hash/configuration string :param \*\*context: context keywords to pass to constructor (if applicable). :raises ValueError: if hash is incorrectly formatted :returns: hash parsed into components, for formatting / calculating checksum. s%s must implement from_string()N(tNotImplementedError(RR^tcontext((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstd|jfdS(srender instance to hash or configuration string :returns: hash string with salt & digest included. should return native string type (ascii-bytes under python 2, unicode under python 3) s%s must implement from_string()N(Rt __class__(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt to_strings cCs|jr;|jrd|jS|jr;|jd|jSnt|tr|j}|jp_d|_z|jdSWd||_Xn|jdS(si placeholder used by default .genconfig() so it can avoid expense of calculating digest. tiiR<N(RRRRYR1Rqt min_roundst_calc_checksum(Rtorig((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_stub_checksums      cCstd|jfdS(sgiven secret; calcuate and return encoded checksum portion of hash string, taking config from object state calc checksum implementations may assume secret is always either unicode or bytes, checks are performed by verify/etc. s"%s must implement _calc_checksum()N(RR(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKs||rDt||}|rDt|||j|j||Snt||dt|}|j||_|jS(NR( RURMRR^R]RzRRyR(RRXRLtsettingsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^s  cKsYt||j||}|j}|dkrCtj|nt|j||S(N(R]RRyRfRZtMissingDigestErrorRR(RRXR^RRRl((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytverifys    t deprecateds1.7tremoveds2.0cKsSt||}|r+|j|j|S|dt|}|j|_|jS(NR(RURt genconfigRzRRyR(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cKsS|dkrtdnt||j||}|j||_|jS(Nsconfig must be string(Rft TypeErrorR]RRRyR(RRXtconfigRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytgenhash s   cKs"|j|}|jd||S(NRX(Rt_calc_needs_update(RR^RXRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt needs_updatescCstS(s; internal helper for :meth:`needs_update`. (R(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR"st salt_sizeRRkRycsfdjDS(Nc3s$|]}|jkr|VqdS(N(t_unparsed_settings(RORP(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys 3s(t setting_kwds(R((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_parsed_settings1st*cCs|dkrdSt|trGddlm}||jd}nt|tset|}nt|}td|d}|| |||S(s*default method to obscure sensitive fieldsi(t ab64_encodeRciiN( RfRYR_tpasslib.utils.binaryRR`RR7R(RrtcharRtsizetclip((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _sanitize7s  csj|ttfdjD}|rbjdk rbj|d]sRyN( RtobjectRJRRyRfRzRt_unsafe_settings(RR^RytsanitizeRLRP((RRRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parsehashEs %   cKszytt|j|}Wntk r5i}nX|jrEtn|j}|jrv|rvt|j||dt k r}t |dkrt dfqnXt dt t|S( s{given secret; calcuate and return encoded checksum portion of hash string, taking config from object state cstdfdS(Ns"%s must implement _calc_checksum()(R(RRX(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytinnerst_wrapperRRc3s$|]}|t|fVqdS(N(R(ROtk(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssconfig must be strings"%s must implement _calc_checksum()s%r should be updated to implement StaticHandler._calc_checksum() instead of StaticHandler.genhash(), support for the latter style will be removed in Passlib 1.8N(Rt_StaticHandler__cc_compat_hackRfRR;RJRRSRRtstrRRRKR (RRXt wrapper_clsRRR^terr((RRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs$    +(N( R;RRRRRRRRRRfRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+{s  tHasEncodingContextcBs&eZdZdZdZddZRS(s?helper for classes which require knowledge of the encoding usedtencodingsutf-8cKs,tt|j||p"|j|_dS(N(RRRtdefault_encodingR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(sencodingN(R;RRRSRRfR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscBskeZdZd Zd dZed dZed dZe dddded d Z RS( s7helper for classes which require a user context keywordtusercKs#tt|j|||_dS(N(RR,RR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKstt|j|d||S(NR(RR,R^(RRXRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^scKs"tt|j||d||S(NR(RR,R(RRXR^RR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRsRs1.7Rs2.0cKs"tt|j||d||S(NR(RR,R(RRXRRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(suserN( R;RRRSRfRRR^RR%R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR,s cBseZdZeZRS(sqmixin for classes which work with decoded checksum bytes .. todo:: document this class's usage (R;RRRzR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR-scBsteZdZdZdZdZdZedddZ ddZ edZ edZ edZ RS(s mixin for hashes which use multiple prefix identifiers For the hashes which may use multiple identifier prefixes, this mixin adds an ``ident`` keyword to constructor. Any value provided is passed through the :meth:`norm_idents` method, which takes care of validating the identifier, as well as allowing aliases for easier specification of the identifiers by the user. .. todo:: document this class's usage Class Methods ============= .. todo:: document using() and needs_update() options cKsv|dk r0|dk r'tdn|}ntt|j|}|dk rr|d|dtj|_n|S(s4 This mixin adds support for the following :meth:`~passlib.ifc.PasswordHash.using` keywords: :param default_ident: default identifier that will be used by resulting customized hasher. :param ident: supported as alternate alias for **default_ident**. s2'default_ident' and 'ident' are mutually exclusiveRxRN(RfRRR.RRzRxt default_ident(RRRxRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR>s    cKsbtt|j||dk r4|j|}n!|jrI|j}n td||_dS(Nsno ident specified( RR.RRft _norm_identRRRRx(RRxRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR\s    cCst|tr!|jd}n|j}||kr:|S|j}|r~y||}Wntk rjq~X||kr~|Sntd|fdS(sD helper which normalizes & validates 'ident' value. Rcsinvalid ident: %rN(RYR_R`t ident_valuest ident_aliasestKeyErrorR(RRxtivtiaRr((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRis     cCst|}|j|jS(N(RbRAR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cCs\t|dd}x4|jD])}|j|r||t|fSqWtj|dS(sDextract ident prefix from hash, helper for subclasses' from_string()RcR^N(R RRAR7RZRd(RR^Rx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _parse_idents N(R;RRRfRRRRxRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR.s   cBseZdZdZdZdZedZedZ e Z dZ dZ eddddZededZddZd Zee d Zed Zed Zedd ZRS(s2 mixin for validating salts. This :class:`GenericHandler` mixin adds a ``salt`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_salt` method, which takes care of validating salt length and content, as well as generating new salts if one it not provided. :param salt: optional salt string :param salt_size: optional size of salt (only used if no salt provided); defaults to :attr:`default_salt_size`. Class Attributes ================ In order for :meth:`!_norm_salt` to do its job, the following attributes should be provided by the handler subclass: .. attribute:: min_salt_size The minimum number of characters allowed in a salt string. An :exc:`ValueError` will be throw if the provided salt is too small. Defaults to ``0``. .. attribute:: max_salt_size The maximum number of characters allowed in a salt string. By default an :exc:`ValueError` will be throw if the provided salt is too large; but if ``relaxed=True``, it will be clipped and a warning issued instead. Defaults to ``None``, for no maximum. .. attribute:: default_salt_size [required] If no salt is provided, this should specify the size of the salt that will be generated by :meth:`_generate_salt`. By default this will fall back to :attr:`max_salt_size`. .. attribute:: salt_chars A string containing all the characters which are allowed in the salt string. An :exc:`ValueError` will be throw if any other characters are encountered. May be set to ``None`` to skip this check (but see in :attr:`default_salt_chars`). .. attribute:: default_salt_chars [required] This attribute controls the set of characters use to generate *new* salt strings. By default, it mirrors :attr:`salt_chars`. If :attr:`!salt_chars` is ``None``, this attribute must be specified in order to generate new salts. Aside from that purpose, the main use of this attribute is for hashes which wish to generate salts from a restricted subset of :attr:`!salt_chars`; such as accepting all characters, but only using a-z. Instance Attributes =================== .. attribute:: salt This instance attribute will be filled in with the salt provided to the constructor (as adapted by :meth:`_norm_salt`) Subclassable Methods ==================== .. automethod:: _norm_salt .. automethod:: _generate_salt icCs|jS(s/default salt size (defaults to *max_salt_size*)(t max_salt_size(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_sizescCs|jS(sDcharset used to generate new salt strings (defaults to *salt_chars*)(t salt_chars(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_charssR9c s|dk r0|dk r'tdn|}ntt|j|}|jd}|dk rt|trt|}n|j |ddd||_ ndk r|j d|t fd|_ n|S(NsB'salt_size' and 'default_salt_size' aliases are mutually exclusiveRRvRcsS(N(((Rk(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt&s(RfRRR/RR@RYRR5t_clip_to_valid_salt_sizeRt _norm_saltRt_generate_salt(RRRRkRLRR((Rks:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s       RcCs|j}|j}||krl||krhd|j|||f}|rYt|tqht|n|S||krd|j|||f}|rt|t|}qt|n|r||krd|j|||f}|rt|t|}qt|n|S(s internal helper -- clip salt size value to handler's absolute limits (min_salt_size / max_salt_size) :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :returns: clipped rounds value s%s: %s (%d) must be exactly %ds$%s: %s (%r) below min_salt_size (%d)s$%s: %s (%r) above max_salt_size (%d)(t min_salt_sizeRRFRRR(RRRvRtmntmxR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+s,         cKsett|j||dk r4|j|}n$|jrL|j}n td||_dS(Nsno salt specified( RR/RRft _parse_saltRRRRk(RRkRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR_s    cCs |j|S(N(R(RRk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRksc s|jr3t|tstj|ddqnt|tst|trots]|ro|jd}qtj|ddn|jd k rt fd|Drt d|j n|j }|r/t||kr/d|j ||jkr dnd ||jf}t |n|j}|rt||krd |j ||krkdnd ||jf}|rt|t|j||}qt |n|S( sThelper to normalize & validate user-provided salt string :arg salt: salt string :raises TypeError: If salt not correct type. :raises ValueError: * if salt contains chars that aren't in :attr:`salt_chars`. * if salt contains less than :attr:`min_salt_size` characters. * if ``relaxed=False`` and salt has more than :attr:`max_salt_size` characters (if ``relaxed=True``, the salt is truncated and a warning is issued instead). :returns: normalized salt R_RkRcRc3s|]}|kVqdS(N((ROR(tsc(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssinvalid characters in %s salts%salt too small (%s requires %s %d %s)texactlys>=s%salt too large (%s requires %s %d %s)s<=N(t_salt_is_bytesRYR_RZR~RR"R`RRfRRRFRR7Rt _salt_unitRRt_truncate_salt(RRkRRRR((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRns0  (  (  % cCs|| S(N((RkR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstt|j|jS(sU helper method for _init_salt(); generates a new random salt string. (RR RR(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKsJtt|j|}|dkr0|j}nt||j|d<|S(s8[experimental method] return info about bitsizes of hashRkN(RR/RRfRR:R(RRRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   N(R;RRRRfRRR$RRRRRRkRRRzRRRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR/s.E3 9cBs/eZdZeZeZdZedZ RS(smixin for classes which use decoded salt parameter A variant of :class:`!HasSalt` which takes in decoded bytes instead of an encoded string. .. todo:: document this class's usage R_cCstt|jS(N(R R R(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs( R;RRRRRzRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR0s c BseZdZdZdZdZdZdZdZ dZ dZ dZ e dddddddd Ze d Ze d Zdd Zd Ze eddZe dZdZe dddZRS(s3mixin for validating rounds parameter This :class:`GenericHandler` mixin adds a ``rounds`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_rounds` method, which takes care of validating the number of rounds. :param rounds: optional number of rounds hash should use Class Attributes ================ In order for :meth:`!_norm_rounds` to do its job, the following attributes must be provided by the handler subclass: .. attribute:: min_rounds The minimum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is too small. Defaults to ``0``. .. attribute:: max_rounds The maximum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is larger than this. Defaults to ``None`` which indicates no limit to the rounds value. .. attribute:: default_rounds If no rounds value is provided to constructor, this value will be used. If this is not specified, a rounds value *must* be specified by the application. .. attribute:: rounds_cost [required] The ``rounds`` parameter typically encodes a cpu-time cost for calculating a hash. This should be set to ``"linear"`` (the default) or ``"log2"``, depending on how the rounds value relates to the actual amount of time that will be required. Class Methods ============= .. todo:: document using() and needs_update() options Instance Attributes =================== .. attribute:: rounds This instance attribute will be filled in with the rounds value provided to the constructor (as adapted by :meth:`_norm_rounds`) Subclassable Methods ==================== .. automethod:: _norm_rounds itlineartmin_desired_roundstmax_desired_roundsRt max_roundsRpt vary_roundsc Ks|dk r0|dk r'tdn|}n|dk r`|dk rWtdn|}n|dk r|dkr|}n|dkr|}n|dkr|}qntt|j|} |jd} |dkrt} |j}nBt} t |t rt |}n| j |ddd| | _|dkrM|j }nt |t rkt |}n|r||krd| j||f} | rt| qt| t|}n| j |ddd| | _ |dk rt |t rt |}n|r7||kr7td| j||fn1|rh||krhtd | j||fn| j |dd d| | _n| jdk r| j| j| _n|dk rt |t r|jd rt|d d }qd|kr t|}qt |}n|dkrCtd| j|fnXt |tr}|dkrtd| j|fqnt |t stdn|rtdtn|| _n| S(NsD'min_rounds' and 'min_desired_rounds' aliases are mutually exclusivesD'max_rounds' and 'max_desired_rounds' aliases are mutually exclusiveRRvRs9%s: max_desired_rounds (%r) below min_desired_rounds (%r)Rs5%s: default_rounds (%r) below min_desired_rounds (%r)s5%s: default_rounds (%r) above max_desired_rounds (%r)Rpt%ig{Gz?t.is%s: vary_rounds (%r) below 0is%s: vary_rounds (%r) above 1.0s vary_rounds must be int or floats\The 'vary_rounds' option is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0(RfRRR1RR@RRRzRYRR5t _norm_roundsRRFRRRRpt_clip_to_desired_roundstendswithtfloatR( RRRRpRRRRqRLRRtexplicit_min_roundsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR6s                               cCsB|jp d}||kr|S|j}|r>||kr>|S|S(s| helper for :meth:`_generate_rounds` -- clips rounds value to desired min/max set by class (if any) i(RR(RRqtmndtmxd((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cCs|j}d}t|trY|jdkrFd|>}d}nt||}n|||t}|||t}|j||j|fS(s helper for :meth:`_generate_rounds` -- returns range for vary rounds generation. :returns: (lower, upper) limits suitable for random.randint() cSs|S(N((Rrtupper((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytlinear_to_nativestlog2icSsO|dkrdS|r,ttj|dSttjtj|dSdS(Nii(R5R4R6tceil(RrR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  (RRYRt rounds_costR5RRzR(RRpRRtlowerR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_calc_vary_rounds_ranges    cKsett|j||dk r4|j|}n$|jrL|j}n td||_dS(Nsno rounds specified( RR1RRft _parse_roundsRt_generate_roundsRRq(RRqRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs    cCs |j|S(N(R(RRq((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR sRqc Cs%t|||j|jd|d|S(s helper for normalizing rounds value. :arg rounds: an integer cost parameter. :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :raises TypeError: * if ``use_defaults=False`` and no rounds is specified * if rounds is not an integer. :raises ValueError: * if rounds is ``None`` and class does not specify a value for :attr:`default_rounds`. * if ``relaxed=False`` and rounds is outside bounds of :attr:`min_rounds` and :attr:`max_rounds` (if ``relaxed=True``, the rounds value will be clamped, and a warning issued). :returns: normalized rounds value RvR(RRR(RRqRRv((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCst|j}|dkr.td|jfn|jrp|j|\}}||krptj||}qpn|S(s internal helper for :meth:`_norm_rounds` -- returns default rounds value, incorporating vary_rounds, and any other limitations hash may place on rounds parameter. s,%s rounds value must be specified explicitlyN(RpRfRRFRR R trandint(RRqR R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s    cKsZ|j}|r"|j|kr"tS|j}|rD|j|krDtStt|j|S(sR mark hash as needing update if rounds is outside desired bounds. (RRqRzRRR1R(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)s  g?cKstt|j|}|jdkr{ddl}|dkrK|j}ntdtd|j ||d|d` handlers; such as :class:`~passlib.hash.ldap_md5_crypt` which wraps :class:`~passlib.hash.md5_crypt` and adds a ``{CRYPT}`` prefix. usage:: myhandler = PrefixWrapper("myhandler", "md5_crypt", prefix="$mh$", orig_prefix="$1$") :param name: name to assign to handler :param wrapped: handler object or name of registered handler :param prefix: identifying prefix to prepend to all hashes :param orig_prefix: prefix to strip (defaults to ''). :param lazy: if True and wrapped handler is specified by name, don't look it up until needed. R<cCs@||_t|tr*|jd}n||_t|trT|jd}n||_|ro||_nt|dr|j|n||_ |s|j n|dk r<|t kr|r|}qt dnt|tr|jd}n|t| |t| kr0t dn||_ndS(NRcRFsno prefix specifiedsident must agree with prefix(RFRYR_R`Rht orig_prefixRthasattrt _set_wrappedt _wrapped_namet _get_wrappedRfRzRR7t_ident(RRFtwrappedRhRAtlazytdocRx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s0          cCsBd|jkr5|jr5td|jftjn||_dS(NRxskPrefixWrapper: 'orig_prefix' option may not work correctly for handlers which have multiple identifiers: %r(RRARRFRZtPasslibRuntimeWarningt_wrapped_handler(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRC scCs8|j}|dkr4t|j}|j|n|S(N(RKRfRRDRC(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRE s   cCsp|j}|tkrld}|js`|j}t|dd}|dk r`|j|}q`n||_n|S(NRx(RFRRfRARGRt _wrap_hash(RRrRGRx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRx s      cswj}|tkrsd}jsgj}t|dd}|rgtfd|D}qgn|_n|S(NRc3s|]}j|VqdS(N(RL(RORx(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys s(t _ident_valuesRRfRARGRttuple(RRrRGtidents((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s    " RRSRpRRR RRRRRRRRRRRRt is_disabledRRRRcCs{t|jp|jg}|jr;|jd|jn|jr[|jd|jndj|}d|j|fS(Ns prefix=%rsorig_prefix=%rs, sPrefixWrapper(%r, %s)(treprRDRKRhR/RAtjoinRF(Rtargs((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__repr__ s  csXtt|j}|j|j|j|jfd|jDt|S(Nc3s$|]}t|r|VqdS(N(RB(ROtattr(RG(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys  s(RRtdirRtupdateR,RGt _proxy_attrsRT(Rtattrs((RGs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__dir__ s  cCs6||jkrt|j|Std|fdS(sFproxy most attributes from wrapped class (e.g. rounds, salt size, etc)smissing attribute: %rN(RXRRGR(RRU((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt __getattr__ scCsZ||jkrG|jrG|j}t||rGt|||dSntj|||S(N(RXt _derived_fromRGRBtsetattrRt __setattr__(RRURrRG((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^ s  cCs?|j}|j|s*tj|n|j|t|S(s4given hash belonging to wrapper, return orig version(RhRARZRdRAR7(RR^Rh((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _unwrap_hash+ s cCsot|tr!|jd}n|j}|j|sNtj|jn|j|t |}t |S(s0given orig hash; return one belonging to wrapperRc( RYR_R`RARARZRdRGRhR7R(RR^RARG((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRL4 s cKsp|jj|}t|j|d|jd|j}||_x*|jD]}t||t ||qIW|S(NRhRA( RGRR3RFRhRAR\t_using_clone_attrsR]R(RRLRtwrapperRU((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRC s $ cKs"|j|}|jj||S(N(R_RGR(RR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRN scCsAt|}|j|js"tS|j|}|jj|S(N(RbRARhRR_RGR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRR s  Rs1.7Rs2.0cKs:|jj|}|dkr-tdn|j|S(Ns+.genconfig() must return a string, not None(RGRRfR?RL(RRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRY s cKsO|dk r0t|dd}|j|}n|j|jj|||S(NRcs config/hash(RfR R_RLRGR(RRXRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR` s t replacements.hash()cKs|j||S(N(R^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytencrypth scKs|j|jj||S(N(RLRGR^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^l scKs7t|dd}|j|}|jj|||S(NRcR^(R R_RGR(RRXR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRo s(N(s setting_kwdss context_kwdssdefault_roundss min_roundss max_roundss rounds_costsmin_desired_roundssmax_desired_roundss vary_roundssdefault_salt_sizes min_salt_sizes max_salt_sizes salt_charssdefault_salt_charssbackendss has_backends get_backends set_backendRPs truncate_sizestruncate_errorstruncate_verify_rejects_salt_is_bytes(#R;RRR`RRRfRRDRKRCRERRGRFRxRMRRXRTRZR[R^R_RLR\RRRR%RRRcR^R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR3 sJ      $ (cRt __future__RR=tloggingt getLoggerR;R6R4t threadingtwarningsRt passlib.excRZt passlib.ifctifcRRRRtpasslib.registryRt passlib.utilsRRR R R R R RRRRRRRRRRRRtpasslib.utils.compatRRRRRRRR R!R"R#tpasslib.utils.decorR$R%t__all__t H64_CHARSt B64_CHARStPADDED_B64_CHARSt UC_HEX_CHARSt LC_HEX_CHARSR:RGRMRUt_UDOLLARRmR]RbRfR&R'RwR(R)R|RRRRR*R+RR,R-R.R/R0R1RtRLockRRR)R2RR3(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyts    L4R        J! &!*Z '&xH N|md4.pyo000064400000001426147221702050005764 0ustar00 5Xc@sRdZddlmZededgZddlmZedjZ[dS(s passlib.utils.md4 - DEPRECATED MODULE, WILL BE REMOVED IN 2.0 MD4 should now be looked up through ``passlib.crypto.digest.lookup_hash("md4").const``, which provides unified handling stdlib implementation (if present). i(twarnsthe module 'passlib.utils.md4' is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0, please use 'lookup_hash("md4").const()' from 'passlib.crypto' insteadtmd4(t lookup_hashN( t__doc__twarningsRtDeprecationWarningt__all__tpasslib.crypto.digestRtconstR(((s5/usr/lib/python2.7/site-packages/passlib/utils/md4.pyts binary.pyc000064400000060232147221702050006550 0ustar00 5Xc@`sdZddlmZmZmZddlmZmZmZ m Z ddl m Z mZmZddlZejeZddlmZddlmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#ddl$m%Z%d d d d d ddddddddddddddddgZ&e!dZ'e!dZ(e!d Z)e!d!Z*e'e!d"Z+e!d#Z,e!d$Z-e!d%Z.eed&Z/d'Z0d(Z1d"Z2e3ee/Z4e5d)Z6d*Z7d+Z8d,Z9d"Z:d-Z;d.Z<d/Z=d0Z e6id1d26d3d46Z>e2d5Z?d6Zde@fd7YZAdeAfd8YZBeBe)ZCeBe)d9eDZEeBe*d9eDZFdS(:sC passlib.utils.binary - binary data encoding/decoding/manipulation i(tabsolute_importtdivisiontprint_function(t b64encodet b64decodet b32decodet b32encode(t b2a_base64t a2b_base64tErrorN(texc( tPY3t bascii_to_strtirangetimaptiter_byte_charstjoin_byte_valuestjoin_byte_elemst nextgettertsuppress_causetutunicodetunicode_or_bytes_types(tmemoized_propertyt BASE64_CHARStPADDED_BASE64_CHARSt AB64_CHARSt HASH64_CHARSt BCRYPT_CHARSt HEX_CHARStLOWER_HEX_CHARStUPPER_HEX_CHARStALL_BYTE_VALUEStcompile_byte_translationt ab64_encodet ab64_decodet b64s_encodet b64s_decodeRRt Base64EnginetLazyBase64Engineth64th64bigtbcrypt64s@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/s@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./s@./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzs@./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789t=t0123456789abcdefABCDEFt0123456789ABCDEFt0123456789abcdefittcC`s|dkrt}n9t|tr7t|dks=ttt|}x|jD]\}}t|t rt |}nt|t rd|kodknstt|t r|j d}nt|trt|dkst||| output byte (str or int). :param source: optional existing byte translation string to use as base. (must be 255-length byte string). defaults to identity mapping. :returns: 255-length byte string for passing to bytes().translate. iiitasciiiN(tNonet_TRANSLATE_SOURCEt isinstancetbytestlentAssertionErrortlistRtitemsRtordtintRtencodetB_EMPTYtjoin(tmappingtsourcettargettktv((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR!ns  '1'cC`st|jtS(sr encode using shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. (Rtrstript _BASE64_STRIP(tdata((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR$scC`st|trKy|jd}WqKtk rGttdqKXnt|d@}|dkrjn>|dkr|t7}n%|dkr|t7}n tdyt |SWn%t k r}tt |nXdS(sq decode from shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. R1s4string argument should contain only ASCII charactersiiisinvalid base64 inputN( R4RR<tUnicodeEncodeErrorRt ValueErrorR6t _BASE64_PAD2t _BASE64_PAD1Rt_BinAsciiErrort TypeError(RFtoffterr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR%s"       s= s==cC`st|jddS(s encode using shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars. it is primarily used by Passlib's custom pbkdf2 hashes. t+t.(R$treplace(RF((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR"scC`sat|trKy|jd}WqKtk rGttdqKXnt|jddS(s decode from shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars, but supports decoding normal ``+/`` altchars as well. it is primarily used by Passlib's custom pbkdf2 hashes. R1s4string argument should contain only ASCII charactersRPRO(R4RR<RGRRHR%RQ(RF((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR#s  cC`stt|jtS(sh wrapper around :func:`base64.b32encode` which strips padding, and returns a native string. (R t _b32encodeRDtB_EQUAL(R@((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRstBt8tOt0icC`set|tr!|jd}n|jt}t|d@}|rX|t| 7}nt|tS(s wrapper around :func:`base64.b32decode` which handles common mistyped chars. padding optional, ignored if present. R1i( R4RR<t translatet_b32_translateR6t_b32_decode_padt _b32decodetTrue(R@t remainder((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRscB`s:eZdZdZdZdZdZdZdZ e dZ e dZ dZdZdZdZdZdZd Zed Zed Zd Zd ZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'RS(scProvides routines for encoding/decoding base64 data using arbitrary character mappings, selectable endianness, etc. :arg charmap: A string of 64 unique characters, which will be used to encode successive 6-bit chunks of data. A character's position within the string should correspond to its 6-bit value. :param big: Whether the encoding should be big-endian (default False). .. note:: This class does not currently handle base64's padding characters in any way what so ever. Raw Bytes <-> Encoded Bytes =========================== The following methods convert between raw bytes, and strings encoded using the engine's specific base64 variant: .. automethod:: encode_bytes .. automethod:: decode_bytes .. automethod:: encode_transposed_bytes .. automethod:: decode_transposed_bytes .. .. automethod:: check_repair_unused .. automethod:: repair_unused Integers <-> Encoded Bytes ========================== The following methods allow encoding and decoding unsigned integers to and from the engine's specific base64 variant. Endianess is determined by the engine's ``big`` constructor keyword. .. automethod:: encode_int6 .. automethod:: decode_int6 .. automethod:: encode_int12 .. automethod:: decode_int12 .. automethod:: encode_int24 .. automethod:: decode_int24 .. automethod:: encode_int64 .. automethod:: decode_int64 Informational Attributes ======================== .. attribute:: charmap unicode string containing list of characters used in encoding; position in string matches 6bit value of character. .. attribute:: bytemap bytes version of :attr:`charmap` .. attribute:: big boolean flag indicating this using big-endian encoding. cC`st|tr!|jd}n$t|tsEtj|dnt|dkrftdntt|dkrtdn||_ |j |_ t dt |D}|j |_||_|r|j|_|j|_n|j|_|j|_dS(Nslatin-1tcharmapi@s'charmap must be 64 characters in lengths-charmap must not contain duplicate characterscs`s!|]\}}||fVqdS(N((t.0tidxtvalue((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys ]s(R4RR<R5R tExpectedStringErrorR6RHtsettbytemapt __getitem__t _encode64tdictt enumeratet _decode64tbigt_encode_bytes_bigt _encode_bytest_decode_bytes_bigt _decode_bytest_encode_bytes_littlet_decode_bytes_little(tselfR^Rjtlookup((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt__init__Qs$      cC`s|jjdS(scharmap as unicodeslatin-1(Rdtdecode(Rq((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR^sscC`st|ts+tdt|fntt|d\}}tratt|}ntd|D}|j |||}t t |j |}|S(sencode bytes to base64 string. :arg source: byte string to encode. :returns: byte string containing encoded data. ssource must be bytes, not %sics`s|]}t|VqdS(N(R:(R_telem((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys s( R4R5RLttypetdivmodR6R RtiterRlRRRf(RqR@tchunksttailt next_valuetgentout((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_bytes{scc`sd}xq||kry|}|}|}|d@V|d@d>|d?BV|d@d>|d?BV|d?V|d7}q W|r|}|dkr|d@V|d?Vq|dkst|}|d@V|d@d>|d?BV|d?Vnd S( s>helper used by encode_bytes() to handle little-endian encodingii?iiiiiiN(R7(RqR{RyRzR`tv1tv2tv3((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRos(           cc`sd}xq||kry|}|}|}|d?V|d@d>|d?BV|d@d>|d?BV|d@V|d7}q W|r|}|dkr|d?V|d@d>Vq|dkst|}|d?V|d@d>|d?BV|d@d>Vnd S( s;helper used by encode_bytes() to handle big-endian encodingiiiiiii?iN(R7(RqR{RyRzR`RRR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRks(          cC`st|ts+tdt|fntt|d\}}|dkratdntt|j |}yt |j |||SWn-t k r}td|j dfnXdS(sdecode bytes from base64 string. :arg source: byte string to decode. :returns: byte string containing decoded data. ssource must be bytes, not %siis(input string length cannot be == 1 mod 4sinvalid character: %riN(R4R5RLRvRwR6RHRRRiRRntKeyErrortargs(RqR@RyRzR{RN((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_bytess c c`sd}xu||kr}|}|}|}|}||d@d>BV|d?|d@d>BV|d?|d>BV|d7}q W|r|}|}||d@d>BV|dkr|}|d?|d@d>BVqndS( s>helper used by decode_bytes() to handle little-endian encodingiiiiiiiN(( RqR{RyRzR`RRRtv4((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRps"        c c`sd}xu||kr}|}|}|}|}|d>|d?BV|d@d>|d?BV|d@d>|BV|d7}q W|r|}|}|d>|d?BV|dkr|}|d@d>|d?BVqndS( s;helper used by decode_bytes() to handle big-endian encodingiiiiiiiN(( RqR{RyRzR`RRRR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRms"        c`sUtfdt|jD}|jfdt|jDt|S(s2helper to generate set of valid last chars & bytesc3`s%|]\}}|@s|VqdS(N((R_titc(tbits(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys Gsc3`s%|]\}}|@s|VqdS(N((R_RR(R(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys Hs(RcRhRdtupdateR^t frozenset(RqRtpset((Rs8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt __make_padsetEs%&cC`s)|jrdnd}||j|fS(sDmask to clear padding bits, and valid last bytes (for strings 2 % 4)iii<(Rjt_Base64Engine__make_padset(RqR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _padinfo2KscC`s)|jrdnd}||j|fS(sDmask to clear padding bits, and valid last bytes (for strings 3 % 4)iii0(RjR(RqR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _padinfo3RscC`s0t|d@}|dkr.|j\}}n:|dkrL|j\}}n|s\t|fStd|d}||krt|fSt|tr|j}||j||@}||kst dnL|j |j ||@}||kst dt rt |g}nt|d |fS(shelper to detect & clear invalid unused bits in last character. :arg source: encoded data (as ascii bytes or unicode). :returns: `(True, result)` if the string was repaired, `(False, source)` if the string was ok as-is. iissource length must != 1 mod 4is%failed to generate valid padding char(R6RRtFalseRHR4RR^tindexR7RfRiR R5R\(RqR@Rztmasktpadsettlasttcm((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytcheck_repair_unusedYs(         cC`s|j|dS(Ni(R(RqR@((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt repair_unusedsc`sTtts+tdtfntfd|D}|j|S(s>encode byte string, first transposing source using offset listssource must be bytes, not %sc3`s|]}|VqdS(N((R_RM(R@(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys s(R4R5RLRvRR~(RqR@toffsetsttmp((R@s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytencode_transposed_bytesscC`sV|j|}dgt|}x't||D]\}}|||||}qWWn$t k rtd|fnX|r|r||L}q|d|>dM}n|S(sdecode base64 string -> integer :arg source: base64 string to decode. :arg bits: number of bits in resulting integer. :raises ValueError: * if the string contains invalid base64 characters. * if the string is not long enough - it must be at least ``int(ceil(bits/6))`` in length. :returns: a integer in the range ``0 <= n < 2**bits`` ssource must be bytes, not %sissource must be %d charsisinvalid character in string: %ri( R4R5RLRvRjR6RHRitreversedR( RqR@RRjtpadtcharsRtR}R((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _decode_ints&     cC`st|ts+tdt|fnt|dkrLtdntr_|d}ny|j|SWntk rtdnXdS(s(decode single character -> 6 bit integerssource must be bytes, not %sissource must be exactly 1 byteisinvalid characterN( R4R5RLRvR6RHR RiR(RqR@((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int6s  cC`st|ts+tdt|fnt|dkrLtdn|j}yM|jr||d||dd>S||d||dd>SWntk rtdnXdS( s'decodes 2 char string -> 12-bit integerssource must be bytes, not %sissource must be exactly 2 bytesiiisinvalid characterN( R4R5RLRvR6RHRiRjR(RqR@Rt((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int12s   $ cC`st|ts+tdt|fnt|dkrLtdn|j}y|jr||d||dd>||dd>||d d >S||d ||dd>||dd>||dd >SWntk r td nXd S( s'decodes 4 char string -> 24-bit integerssource must be bytes, not %sissource must be exactly 4 bytesiiiii iisinvalid characterN( R4R5RLRvR6RHRiRjR(RqR@Rt((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int24s  DH cC`s|j|dS(s&decode 5 char string -> 30 bit integeri(R(RqR@((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int30scC`s|j|dS(sdecode 11 char base64 string -> 64-bit integer this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. i@(R(RqR@((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt decode_int64sc`sdkstd| d}||7}|jrYt|ddd}|Kntd|d}tt|jfd|DS(sencode integer into base64 format :arg value: non-negative integer to encode :arg bits: number of bits to encode :returns: a string of length ``int(ceil(bits/6.0))``. iscaller did not sanitize inputiic3`s|]}|?d@VqdS(i?N((R_RM(Ra(s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pys "s(R7RjR RRRf(RqRaRRtitr((Ras8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _encode_ints      cC`sP|dks|dkr'tdntr?|j||d!S|j|SdS(s0encodes 6-bit integer -> single hash64 characterii?svalue out of rangeiN(RHR RdRf(RqRa((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int6(s cC`sm|dks|dkr'tdn|d@|d?d@g}|jrWt|}ntt|j|S(s'encodes 12-bit integer -> 2 char stringiisvalue out of rangei?i(RHRjRRRRf(RqRatraw((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int121s  cC`s|dks|dkr'tdn|d@|d?d@|d?d@|d?d@g}|jrmt|}ntt|j|S(s'encodes 24-bit integer -> 4 char stringiisvalue out of rangei?ii i(RHRjRRRRf(RqRaR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int24:s cC`s7|dks|dkr'tdn|j|dS(s&decode 5 char string -> 30 bit integerii?svalue out of rangei(RHR(RqRa((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int30DscC`s7|dks|dkr'tdn|j|dS(sencode 64-bit integer -> 11 char hash64 string this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. ilsvalue out of rangei@(RHR(RqRa((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt encode_int64JsN((t__name__t __module__t__doc__R2RdRjRfRiRlRnRRstpropertyR^R~RoRkRRpRmRRRRRRRRRRRRRRRRRRRR(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR&sD? "  ' +  # *  )    (      cB`s/eZdZdZdZdZdZRS(s<Base64Engine which delays initialization until it's accessedcO`s||f|_dS(N(t _lazy_opts(RqRtkwds((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRs\scC`s;|j\}}tt|j|||`t|_dS(N(RtsuperR'RsR&t __class__(RqRR((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyt _lazy_init_scC`s,|jds|jntj||S(Nt_(t startswithRtobjectt__getattribute__(Rqtattr((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyRes N(RRRR2RRsRR(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pyR'Xs   Rj(GRt __future__RRRtbase64RRRR[RRRtbinasciiRRR RKtloggingt getLoggerRtlogtpasslibR tpasslib.utils.compatR R R RRRRRRRRRtpasslib.utils.decorRt__all__RRRRRRRRR R=tB_NULLRSR8R3R2R!R$R%RERJRIR"R#RYRZRR&R'R(R\R)R*(((s8/usr/lib/python2.7/site-packages/passlib/utils/binary.pytsn" R         !      ] md4.pyc000064400000001426147221702050005750 0ustar00 5Xc@sRdZddlmZededgZddlmZedjZ[dS(s passlib.utils.md4 - DEPRECATED MODULE, WILL BE REMOVED IN 2.0 MD4 should now be looked up through ``passlib.crypto.digest.lookup_hash("md4").const``, which provides unified handling stdlib implementation (if present). i(twarnsthe module 'passlib.utils.md4' is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0, please use 'lookup_hash("md4").const()' from 'passlib.crypto' insteadtmd4(t lookup_hashN( t__doc__twarningsRtDeprecationWarningt__all__tpasslib.crypto.digestRtconstR(((s5/usr/lib/python2.7/site-packages/passlib/utils/md4.pyts compat/__init__.py000064400000032217147221702050010145 0ustar00"""passlib.utils.compat - python 2/3 compatibility helpers""" #============================================================================= # figure out what we're running #============================================================================= #------------------------------------------------------------------------ # python version #------------------------------------------------------------------------ import sys PY2 = sys.version_info < (3,0) PY3 = sys.version_info >= (3,0) # make sure it's not an unsupported version, even if we somehow got this far if sys.version_info < (2,6) or (3,0) <= sys.version_info < (3,2): raise RuntimeError("Passlib requires Python 2.6, 2.7, or >= 3.2 (as of passlib 1.7)") PY26 = sys.version_info < (2,7) #------------------------------------------------------------------------ # python implementation #------------------------------------------------------------------------ JYTHON = sys.platform.startswith('java') PYPY = hasattr(sys, "pypy_version_info") if PYPY and sys.pypy_version_info < (2,0): raise RuntimeError("passlib requires pypy >= 2.0 (as of passlib 1.7)") # e.g. '2.7.7\n[Pyston 0.5.1]' PYSTON = "Pyston" in sys.version #============================================================================= # common imports #============================================================================= import logging; log = logging.getLogger(__name__) if PY3: import builtins else: import __builtin__ as builtins def add_doc(obj, doc): """add docstring to an object""" obj.__doc__ = doc #============================================================================= # the default exported vars #============================================================================= __all__ = [ # python versions 'PY2', 'PY3', 'PY26', # io 'BytesIO', 'StringIO', 'NativeStringIO', 'SafeConfigParser', 'print_', # type detection ## 'is_mapping', 'int_types', 'num_types', 'unicode_or_bytes_types', 'native_string_types', # unicode/bytes types & helpers 'u', 'unicode', 'uascii_to_str', 'bascii_to_str', 'str_to_uascii', 'str_to_bascii', 'join_unicode', 'join_bytes', 'join_byte_values', 'join_byte_elems', 'byte_elem_value', 'iter_byte_values', # iteration helpers 'irange', #'lrange', 'imap', 'lmap', 'iteritems', 'itervalues', 'next', # collections 'OrderedDict', # introspection 'get_method_function', 'add_doc', ] # begin accumulating mapping of lazy-loaded attrs, # 'merged' into module at bottom _lazy_attrs = dict() #============================================================================= # unicode & bytes types #============================================================================= if PY3: unicode = str # TODO: once we drop python 3.2 support, can use u'' again! def u(s): assert isinstance(s, str) return s unicode_or_bytes_types = (str, bytes) native_string_types = (unicode,) else: unicode = builtins.unicode def u(s): assert isinstance(s, str) return s.decode("unicode_escape") unicode_or_bytes_types = (basestring,) native_string_types = (basestring,) # shorter preferred aliases unicode_or_bytes = unicode_or_bytes_types unicode_or_str = native_string_types # unicode -- unicode type, regardless of python version # bytes -- bytes type, regardless of python version # unicode_or_bytes_types -- types that text can occur in, whether encoded or not # native_string_types -- types that native python strings (dict keys etc) can occur in. #============================================================================= # unicode & bytes helpers #============================================================================= # function to join list of unicode strings join_unicode = u('').join # function to join list of byte strings join_bytes = b''.join if PY3: def uascii_to_str(s): assert isinstance(s, unicode) return s def bascii_to_str(s): assert isinstance(s, bytes) return s.decode("ascii") def str_to_uascii(s): assert isinstance(s, str) return s def str_to_bascii(s): assert isinstance(s, str) return s.encode("ascii") join_byte_values = join_byte_elems = bytes def byte_elem_value(elem): assert isinstance(elem, int) return elem def iter_byte_values(s): assert isinstance(s, bytes) return s def iter_byte_chars(s): assert isinstance(s, bytes) # FIXME: there has to be a better way to do this return (bytes([c]) for c in s) else: def uascii_to_str(s): assert isinstance(s, unicode) return s.encode("ascii") def bascii_to_str(s): assert isinstance(s, bytes) return s def str_to_uascii(s): assert isinstance(s, str) return s.decode("ascii") def str_to_bascii(s): assert isinstance(s, str) return s def join_byte_values(values): return join_bytes(chr(v) for v in values) join_byte_elems = join_bytes byte_elem_value = ord def iter_byte_values(s): assert isinstance(s, bytes) return (ord(c) for c in s) def iter_byte_chars(s): assert isinstance(s, bytes) return s add_doc(uascii_to_str, "helper to convert ascii unicode -> native str") add_doc(bascii_to_str, "helper to convert ascii bytes -> native str") add_doc(str_to_uascii, "helper to convert ascii native str -> unicode") add_doc(str_to_bascii, "helper to convert ascii native str -> bytes") # join_byte_values -- function to convert list of ordinal integers to byte string. # join_byte_elems -- function to convert list of byte elements to byte string; # i.e. what's returned by ``b('a')[0]``... # this is b('a') under PY2, but 97 under PY3. # byte_elem_value -- function to convert byte element to integer -- a noop under PY3 add_doc(iter_byte_values, "iterate over byte string as sequence of ints 0-255") add_doc(iter_byte_chars, "iterate over byte string as sequence of 1-byte strings") #============================================================================= # numeric #============================================================================= if PY3: int_types = (int,) num_types = (int, float) else: int_types = (int, long) num_types = (int, long, float) #============================================================================= # iteration helpers # # irange - range iterable / view (xrange under py2, range under py3) # lrange - range list (range under py2, list(range()) under py3) # # imap - map to iterator # lmap - map to list #============================================================================= if PY3: irange = range ##def lrange(*a,**k): ## return list(range(*a,**k)) def lmap(*a, **k): return list(map(*a,**k)) imap = map def iteritems(d): return d.items() def itervalues(d): return d.values() def nextgetter(obj): return obj.__next__ izip = zip else: irange = xrange ##lrange = range lmap = map from itertools import imap, izip def iteritems(d): return d.iteritems() def itervalues(d): return d.itervalues() def nextgetter(obj): return obj.next add_doc(nextgetter, "return function that yields successive values from iterable") #============================================================================= # typing #============================================================================= ##def is_mapping(obj): ## # non-exhaustive check, enough to distinguish from lists, etc ## return hasattr(obj, "items") #============================================================================= # introspection #============================================================================= if PY3: method_function_attr = "__func__" else: method_function_attr = "im_func" def get_method_function(func): """given (potential) method, return underlying function""" return getattr(func, method_function_attr, func) def get_unbound_method_function(func): """given unbound method, return underlying function""" return func if PY3 else func.__func__ def suppress_cause(exc): """ backward compat hack to suppress exception cause in python3.3+ one python < 3.3 support is dropped, can replace all uses with "raise exc from None" """ exc.__cause__ = None return exc #============================================================================= # input/output #============================================================================= if PY3: _lazy_attrs = dict( BytesIO="io.BytesIO", UnicodeIO="io.StringIO", NativeStringIO="io.StringIO", SafeConfigParser="configparser.ConfigParser", ) print_ = getattr(builtins, "print") else: _lazy_attrs = dict( BytesIO="cStringIO.StringIO", UnicodeIO="StringIO.StringIO", NativeStringIO="cStringIO.StringIO", SafeConfigParser="ConfigParser.SafeConfigParser", ) def print_(*args, **kwds): """The new-style print function.""" # extract kwd args fp = kwds.pop("file", sys.stdout) sep = kwds.pop("sep", None) end = kwds.pop("end", None) if kwds: raise TypeError("invalid keyword arguments") # short-circuit if no target if fp is None: return # use unicode or bytes ? want_unicode = isinstance(sep, unicode) or isinstance(end, unicode) or \ any(isinstance(arg, unicode) for arg in args) # pick default end sequence if end is None: end = u("\n") if want_unicode else "\n" elif not isinstance(end, unicode_or_bytes_types): raise TypeError("end must be None or a string") # pick default separator if sep is None: sep = u(" ") if want_unicode else " " elif not isinstance(sep, unicode_or_bytes_types): raise TypeError("sep must be None or a string") # write to buffer first = True write = fp.write for arg in args: if first: first = False else: write(sep) if not isinstance(arg, basestring): arg = str(arg) write(arg) write(end) #============================================================================= # collections #============================================================================= if PY26: _lazy_attrs['OrderedDict'] = 'passlib.utils.compat._ordered_dict.OrderedDict' else: _lazy_attrs['OrderedDict'] = 'collections.OrderedDict' #============================================================================= # lazy overlay module #============================================================================= from types import ModuleType def _import_object(source): """helper to import object from module; accept format `path.to.object`""" modname, modattr = source.rsplit(".",1) mod = __import__(modname, fromlist=[modattr], level=0) return getattr(mod, modattr) class _LazyOverlayModule(ModuleType): """proxy module which overlays original module, and lazily imports specified attributes. this is mainly used to prevent importing of resources that are only needed by certain password hashes, yet allow them to be imported from a single location. used by :mod:`passlib.utils`, :mod:`passlib.crypto`, and :mod:`passlib.utils.compat`. """ @classmethod def replace_module(cls, name, attrmap): orig = sys.modules[name] self = cls(name, attrmap, orig) sys.modules[name] = self return self def __init__(self, name, attrmap, proxy=None): ModuleType.__init__(self, name) self.__attrmap = attrmap self.__proxy = proxy self.__log = logging.getLogger(name) def __getattr__(self, attr): proxy = self.__proxy if proxy and hasattr(proxy, attr): return getattr(proxy, attr) attrmap = self.__attrmap if attr in attrmap: source = attrmap[attr] if callable(source): value = source() else: value = _import_object(source) setattr(self, attr, value) self.__log.debug("loaded lazy attr %r: %r", attr, value) return value raise AttributeError("'module' object has no attribute '%s'" % (attr,)) def __repr__(self): proxy = self.__proxy if proxy: return repr(proxy) else: return ModuleType.__repr__(self) def __dir__(self): attrs = set(dir(self.__class__)) attrs.update(self.__dict__) attrs.update(self.__attrmap) proxy = self.__proxy if proxy is not None: attrs.update(dir(proxy)) return list(attrs) # replace this module with overlay that will lazily import attributes. _LazyOverlayModule.replace_module(__name__, _lazy_attrs) #============================================================================= # eof #============================================================================= compat/__init__.pyc000064400000032243147221702050010307 0ustar00 5Xc$@sdZddlZejdckZejddkZejdeks^dfejkoYdgknrmednejdhkZejjd Z e ed Z e rej dikred nd ej kZddlZejeZerddlZn ddlZd Zddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.g!ZeZereZd/ZeefZefZn$ejZd0ZefZefZeZ eZ!ed1j"Z#d1j"Z$erNd2Z%d3Z&d4Z'd5Z(eZ)Z*d6Z+d7Z,d8Z-nKd9Z%d:Z&d;Z'd<Z(d=Z)e$Z*e.Z+d>Z,d?Z-ee%d@ee&dAee'dBee(dCee,dDee-dEere/fZ0e/e1fZ2ne/e3fZ0e/e3e1fZ2er_e4Z5dFZ6e7Z8dGZ9dHZ:dIZ;e<Z=n=e>Z5e7Z6ddJl?m8Z8m=Z=dKZ9dLZ:dMZ;ee;dNerdOZ@ndPZ@dQZAdRZBdSZCereddTdUdVddVddWZeDedXZEn*eddYdUdZddYdd[Zd\ZEerOd]ed,= 3.2 (as of passlib 1.7)itjavatpypy_version_infos0passlib requires pypy >= 2.0 (as of passlib 1.7)tPystoncCs ||_dS(sadd docstring to an objectN(t__doc__(tobjtdoc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytadd_doc)stPY2tPY3tPY26tBytesIOtStringIOtNativeStringIOtSafeConfigParsertprint_t int_typest num_typestunicode_or_bytes_typestnative_string_typestutunicodet uascii_to_strt bascii_to_strt str_to_uasciit str_to_basciit join_unicodet join_bytestjoin_byte_valuestjoin_byte_elemstbyte_elem_valuetiter_byte_valuestirangetimaptlmapt iteritemst itervaluestnextt OrderedDicttget_method_functionRcCst|tst|S(N(t isinstancetstrtAssertionError(ts((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRascCs"t|tst|jdS(Ntunicode_escape(R'R(R)tdecode(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRkstcCst|tst|S(N(R'RR)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs"t|tst|jdS(Ntascii(R'tbytesR)R,(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'R(R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs"t|tst|jdS(NR.(R'R(R)tencode(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'tintR)(telem((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'R/R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs#t|tstd|DS(Ncss|]}t|gVqdS(N(R/(t.0tc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s(R'R/R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytiter_byte_charsscCs"t|tst|jdS(NR.(R'RR)R0(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'R/R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs"t|tst|jdS(NR.(R'R(R)R,(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'R(R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCstd|DS(Ncss|]}t|VqdS(N(tchr(R3tv((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s(R(tvalues((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs#t|tstd|DS(Ncss|]}t|VqdS(N(tord(R3R4((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s(R'R/R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCst|tst|S(N(R'R/R)(R*((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR5ss-helper to convert ascii unicode -> native strs+helper to convert ascii bytes -> native strs-helper to convert ascii native str -> unicodes+helper to convert ascii native str -> bytess2iterate over byte string as sequence of ints 0-255s6iterate over byte string as sequence of 1-byte stringscOstt||S(N(tlisttmap(tatk((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR!scCs |jS(N(titems(td((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR"scCs |jS(N(R8(R?((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR#scCs|jS(N(t__next__(R((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt nextgetters(R tizipcCs |jS(N(R"(R?((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR"scCs |jS(N(R#(R?((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR#scCs|jS(N(R$(R((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRAss;return function that yields successive values from iterablet__func__tim_funccCst|t|S(s4given (potential) method, return underlying function(tgetattrtmethod_function_attr(tfunc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR&scCstr |S|jS(s0given unbound method, return underlying function(RRC(RG((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytget_unbound_method_functionscCs d|_|S(s backward compat hack to suppress exception cause in python3.3+ one python < 3.3 support is dropped, can replace all uses with "raise exc from None" N(tNonet __cause__(texc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytsuppress_cause"s s io.BytesIOt UnicodeIOs io.StringIOsconfigparser.ConfigParsertprintscStringIO.StringIOsStringIO.StringIOsConfigParser.SafeConfigParserc Os|jdtj}|jdd}|jdd}|rNtdn|dkr^dSt|tpt|tptd|D}|dkr|rtdnd}nt|t stdn|dkr|rtd nd }nt|t std nt }|j }xO|D]G}|rGt }n ||t|t sot|}n||q2W||dS( sThe new-style print function.tfiletseptendsinvalid keyword argumentsNcss|]}t|tVqdS(N(R'R(R3targ((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys Oss send must be None or a stringt ssep must be None or a string(tpoptsyststdoutRIt TypeErrorR'RtanyRRtTruetwritetFalset basestringR(( targstkwdstfpRPRQt want_unicodetfirstRZRR((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR@s6       s.passlib.utils.compat._ordered_dict.OrderedDictscollections.OrderedDict(t ModuleTypecCs@|jdd\}}t|d|gdd}t||S(sChelper to import object from module; accept format `path.to.object`t.itfromlisttleveli(trsplitt __import__RE(tsourcetmodnametmodattrtmod((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt_import_objectwst_LazyOverlayModulecBsDeZdZedZddZdZdZdZ RS(sgproxy module which overlays original module, and lazily imports specified attributes. this is mainly used to prevent importing of resources that are only needed by certain password hashes, yet allow them to be imported from a single location. used by :mod:`passlib.utils`, :mod:`passlib.crypto`, and :mod:`passlib.utils.compat`. cCs0tj|}||||}|tj|<|S(N(RUtmodules(tclstnametattrmaptorigtself((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytreplace_modules  cCs8tj||||_||_tj||_dS(N(Rbt__init__t_LazyOverlayModule__attrmapt_LazyOverlayModule__proxytloggingt getLoggert_LazyOverlayModule__log(RsRpRqtproxy((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRus  cCs|j}|r+t||r+t||S|j}||kr||}t|rb|}n t|}t||||jjd|||St d|fdS(Nsloaded lazy attr %r: %rs%'module' object has no attribute '%s'( RwthasattrRERvtcallableRltsetattrRztdebugtAttributeError(RstattrR{RqRhtvalue((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt __getattr__s        cCs*|j}|rt|Stj|SdS(N(RwtreprRbt__repr__(RsR{((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRs  cCsjtt|j}|j|j|j|j|j}|dk r`|jt|nt|S(N( tsettdirt __class__tupdatet__dict__RvRwRIR:(RstattrsR{((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt__dir__s  N( t__name__t __module__Rt classmethodRtRIRuRRR(((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRm}s     (ii(ii(ii(ii(ii(ii(ii(KRRUt version_infoRRt RuntimeErrorR tplatformt startswithtJYTHONR|tPYPYRtversiontPYSTONRxRyRtlogtbuiltinst __builtin__Rt__all__tdictt _lazy_attrsR(RRR/RRR\tunicode_or_bytestunicode_or_strtjoinRRRRRRRRRRR5R9R1RtfloatRtlongtrangeRR!R;R R"R#RAtzipRBtxranget itertoolsRFR&RHRLRERttypesRbRlRmRt(((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyts .                                                      -   :compat/_ordered_dict.pyc000064400000022356147221702050011342 0ustar00 5Xc@sXdZyddlmZWn!ek r=ddlmZnXdefdYZdS(spasslib.utils.compat._ordered_dict -- backport of collections.OrderedDict for py26 taken from stdlib-suggested recipe at http://code.activestate.com/recipes/576693/ this should be imported from passlib.utils.compat.OrderedDict, not here. i(t get_identt OrderedDictcBseZdZdZejdZejdZdZdZdZ e dZ dZ d Z d Zd Zd Zd ZdZeZeZedZddZidZdZdZeddZdZdZRS(s)Dictionary that remembers insertion ordercOst|dkr+tdt|ny |jWn7tk rog|_}||dg|(i|_nX|j||dS(sInitialize an ordered dictionary. Signature is the same as for regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. is$expected at most 1 arguments, got %dN(tlent TypeErrort_OrderedDict__roottAttributeErrortNonet_OrderedDict__mapt_OrderedDict__update(tselftargstkwdstroot((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__init__s    cCs\||krH|j}|d}|||g|d<|d<|j| od[i]=yiiN(RR(R tkeytvaluet dict_setitemR tlast((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __setitem__)s    )cCs@||||jj|\}}}||d<||d del od[y]iiN(Rtpop(R Rt dict_delitemt link_prevt link_next((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __delitem__3s  ccs=|j}|d}x#||k r8|dV|d}qWdS(sod.__iter__() <==> iter(od)iiN(R(R R tcurr((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__iter__<s    ccs=|j}|d}x#||k r8|dV|d}qWdS(s#od.__reversed__() <==> reversed(od)iiN(R(R R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __reversed__Ds    cCsmyHx|jjD] }|2qW|j}||dg|(|jjWntk r[nXtj|dS(s.od.clear() -> None. Remove all items from od.N(Rt itervaluesRRtclearRtdict(R tnodeR ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRLs  cCs|stdn|j}|rO|d}|d}||d<||d (k, v), return and remove a (key, value) pair. Pairs are returned in LIFO order if last is true or FIFO order if false. sdictionary is emptyiii(tKeyErrorRRRR(R RR tlinkRRRR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytpopitemXs            cCs t|S(sod.keys() -> list of keys in od(tlist(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytkeysqscCsg|D]}||^qS(s#od.values() -> list of values in od((R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytvaluesuscCs!g|D]}|||f^qS(s.od.items() -> list of (key, value) pairs in od((R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytitemsyscCs t|S(s0od.iterkeys() -> an iterator over the keys in od(titer(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytiterkeys}sccsx|D]}||VqWdS(s2od.itervalues -> an iterator over the values in odN((R tk((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRs ccs$x|D]}|||fVqWdS(s=od.iteritems -> an iterator over the (key, value) items in odN((R R(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt iteritemss cOs&t|dkr.tdt|fn|sCtdn|d}d}t|dkrr|d}nt|trxw|D]}|||| None. Update od from dict/iterable E and F. If E is a dict instance, does: for k in E: od[k] = E[k] If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] Or if E is an iterable of items, does: for k, v in E: od[k] = v In either case, this is followed by: for k, v in F.items(): od[k] = v is8update() takes at most 2 positional arguments (%d given)s,update() takes at least 1 argument (0 given)iiR#N((RRt isinstanceRthasattrR#R%(R R R totherRR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytupdates&    cCsC||kr!||}||=|S||jkr?t|n|S(sod.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. (t_OrderedDict__markerR(R Rtdefaulttresult((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRs  cCs"||kr||S|||<|S(sDod.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od((R RR/((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt setdefaults  cCsst|tf}||kr%dSd|| repr(od)s...is%s()s%s(%r)N(tidt _get_identt __class__t__name__R%(R t _repr_runningtcall_key((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__repr__s  cCsg|D]}|||g^q}t|j}x'ttD]}|j|dqEW|rx|j|f|fS|j|ffS(s%Return state information for picklingN(tvarstcopyRRRR4(R R(R%t inst_dict((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __reduce__s#cCs |j|S(s!od.copy() -> a shallow copy of od(R4(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyR:scCs(|}x|D]}||| New ordered dictionary with keys from S and values equal to v (which defaults to None). ((tclstiterableRtdR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytfromkeyss  cCsMt|tr=t|t|ko<|j|jkStj||S(sod.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive while comparison to a regular mapping is order-insensitive. (R*RRR%Rt__eq__(R R,((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRAs.cCs ||k S(N((R R,((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__ne__sN( R5t __module__t__doc__R RRRRRRtTrueR!R#R$R%R'RR)R-RtobjectR.RRR1R8R<R:t classmethodR@RARB(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyR s4                N(RDtthreadRR3t ImportErrort dummy_threadRR(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyts  compat/__init__.pyo000064400000031133147221702050010320 0ustar00 5Xc$@sdZddlZejdckZejddkZejdeks^dfejkoYdgknrmednejdhkZejjd Z e ed Z e rej dikred nd ej kZddlZejeZerddlZn ddlZd Zddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.g!ZeZereZd/ZeefZefZn$ejZd0ZefZefZeZ eZ!ed1j"Z#d1j"Z$erNd2Z%d3Z&d4Z'd5Z(eZ)Z*d6Z+d7Z,d8Z-nKd9Z%d:Z&d;Z'd<Z(d=Z)e$Z*e.Z+d>Z,d?Z-ee%d@ee&dAee'dBee(dCee,dDee-dEere/fZ0e/e1fZ2ne/e3fZ0e/e3e1fZ2er_e4Z5dFZ6e7Z8dGZ9dHZ:dIZ;e<Z=n=e>Z5e7Z6ddJl?m8Z8m=Z=dKZ9dLZ:dMZ;ee;dNerdOZ@ndPZ@dQZAdRZBdSZCereddTdUdVddVddWZeDedXZEn*eddYdUdZddYdd[Zd\ZEerOd]ed,= 3.2 (as of passlib 1.7)itjavatpypy_version_infos0passlib requires pypy >= 2.0 (as of passlib 1.7)tPystoncCs ||_dS(sadd docstring to an objectN(t__doc__(tobjtdoc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytadd_doc)stPY2tPY3tPY26tBytesIOtStringIOtNativeStringIOtSafeConfigParsertprint_t int_typest num_typestunicode_or_bytes_typestnative_string_typestutunicodet uascii_to_strt bascii_to_strt str_to_uasciit str_to_basciit join_unicodet join_bytestjoin_byte_valuestjoin_byte_elemstbyte_elem_valuetiter_byte_valuestirangetimaptlmapt iteritemst itervaluestnextt OrderedDicttget_method_functionRcCs|S(N((ts((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRascCs |jdS(Ntunicode_escape(tdecode(R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRkstcCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs |jdS(Ntascii(R)(R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs |jdS(NR+(tencode(R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((telem((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCsd|DS(Ncss|]}t|gVqdS(N(tbytes(t.0tc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytiter_byte_charsscCs |jdS(NR+(R,(R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs |jdS(NR+(R)(R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCstd|DS(Ncss|]}t|VqdS(N(tchr(R/tv((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s(R(tvalues((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCsd|DS(Ncss|]}t|VqdS(N(tord(R/R0((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys s((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRscCs|S(N((R'((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR1ss-helper to convert ascii unicode -> native strs+helper to convert ascii bytes -> native strs-helper to convert ascii native str -> unicodes+helper to convert ascii native str -> bytess2iterate over byte string as sequence of ints 0-255s6iterate over byte string as sequence of 1-byte stringscOstt||S(N(tlisttmap(tatk((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR!scCs |jS(N(titems(td((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR"scCs |jS(N(R4(R;((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR#scCs|jS(N(t__next__(R((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt nextgetters(R tizipcCs |jS(N(R"(R;((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR"scCs |jS(N(R#(R;((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR#scCs|jS(N(R$(R((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR=ss;return function that yields successive values from iterablet__func__tim_funccCst|t|S(s4given (potential) method, return underlying function(tgetattrtmethod_function_attr(tfunc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR&scCstr |S|jS(s0given unbound method, return underlying function(RR?(RC((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytget_unbound_method_functionscCs d|_|S(s backward compat hack to suppress exception cause in python3.3+ one python < 3.3 support is dropped, can replace all uses with "raise exc from None" N(tNonet __cause__(texc((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytsuppress_cause"s s io.BytesIOt UnicodeIOs io.StringIOsconfigparser.ConfigParsertprintscStringIO.StringIOsStringIO.StringIOsConfigParser.SafeConfigParserc Os|jdtj}|jdd}|jdd}|rNtdn|dkr^dSt|tpt|tptd|D}|dkr|rtdnd}nt|t stdn|dkr|rtd nd }nt|t std nt }|j }xO|D]G}|rGt }n ||t|t sot|}n||q2W||dS( sThe new-style print function.tfiletseptendsinvalid keyword argumentsNcss|]}t|tVqdS(N(t isinstanceR(R/targ((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pys Oss send must be None or a stringt ssep must be None or a string(tpoptsyststdoutREt TypeErrorRNRtanyRRtTruetwritetFalset basestringtstr( targstkwdstfpRLRMt want_unicodetfirstRWRO((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyR@s6       s.passlib.utils.compat._ordered_dict.OrderedDictscollections.OrderedDict(t ModuleTypecCs@|jdd\}}t|d|gdd}t||S(sChelper to import object from module; accept format `path.to.object`t.itfromlisttleveli(trsplitt __import__RA(tsourcetmodnametmodattrtmod((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt_import_objectwst_LazyOverlayModulecBsDeZdZedZddZdZdZdZ RS(sgproxy module which overlays original module, and lazily imports specified attributes. this is mainly used to prevent importing of resources that are only needed by certain password hashes, yet allow them to be imported from a single location. used by :mod:`passlib.utils`, :mod:`passlib.crypto`, and :mod:`passlib.utils.compat`. cCs0tj|}||||}|tj|<|S(N(RRtmodules(tclstnametattrmaptorigtself((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pytreplace_modules  cCs8tj||||_||_tj||_dS(N(R`t__init__t_LazyOverlayModule__attrmapt_LazyOverlayModule__proxytloggingt getLoggert_LazyOverlayModule__log(RqRnRotproxy((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRss  cCs|j}|r+t||r+t||S|j}||kr||}t|rb|}n t|}t||||jjd|||St d|fdS(Nsloaded lazy attr %r: %rs%'module' object has no attribute '%s'( RuthasattrRARttcallableRjtsetattrRxtdebugtAttributeError(RqtattrRyRoRftvalue((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt __getattr__s        cCs*|j}|rt|Stj|SdS(N(RutreprR`t__repr__(RqRy((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRs  cCsjtt|j}|j|j|j|j|j}|dk r`|jt|nt|S(N( tsettdirt __class__tupdatet__dict__RtRuRER6(RqtattrsRy((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyt__dir__s  N( t__name__t __module__Rt classmethodRrRERsRRR(((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyRk}s     (ii(ii(ii(ii(ii(ii(ii(KRRRt version_infoRRt RuntimeErrorR tplatformt startswithtJYTHONRztPYPYRtversiontPYSTONRvRwRtlogtbuiltinst __builtin__Rt__all__tdictt _lazy_attrsRZRRR.RRRYtunicode_or_bytestunicode_or_strtjoinRRRRRRRRRRR1R5tintRtfloatRtlongtrangeRR!R7R R"R#R=tzipR>txranget itertoolsRBR&RDRHRARttypesR`RjRkRr(((sA/usr/lib/python2.7/site-packages/passlib/utils/compat/__init__.pyts .                                                      -   :compat/_ordered_dict.pyo000064400000022356147221702050011356 0ustar00 5Xc@sXdZyddlmZWn!ek r=ddlmZnXdefdYZdS(spasslib.utils.compat._ordered_dict -- backport of collections.OrderedDict for py26 taken from stdlib-suggested recipe at http://code.activestate.com/recipes/576693/ this should be imported from passlib.utils.compat.OrderedDict, not here. i(t get_identt OrderedDictcBseZdZdZejdZejdZdZdZdZ e dZ dZ d Z d Zd Zd Zd ZdZeZeZedZddZidZdZdZeddZdZdZRS(s)Dictionary that remembers insertion ordercOst|dkr+tdt|ny |jWn7tk rog|_}||dg|(i|_nX|j||dS(sInitialize an ordered dictionary. Signature is the same as for regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. is$expected at most 1 arguments, got %dN(tlent TypeErrort_OrderedDict__roottAttributeErrortNonet_OrderedDict__mapt_OrderedDict__update(tselftargstkwdstroot((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__init__s    cCs\||krH|j}|d}|||g|d<|d<|j| od[i]=yiiN(RR(R tkeytvaluet dict_setitemR tlast((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __setitem__)s    )cCs@||||jj|\}}}||d<||d del od[y]iiN(Rtpop(R Rt dict_delitemt link_prevt link_next((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __delitem__3s  ccs=|j}|d}x#||k r8|dV|d}qWdS(sod.__iter__() <==> iter(od)iiN(R(R R tcurr((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__iter__<s    ccs=|j}|d}x#||k r8|dV|d}qWdS(s#od.__reversed__() <==> reversed(od)iiN(R(R R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __reversed__Ds    cCsmyHx|jjD] }|2qW|j}||dg|(|jjWntk r[nXtj|dS(s.od.clear() -> None. Remove all items from od.N(Rt itervaluesRRtclearRtdict(R tnodeR ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRLs  cCs|stdn|j}|rO|d}|d}||d<||d (k, v), return and remove a (key, value) pair. Pairs are returned in LIFO order if last is true or FIFO order if false. sdictionary is emptyiii(tKeyErrorRRRR(R RR tlinkRRRR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytpopitemXs            cCs t|S(sod.keys() -> list of keys in od(tlist(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytkeysqscCsg|D]}||^qS(s#od.values() -> list of values in od((R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytvaluesuscCs!g|D]}|||f^qS(s.od.items() -> list of (key, value) pairs in od((R R((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytitemsyscCs t|S(s0od.iterkeys() -> an iterator over the keys in od(titer(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytiterkeys}sccsx|D]}||VqWdS(s2od.itervalues -> an iterator over the values in odN((R tk((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRs ccs$x|D]}|||fVqWdS(s=od.iteritems -> an iterator over the (key, value) items in odN((R R(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt iteritemss cOs&t|dkr.tdt|fn|sCtdn|d}d}t|dkrr|d}nt|trxw|D]}|||| None. Update od from dict/iterable E and F. If E is a dict instance, does: for k in E: od[k] = E[k] If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] Or if E is an iterable of items, does: for k, v in E: od[k] = v In either case, this is followed by: for k, v in F.items(): od[k] = v is8update() takes at most 2 positional arguments (%d given)s,update() takes at least 1 argument (0 given)iiR#N((RRt isinstanceRthasattrR#R%(R R R totherRR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytupdates&    cCsC||kr!||}||=|S||jkr?t|n|S(sod.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. (t_OrderedDict__markerR(R Rtdefaulttresult((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRs  cCs"||kr||S|||<|S(sDod.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od((R RR/((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt setdefaults  cCsst|tf}||kr%dSd|| repr(od)s...is%s()s%s(%r)N(tidt _get_identt __class__t__name__R%(R t _repr_runningtcall_key((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__repr__s  cCsg|D]}|||g^q}t|j}x'ttD]}|j|dqEW|rx|j|f|fS|j|ffS(s%Return state information for picklingN(tvarstcopyRRRR4(R R(R%t inst_dict((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt __reduce__s#cCs |j|S(s!od.copy() -> a shallow copy of od(R4(R ((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyR:scCs(|}x|D]}||| New ordered dictionary with keys from S and values equal to v (which defaults to None). ((tclstiterableRtdR((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pytfromkeyss  cCsMt|tr=t|t|ko<|j|jkStj||S(sod.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive while comparison to a regular mapping is order-insensitive. (R*RRR%Rt__eq__(R R,((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyRAs.cCs ||k S(N((R R,((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyt__ne__sN( R5t __module__t__doc__R RRRRRRtTrueR!R#R$R%R'RR)R-RtobjectR.RRR1R8R<R:t classmethodR@RARB(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyR s4                N(RDtthreadRR3t ImportErrort dummy_threadRR(((sF/usr/lib/python2.7/site-packages/passlib/utils/compat/_ordered_dict.pyts  compat/_ordered_dict.py000064400000020260147221702050011167 0ustar00"""passlib.utils.compat._ordered_dict -- backport of collections.OrderedDict for py26 taken from stdlib-suggested recipe at http://code.activestate.com/recipes/576693/ this should be imported from passlib.utils.compat.OrderedDict, not here. """ try: from thread import get_ident as _get_ident except ImportError: from dummy_thread import get_ident as _get_ident class OrderedDict(dict): """Dictionary that remembers insertion order""" # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. # Big-O running times for all methods are the same as for regular dictionaries. # The internal self.__map dictionary maps keys to links in a doubly linked list. # The circular doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted (this simplifies the algorithm). # Each link is stored as a list of length three: [PREV, NEXT, KEY]. def __init__(self, *args, **kwds): '''Initialize an ordered dictionary. Signature is the same as for regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. ''' if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: self.__root except AttributeError: self.__root = root = [] # sentinel node root[:] = [root, root, None] self.__map = {} self.__update(*args, **kwds) def __setitem__(self, key, value, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y' # Setting a new item creates a new link which goes at the end of the linked # list, and the inherited dictionary is updated with the new key/value pair. if key not in self: root = self.__root last = root[0] last[1] = root[0] = self.__map[key] = [last, root, key] dict_setitem(self, key, value) def __delitem__(self, key, dict_delitem=dict.__delitem__): 'od.__delitem__(y) <==> del od[y]' # Deleting an existing item uses self.__map to find the link which is # then removed by updating the links in the predecessor and successor nodes. dict_delitem(self, key) link_prev, link_next, key = self.__map.pop(key) link_prev[1] = link_next link_next[0] = link_prev def __iter__(self): 'od.__iter__() <==> iter(od)' root = self.__root curr = root[1] while curr is not root: yield curr[2] curr = curr[1] def __reversed__(self): 'od.__reversed__() <==> reversed(od)' root = self.__root curr = root[0] while curr is not root: yield curr[2] curr = curr[0] def clear(self): 'od.clear() -> None. Remove all items from od.' try: for node in self.__map.itervalues(): del node[:] root = self.__root root[:] = [root, root, None] self.__map.clear() except AttributeError: pass dict.clear(self) def popitem(self, last=True): '''od.popitem() -> (k, v), return and remove a (key, value) pair. Pairs are returned in LIFO order if last is true or FIFO order if false. ''' if not self: raise KeyError('dictionary is empty') root = self.__root if last: link = root[0] link_prev = link[0] link_prev[1] = root root[0] = link_prev else: link = root[1] link_next = link[1] root[1] = link_next link_next[0] = root key = link[2] del self.__map[key] value = dict.pop(self, key) return key, value # -- the following methods do not depend on the internal structure -- def keys(self): 'od.keys() -> list of keys in od' return list(self) def values(self): 'od.values() -> list of values in od' return [self[key] for key in self] def items(self): 'od.items() -> list of (key, value) pairs in od' return [(key, self[key]) for key in self] def iterkeys(self): 'od.iterkeys() -> an iterator over the keys in od' return iter(self) def itervalues(self): 'od.itervalues -> an iterator over the values in od' for k in self: yield self[k] def iteritems(self): 'od.iteritems -> an iterator over the (key, value) items in od' for k in self: yield (k, self[k]) def update(*args, **kwds): '''od.update(E, **F) -> None. Update od from dict/iterable E and F. If E is a dict instance, does: for k in E: od[k] = E[k] If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] Or if E is an iterable of items, does: for k, v in E: od[k] = v In either case, this is followed by: for k, v in F.items(): od[k] = v ''' if len(args) > 2: raise TypeError('update() takes at most 2 positional ' 'arguments (%d given)' % (len(args),)) elif not args: raise TypeError('update() takes at least 1 argument (0 given)') self = args[0] # Make progressively weaker assumptions about "other" other = () if len(args) == 2: other = args[1] if isinstance(other, dict): for key in other: self[key] = other[key] elif hasattr(other, 'keys'): for key in other.keys(): self[key] = other[key] else: for key, value in other: self[key] = value for key, value in kwds.items(): self[key] = value __update = update # let subclasses override update without breaking __init__ __marker = object() def pop(self, key, default=__marker): '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. ''' if key in self: result = self[key] del self[key] return result if default is self.__marker: raise KeyError(key) return default def setdefault(self, key, default=None): 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' if key in self: return self[key] self[key] = default return default def __repr__(self, _repr_running={}): 'od.__repr__() <==> repr(od)' call_key = id(self), _get_ident() if call_key in _repr_running: return '...' _repr_running[call_key] = 1 try: if not self: return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, self.items()) finally: del _repr_running[call_key] def __reduce__(self): 'Return state information for pickling' items = [[k, self[k]] for k in self] inst_dict = vars(self).copy() for k in vars(OrderedDict()): inst_dict.pop(k, None) if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) def copy(self): 'od.copy() -> a shallow copy of od' return self.__class__(self) @classmethod def fromkeys(cls, iterable, value=None): '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S and values equal to v (which defaults to None). ''' d = cls() for key in iterable: d[key] = value return d def __eq__(self, other): '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive while comparison to a regular mapping is order-insensitive. ''' if isinstance(other, OrderedDict): return len(self)==len(other) and self.items() == other.items() return dict.__eq__(self, other) def __ne__(self, other): return not self == other des.pyo000064400000003052147221702050006050 0ustar00 5Xc@sdZddlmZededdlmZddlmZmZm Z edddd d d eZedddd d d eZedddd d d e Z ddl Z e j dj Z edddd d ddddZdS(st passlib.utils.des - DEPRECATED LOCATION, WILL BE REMOVED IN 2.0 This has been moved to :mod:`passlib.crypto.des`. i(twarnsthe 'passlib.utils.des' module has been relocated to 'passlib.crypto.des' as of passlib 1.7, and the old location will be removed in passlib 2.0(tdeprecated_function(texpand_des_keytdes_encrypt_blocktdes_encrypt_int_blockt deprecateds1.7tremoveds1.8t replacements!passlib.crypto.des.expand_des_keys$passlib.crypto.des.des_encrypt_blocks(passlib.crypto.des.des_encrypt_int_blockNs>Qs1.6s*passlib.crypto.des.des_encrypt_int_block()iicCsVt|trCt|dkr0t|}nt|d}nt||||S(Nii(t isinstancetbytestlenRt_unpack_uint64R(tkeytinputtsalttrounds((s5/usr/lib/python2.7/site-packages/passlib/utils/des.pytmdes_encrypt_int_block#s (t__doc__twarningsRtDeprecationWarningtpasslib.utils.decorRtpasslib.crypto.desRRRtstructtStructtunpackR R(((s5/usr/lib/python2.7/site-packages/passlib/utils/des.pyts  handlers.py000064400000313426147221702050006727 0ustar00"""passlib.handler - code for implementing handlers, and global registry for handlers""" #============================================================================= # imports #============================================================================= from __future__ import with_statement # core import inspect import logging; log = logging.getLogger(__name__) import math import threading from warnings import warn # site # pkg import passlib.exc as exc, passlib.ifc as ifc from passlib.exc import MissingBackendError, PasslibConfigWarning, \ PasslibHashWarning from passlib.ifc import PasswordHash from passlib.registry import get_crypt_handler from passlib.utils import ( consteq, getrandstr, getrandbytes, rng, to_native_str, is_crypt_handler, to_unicode, MAX_PASSWORD_SIZE, accepts_keyword, as_bool, update_mixin_classes) from passlib.utils.binary import ( BASE64_CHARS, HASH64_CHARS, PADDED_BASE64_CHARS, HEX_CHARS, UPPER_HEX_CHARS, LOWER_HEX_CHARS, ALL_BYTE_VALUES, ) from passlib.utils.compat import join_byte_values, irange, u, native_string_types, \ uascii_to_str, join_unicode, unicode, str_to_uascii, \ join_unicode, unicode_or_bytes_types, PY2, int_types from passlib.utils.decor import classproperty, deprecated_method # local __all__ = [ # helpers for implementing MCF handlers 'parse_mc2', 'parse_mc3', 'render_mc2', 'render_mc3', # framework for implementing handlers 'GenericHandler', 'StaticHandler', 'HasUserContext', 'HasRawChecksum', 'HasManyIdents', 'HasSalt', 'HasRawSalt', 'HasRounds', 'HasManyBackends', # other helpers 'PrefixWrapper', # TODO: a bunch of other things are commonly assumed in this namespace # (e.g. HEX_CHARS etc); need to audit uses and update this list. ] #============================================================================= # constants #============================================================================= # deprecated aliases - will be removed after passlib 1.8 H64_CHARS = HASH64_CHARS B64_CHARS = BASE64_CHARS PADDED_B64_CHARS = PADDED_BASE64_CHARS UC_HEX_CHARS = UPPER_HEX_CHARS LC_HEX_CHARS = LOWER_HEX_CHARS #============================================================================= # support functions #============================================================================= def _bitsize(count, chars): """helper for bitsize() methods""" if chars and count: import math return int(count * math.log(len(chars), 2)) else: return 0 def guess_app_stacklevel(start=1): """ try to guess stacklevel for application warning. looks for first frame not part of passlib. """ frame = inspect.currentframe() count = -start try: while frame: name = frame.f_globals.get('__name__', "") if name.startswith("passlib.tests.") or not name.startswith("passlib."): return max(1, count) count += 1 frame = frame.f_back return start finally: del frame def warn_hash_settings_deprecation(handler, kwds): warn("passing settings to %(handler)s.hash() is deprecated, and won't be supported in Passlib 2.0; " "use '%(handler)s.using(**settings).hash(secret)' instead" % dict(handler=handler.name), DeprecationWarning, stacklevel=guess_app_stacklevel(2)) def extract_settings_kwds(handler, kwds): """ helper to extract settings kwds from mix of context & settings kwds. pops settings keys from kwds, returns them as a dict. """ context_keys = set(handler.context_kwds) return dict((key, kwds.pop(key)) for key in list(kwds) if key not in context_keys) #============================================================================= # parsing helpers #============================================================================= _UDOLLAR = u("$") _UZERO = u("0") def validate_secret(secret): """ensure secret has correct type & size""" if not isinstance(secret, unicode_or_bytes_types): raise exc.ExpectedStringError(secret, "secret") if len(secret) > MAX_PASSWORD_SIZE: raise exc.PasswordSizeError(MAX_PASSWORD_SIZE) def to_unicode_for_identify(hash): """convert hash to unicode for identify method""" if isinstance(hash, unicode): return hash elif isinstance(hash, bytes): # try as utf-8, but if it fails, use foolproof latin-1, # since we don't really care about non-ascii chars # when running identify. try: return hash.decode("utf-8") except UnicodeDecodeError: return hash.decode("latin-1") else: raise exc.ExpectedStringError(hash, "hash") def parse_mc2(hash, prefix, sep=_UDOLLAR, handler=None): """parse hash using 2-part modular crypt format. this expects a hash of the format :samp:`{prefix}{salt}[${checksum}]`, such as md5_crypt, and parses it into salt / checksum portions. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param handler: handler class to pass to error constructors. :returns: a ``(salt, chk | None)`` tuple. """ # detect prefix hash = to_unicode(hash, "ascii", "hash") assert isinstance(prefix, unicode) if not hash.startswith(prefix): raise exc.InvalidHashError(handler) # parse 2-part hash or 1-part config string assert isinstance(sep, unicode) parts = hash[len(prefix):].split(sep) if len(parts) == 2: salt, chk = parts return salt, chk or None elif len(parts) == 1: return parts[0], None else: raise exc.MalformedHashError(handler) def parse_mc3(hash, prefix, sep=_UDOLLAR, rounds_base=10, default_rounds=None, handler=None): """parse hash using 3-part modular crypt format. this expects a hash of the format :samp:`{prefix}[{rounds}]${salt}[${checksum}]`, such as sha1_crypt, and parses it into rounds / salt / checksum portions. tries to convert the rounds to an integer, and throws error if it has zero-padding. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param rounds_base: the numeric base the rounds are encoded in (defaults to base 10). :param default_rounds: the default rounds value to return if the rounds field was omitted. if this is ``None`` (the default), the rounds field is *required*. :param handler: handler class to pass to error constructors. :returns: a ``(rounds : int, salt, chk | None)`` tuple. """ # detect prefix hash = to_unicode(hash, "ascii", "hash") assert isinstance(prefix, unicode) if not hash.startswith(prefix): raise exc.InvalidHashError(handler) # parse 3-part hash or 2-part config string assert isinstance(sep, unicode) parts = hash[len(prefix):].split(sep) if len(parts) == 3: rounds, salt, chk = parts elif len(parts) == 2: rounds, salt = parts chk = None else: raise exc.MalformedHashError(handler) # validate & parse rounds portion if rounds.startswith(_UZERO) and rounds != _UZERO: raise exc.ZeroPaddedRoundsError(handler) elif rounds: rounds = int(rounds, rounds_base) elif default_rounds is None: raise exc.MalformedHashError(handler, "empty rounds field") else: rounds = default_rounds # return result return rounds, salt, chk or None # def parse_mc3_long(hash, prefix, sep=_UDOLLAR, handler=None): # """ # parse hash using 3-part modular crypt format, # with complex settings string instead of simple rounds. # otherwise works same as :func:`parse_mc3` # """ # # detect prefix # hash = to_unicode(hash, "ascii", "hash") # assert isinstance(prefix, unicode) # if not hash.startswith(prefix): # raise exc.InvalidHashError(handler) # # # parse 3-part hash or 2-part config string # assert isinstance(sep, unicode) # parts = hash[len(prefix):].split(sep) # if len(parts) == 3: # return parts # elif len(parts) == 2: # settings, salt = parts # return settings, salt, None # else: # raise exc.MalformedHashError(handler) def parse_int(source, base=10, default=None, param="value", handler=None): """ helper to parse an integer config field :arg source: unicode source string :param base: numeric base :param default: optional default if source is empty :param param: name of variable, for error msgs :param handler: handler class, for error msgs """ if source.startswith(_UZERO) and source != _UZERO: raise exc.MalformedHashError(handler, "zero-padded %s field" % param) elif source: return int(source, base) elif default is None: raise exc.MalformedHashError(handler, "empty %s field" % param) else: return default #============================================================================= # formatting helpers #============================================================================= def render_mc2(ident, salt, checksum, sep=u("$")): """format hash using 2-part modular crypt format; inverse of parse_mc2() returns native string with format :samp:`{ident}{salt}[${checksum}]`, such as used by md5_crypt. :arg ident: identifier prefix (unicode) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :returns: config or hash (native str) """ if checksum: parts = [ident, salt, sep, checksum] else: parts = [ident, salt] return uascii_to_str(join_unicode(parts)) def render_mc3(ident, rounds, salt, checksum, sep=u("$"), rounds_base=10): """format hash using 3-part modular crypt format; inverse of parse_mc3() returns native string with format :samp:`{ident}[{rounds}$]{salt}[${checksum}]`, such as used by sha1_crypt. :arg ident: identifier prefix (unicode) :arg rounds: rounds field (int or None) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :param rounds_base: base to encode rounds value (defaults to base 10) :returns: config or hash (native str) """ if rounds is None: rounds = u('') elif rounds_base == 16: rounds = u("%x") % rounds else: assert rounds_base == 10 rounds = unicode(rounds) if checksum: parts = [ident, rounds, sep, salt, sep, checksum] else: parts = [ident, rounds, sep, salt] return uascii_to_str(join_unicode(parts)) #============================================================================= # parameter helpers #============================================================================= def validate_default_value(handler, default, norm, param="value"): """ assert helper that quickly validates default value. designed to get out of the way and reduce overhead when asserts are stripped. """ assert default is not None, "%s lacks default %s" % (handler.name, param) assert norm(default) == default, "%s: invalid default %s: %r" % (handler.name, param, default) return True def norm_integer(handler, value, min=1, max=None, # * param="value", relaxed=False): """ helper to normalize and validate an integer value (e.g. rounds, salt_size) :arg value: value provided to constructor :arg default: default value if none provided. if set to ``None``, value is required. :arg param: name of parameter (xxx: move to first arg?) :param min: minimum value (defaults to 1) :param max: maximum value (default ``None`` means no maximum) :returns: validated value """ # check type if not isinstance(value, int_types): raise exc.ExpectedTypeError(value, "integer", param) # check minimum if value < min: msg = "%s: %s (%d) is too low, must be at least %d" % (handler.name, param, value, min) if relaxed: warn(msg, exc.PasslibHashWarning) value = min else: raise ValueError(msg) # check maximum if max and value > max: msg = "%s: %s (%d) is too large, cannot be more than %d" % (handler.name, param, value, max) if relaxed: warn(msg, exc.PasslibHashWarning) value = max else: raise ValueError(msg) return value #============================================================================= # MinimalHandler #============================================================================= class MinimalHandler(PasswordHash): """ helper class for implementing hash handlers. provides nothing besides a base implementation of the .using() subclass constructor. """ #=================================================================== # class attr #=================================================================== #: private flag used by using() constructor to detect if this is already a subclass. _configured = False #=================================================================== # configuration interface #=================================================================== @classmethod def using(cls, relaxed=False): # NOTE: this provides the base implementation, which takes care of # creating the newly configured class. Mixins and subclasses # should wrap this, and modify the returned class to suit their options. # NOTE: 'relaxed' keyword is ignored here, but parsed so that subclasses # can check for it as argument, and modify their parsing behavior accordingly. name = cls.__name__ if not cls._configured: # TODO: straighten out class naming, repr, and .name attr name = "" % name return type(name, (cls,), dict(__module__=cls.__module__, _configured=True)) #=================================================================== # eoc #=================================================================== class TruncateMixin(MinimalHandler): """ PasswordHash mixin which provides a method that will check if secret would be truncated, and can be configured to throw an error. .. warning:: Hashers using this mixin will generally need to override the default PasswordHash.truncate_error policy of "True", and will similarly want to override .truncate_verify_reject as well. TODO: This should be done explicitly, but for now this mixin sets these flags implicitly. """ truncate_error = False truncate_verify_reject = False @classmethod def using(cls, truncate_error=None, **kwds): subcls = super(TruncateMixin, cls).using(**kwds) if truncate_error is not None: truncate_error = as_bool(truncate_error, param="truncate_error") if truncate_error is not None: subcls.truncate_error = truncate_error return subcls @classmethod def _check_truncate_policy(cls, secret): """ make sure secret won't be truncated. NOTE: this should only be called for .hash(), not for .verify(), which should honor the .truncate_verify_reject policy. """ assert cls.truncate_size is not None, "truncate_size must be set by subclass" if cls.truncate_error and len(secret) > cls.truncate_size: raise exc.PasswordTruncateError(cls) #============================================================================= # GenericHandler #============================================================================= class GenericHandler(MinimalHandler): """helper class for implementing hash handlers. GenericHandler-derived classes will have (at least) the following constructor options, though others may be added by mixins and by the class itself: :param checksum: this should contain the digest portion of a parsed hash (mainly provided when the constructor is called by :meth:`from_string()`). defaults to ``None``. :param use_defaults: If ``False`` (the default), a :exc:`TypeError` should be thrown if any settings required by the handler were not explicitly provided. If ``True``, the handler should attempt to provide a default for any missing values. This means generate missing salts, fill in default cost parameters, etc. This is typically only set to ``True`` when the constructor is called by :meth:`hash`, allowing user-provided values to be handled in a more permissive manner. :param relaxed: If ``False`` (the default), a :exc:`ValueError` should be thrown if any settings are out of bounds or otherwise invalid. If ``True``, they should be corrected if possible, and a warning issue. If not possible, only then should an error be raised. (e.g. under ``relaxed=True``, rounds values will be clamped to min/max rounds). This is mainly used when parsing the config strings of certain hashes, whose specifications implementations to be tolerant of incorrect values in salt strings. Class Attributes ================ .. attribute:: ident [optional] If this attribute is filled in, the default :meth:`identify` method will use it as a identifying prefix that can be used to recognize instances of this handler's hash. Filling this out is recommended for speed. This should be a unicode str. .. attribute:: _hash_regex [optional] If this attribute is filled in, the default :meth:`identify` method will use it to recognize instances of the hash. If :attr:`ident` is specified, this will be ignored. This should be a unique regex object. .. attribute:: checksum_size [optional] Specifies the number of characters that should be expected in the checksum string. If omitted, no check will be performed. .. attribute:: checksum_chars [optional] A string listing all the characters allowed in the checksum string. If omitted, no check will be performed. This should be a unicode str. .. attribute:: _stub_checksum Placeholder checksum that will be used by genconfig() in lieu of actually generating a hash for the empty string. This should be a string of the same datatype as :attr:`checksum`. Instance Attributes =================== .. attribute:: checksum The checksum string provided to the constructor (after passing it through :meth:`_norm_checksum`). Required Subclass Methods ========================= The following methods must be provided by handler subclass: .. automethod:: from_string .. automethod:: to_string .. automethod:: _calc_checksum Default Methods =============== The following methods have default implementations that should work for most cases, though they may be overridden if the hash subclass needs to: .. automethod:: _norm_checksum .. automethod:: genconfig .. automethod:: genhash .. automethod:: identify .. automethod:: hash .. automethod:: verify """ #=================================================================== # class attr #=================================================================== # this must be provided by the actual class. setting_kwds = None # providing default since most classes don't use this at all. context_kwds = () # optional prefix that uniquely identifies hash ident = None # optional regexp for recognizing hashes, # used by default identify() if .ident isn't specified. _hash_regex = None # if specified, _norm_checksum will require this length checksum_size = None # if specified, _norm_checksum() will validate this checksum_chars = None # private flag used by HasRawChecksum _checksum_is_bytes = False #=================================================================== # instance attrs #=================================================================== checksum = None # stores checksum # use_defaults = False # whether _norm_xxx() funcs should fill in defaults. # relaxed = False # when _norm_xxx() funcs should be strict about inputs #=================================================================== # init #=================================================================== def __init__(self, checksum=None, use_defaults=False, **kwds): self.use_defaults = use_defaults super(GenericHandler, self).__init__(**kwds) if checksum is not None: # XXX: do we need to set .relaxed for checksum coercion? self.checksum = self._norm_checksum(checksum) # NOTE: would like to make this classmethod, but fshp checksum size # is dependant on .variant, so leaving this as instance method. def _norm_checksum(self, checksum, relaxed=False): """validates checksum keyword against class requirements, returns normalized version of checksum. """ # NOTE: by default this code assumes checksum should be unicode. # For classes where the checksum is raw bytes, the HasRawChecksum sets # the _checksum_is_bytes flag which alters various code paths below. # normalize to bytes / unicode raw = self._checksum_is_bytes if raw: # NOTE: no clear route to reasonably convert unicode -> raw bytes, # so 'relaxed' does nothing here if not isinstance(checksum, bytes): raise exc.ExpectedTypeError(checksum, "bytes", "checksum") elif not isinstance(checksum, unicode): if isinstance(checksum, bytes) and relaxed: warn("checksum should be unicode, not bytes", PasslibHashWarning) checksum = checksum.decode("ascii") else: raise exc.ExpectedTypeError(checksum, "unicode", "checksum") # check size cc = self.checksum_size if cc and len(checksum) != cc: raise exc.ChecksumSizeError(self, raw=raw) # check charset if not raw: cs = self.checksum_chars if cs and any(c not in cs for c in checksum): raise ValueError("invalid characters in %s checksum" % (self.name,)) return checksum #=================================================================== # password hash api - formatting interface #=================================================================== @classmethod def identify(cls, hash): # NOTE: subclasses may wish to use faster / simpler identify, # and raise value errors only when an invalid (but identifiable) # string is parsed hash = to_unicode_for_identify(hash) if not hash: return False # does class specify a known unique prefix to look for? ident = cls.ident if ident is not None: return hash.startswith(ident) # does class provide a regexp to use? pat = cls._hash_regex if pat is not None: return pat.match(hash) is not None # as fallback, try to parse hash, and see if we succeed. # inefficient, but works for most cases. try: cls.from_string(hash) return True except ValueError: return False @classmethod def from_string(cls, hash, **context): # pragma: no cover r""" return parsed instance from hash/configuration string :param \*\*context: context keywords to pass to constructor (if applicable). :raises ValueError: if hash is incorrectly formatted :returns: hash parsed into components, for formatting / calculating checksum. """ raise NotImplementedError("%s must implement from_string()" % (cls,)) def to_string(self): # pragma: no cover """render instance to hash or configuration string :returns: hash string with salt & digest included. should return native string type (ascii-bytes under python 2, unicode under python 3) """ raise NotImplementedError("%s must implement from_string()" % (self.__class__,)) #=================================================================== # checksum generation #=================================================================== # NOTE: this is only used by genconfig(), and will be removed in passlib 2.0 @property def _stub_checksum(self): """ placeholder used by default .genconfig() so it can avoid expense of calculating digest. """ # used fixed string if available if self.checksum_size: if self._checksum_is_bytes: return b'\x00' * self.checksum_size if self.checksum_chars: return self.checksum_chars[0] * self.checksum_size # hack to minimize cost of calculating real checksum if isinstance(self, HasRounds): orig = self.rounds self.rounds = self.min_rounds or 1 try: return self._calc_checksum("") finally: self.rounds = orig # final fallback, generate a real checksum return self._calc_checksum("") def _calc_checksum(self, secret): # pragma: no cover """given secret; calcuate and return encoded checksum portion of hash string, taking config from object state calc checksum implementations may assume secret is always either unicode or bytes, checks are performed by verify/etc. """ raise NotImplementedError("%s must implement _calc_checksum()" % (self.__class__,)) #=================================================================== #'application' interface (default implementation) #=================================================================== @classmethod def hash(cls, secret, **kwds): if kwds: # Deprecating passing any settings keywords via .hash() as of passlib 1.7; everything # should use .using().hash() instead. If any keywords are specified, presume they're # context keywords by default (the common case), and extract out any settings kwds. # Support for passing settings via .hash() will be removed in Passlib 2.0, along with # this block of code. settings = extract_settings_kwds(cls, kwds) if settings: warn_hash_settings_deprecation(cls, settings) return cls.using(**settings).hash(secret, **kwds) # NOTE: at this point, 'kwds' should just contain context_kwds subset validate_secret(secret) self = cls(use_defaults=True, **kwds) self.checksum = self._calc_checksum(secret) return self.to_string() @classmethod def verify(cls, secret, hash, **context): # NOTE: classes with multiple checksum encodings should either # override this method, or ensure that from_string() / _norm_checksum() # ensures .checksum always uses a single canonical representation. validate_secret(secret) self = cls.from_string(hash, **context) chk = self.checksum if chk is None: raise exc.MissingDigestError(cls) return consteq(self._calc_checksum(secret), chk) #=================================================================== # legacy crypt interface #=================================================================== @deprecated_method(deprecated="1.7", removed="2.0") @classmethod def genconfig(cls, **kwds): # NOTE: 'kwds' should generally always be settings, so after this completes, *should* be empty. settings = extract_settings_kwds(cls, kwds) if settings: return cls.using(**settings).genconfig(**kwds) # NOTE: this uses optional stub checksum to bypass potentially expensive digest generation, # when caller just wants the config string. self = cls(use_defaults=True, **kwds) self.checksum = self._stub_checksum return self.to_string() @deprecated_method(deprecated="1.7", removed="2.0") @classmethod def genhash(cls, secret, config, **context): if config is None: raise TypeError("config must be string") validate_secret(secret) self = cls.from_string(config, **context) self.checksum = self._calc_checksum(secret) return self.to_string() #=================================================================== # migration interface (basde implementation) #=================================================================== @classmethod def needs_update(cls, hash, secret=None, **kwds): # NOTE: subclasses should generally just wrap _calc_needs_update() # to check their particular keywords. self = cls.from_string(hash) assert isinstance(self, cls) return self._calc_needs_update(secret=secret, **kwds) def _calc_needs_update(self, secret=None): """ internal helper for :meth:`needs_update`. """ # NOTE: this just provides a stub, subclasses & mixins # should override this with their own tests. return False #=================================================================== # experimental - the following methods are not finished or tested, # but way work correctly for some hashes #=================================================================== _unparsed_settings = ("salt_size", "relaxed") _unsafe_settings = ("salt", "checksum") @classproperty def _parsed_settings(cls): return (key for key in cls.setting_kwds if key not in cls._unparsed_settings) # XXX: make this a global function? @staticmethod def _sanitize(value, char=u("*")): """default method to obscure sensitive fields""" if value is None: return None if isinstance(value, bytes): from passlib.utils.binary import ab64_encode value = ab64_encode(value).decode("ascii") elif not isinstance(value, unicode): value = unicode(value) size = len(value) clip = min(4, size//8) return value[:clip] + char * (size-clip) @classmethod def parsehash(cls, hash, checksum=True, sanitize=False): """[experimental method] parse hash into dictionary of settings. this essentially acts as the inverse of :meth:`hash`: for most cases, if ``hash = cls.hash(secret, **opts)``, then ``cls.parsehash(hash)`` will return a dict matching the original options (with the extra keyword *checksum*). this method may not work correctly for all hashes, and may not be available on some few. its interface may change in future releases, if it's kept around at all. :arg hash: hash to parse :param checksum: include checksum keyword? (defaults to True) :param sanitize: mask data for sensitive fields? (defaults to False) """ # FIXME: this may not work for hashes with non-standard settings. # XXX: how should this handle checksum/salt encoding? # need to work that out for hash() anyways. self = cls.from_string(hash) # XXX: could split next few lines out as self._parsehash() for subclassing # XXX: could try to resolve ident/variant to publically suitable alias. UNSET = object() kwds = dict((key, getattr(self, key)) for key in self._parsed_settings if getattr(self, key) != getattr(cls, key, UNSET)) if checksum and self.checksum is not None: kwds['checksum'] = self.checksum if sanitize: if sanitize is True: sanitize = cls._sanitize for key in cls._unsafe_settings: if key in kwds: kwds[key] = sanitize(kwds[key]) return kwds @classmethod def bitsize(cls, **kwds): """[experimental method] return info about bitsizes of hash""" try: info = super(GenericHandler, cls).bitsize(**kwds) except AttributeError: info = {} cc = ALL_BYTE_VALUES if cls._checksum_is_bytes else cls.checksum_chars if cls.checksum_size and cc: # FIXME: this may overestimate size due to padding bits (e.g. bcrypt) # FIXME: this will be off by 1 for case-insensitive hashes. info['checksum'] = _bitsize(cls.checksum_size, cc) return info #=================================================================== # eoc #=================================================================== class StaticHandler(GenericHandler): """GenericHandler mixin for classes which have no settings. This mixin assumes the entirety of the hash ise stored in the :attr:`checksum` attribute; that the hash has no rounds, salt, etc. This class provides the following: * a default :meth:`genconfig` that always returns None. * a default :meth:`from_string` and :meth:`to_string` that store the entire hash within :attr:`checksum`, after optionally stripping a constant prefix. All that is required by subclasses is an implementation of the :meth:`_calc_checksum` method. """ # TODO: document _norm_hash() setting_kwds = () # optional constant prefix subclasses can specify _hash_prefix = u("") @classmethod def from_string(cls, hash, **context): # default from_string() which strips optional prefix, # and passes rest unchanged as checksum value. hash = to_unicode(hash, "ascii", "hash") hash = cls._norm_hash(hash) # could enable this for extra strictness ##pat = cls._hash_regex ##if pat and pat.match(hash) is None: ## raise ValueError("not a valid %s hash" % (cls.name,)) prefix = cls._hash_prefix if prefix: if hash.startswith(prefix): hash = hash[len(prefix):] else: raise exc.InvalidHashError(cls) return cls(checksum=hash, **context) @classmethod def _norm_hash(cls, hash): """helper for subclasses to normalize case if needed""" return hash def to_string(self): return uascii_to_str(self._hash_prefix + self.checksum) # per-subclass: stores dynamically created subclass used by _calc_checksum() stub __cc_compat_hack = None def _calc_checksum(self, secret): """given secret; calcuate and return encoded checksum portion of hash string, taking config from object state """ # NOTE: prior to 1.6, StaticHandler required classes implement genhash # instead of this method. so if we reach here, we try calling genhash. # if that succeeds, we issue deprecation warning. if it fails, # we'll just recurse back to here, but in a different instance. # so before we call genhash, we create a subclass which handles # throwing the NotImplementedError. cls = self.__class__ assert cls.__module__ != __name__ wrapper_cls = cls.__cc_compat_hack if wrapper_cls is None: def inner(self, secret): raise NotImplementedError("%s must implement _calc_checksum()" % (cls,)) wrapper_cls = cls.__cc_compat_hack = type(cls.__name__ + "_wrapper", (cls,), dict(_calc_checksum=inner, __module__=cls.__module__)) context = dict((k,getattr(self,k)) for k in self.context_kwds) # NOTE: passing 'config=None' here even though not currently allowed by ifc, # since it *is* allowed under the old 1.5 ifc we're checking for here. try: hash = wrapper_cls.genhash(secret, None, **context) except TypeError as err: if str(err) == "config must be string": raise NotImplementedError("%s must implement _calc_checksum()" % (cls,)) else: raise warn("%r should be updated to implement StaticHandler._calc_checksum() " "instead of StaticHandler.genhash(), support for the latter " "style will be removed in Passlib 1.8" % cls, DeprecationWarning) return str_to_uascii(hash) #============================================================================= # GenericHandler mixin classes #============================================================================= class HasEncodingContext(GenericHandler): """helper for classes which require knowledge of the encoding used""" context_kwds = ("encoding",) default_encoding = "utf-8" def __init__(self, encoding=None, **kwds): super(HasEncodingContext, self).__init__(**kwds) self.encoding = encoding or self.default_encoding class HasUserContext(GenericHandler): """helper for classes which require a user context keyword""" context_kwds = ("user",) def __init__(self, user=None, **kwds): super(HasUserContext, self).__init__(**kwds) self.user = user # XXX: would like to validate user input here, but calls to from_string() # which lack context keywords would then fail; so leaving code per-handler. # wrap funcs to accept 'user' as positional arg for ease of use. @classmethod def hash(cls, secret, user=None, **context): return super(HasUserContext, cls).hash(secret, user=user, **context) @classmethod def verify(cls, secret, hash, user=None, **context): return super(HasUserContext, cls).verify(secret, hash, user=user, **context) @deprecated_method(deprecated="1.7", removed="2.0") @classmethod def genhash(cls, secret, config, user=None, **context): return super(HasUserContext, cls).genhash(secret, config, user=user, **context) # XXX: how to guess the entropy of a username? # most of these hashes are for a system (e.g. Oracle) # which has a few *very common* names and thus really low entropy; # while the rest are slightly less predictable. # need to find good reference about this. ##@classmethod ##def bitsize(cls, **kwds): ## info = super(HasUserContext, cls).bitsize(**kwds) ## info['user'] = xxx ## return info #------------------------------------------------------------------------ # checksum mixins #------------------------------------------------------------------------ class HasRawChecksum(GenericHandler): """mixin for classes which work with decoded checksum bytes .. todo:: document this class's usage """ # NOTE: GenericHandler.checksum_chars is ignored by this implementation. # NOTE: all HasRawChecksum code is currently part of GenericHandler, # using private '_checksum_is_bytes' flag. # this arrangement may be changed in the future. _checksum_is_bytes = True #------------------------------------------------------------------------ # ident mixins #------------------------------------------------------------------------ class HasManyIdents(GenericHandler): """mixin for hashes which use multiple prefix identifiers For the hashes which may use multiple identifier prefixes, this mixin adds an ``ident`` keyword to constructor. Any value provided is passed through the :meth:`norm_idents` method, which takes care of validating the identifier, as well as allowing aliases for easier specification of the identifiers by the user. .. todo:: document this class's usage Class Methods ============= .. todo:: document using() and needs_update() options """ #=================================================================== # class attrs #=================================================================== default_ident = None # should be unicode ident_values = None # should be list of unicode strings ident_aliases = None # should be dict of unicode -> unicode # NOTE: any aliases provided to norm_ident() as bytes # will have been converted to unicode before # comparing against this dictionary. # NOTE: relying on test_06_HasManyIdents() to verify # these are configured correctly. #=================================================================== # instance attrs #=================================================================== ident = None #=================================================================== # variant constructor #=================================================================== @classmethod def using(cls, # keyword only... default_ident=None, ident=None, **kwds): """ This mixin adds support for the following :meth:`~passlib.ifc.PasswordHash.using` keywords: :param default_ident: default identifier that will be used by resulting customized hasher. :param ident: supported as alternate alias for **default_ident**. """ # resolve aliases if ident is not None: if default_ident is not None: raise TypeError("'default_ident' and 'ident' are mutually exclusive") default_ident = ident # create subclass subcls = super(HasManyIdents, cls).using(**kwds) # add custom default ident # (NOTE: creates instance to run value through _norm_ident()) if default_ident is not None: subcls.default_ident = cls(ident=default_ident, use_defaults=True).ident return subcls #=================================================================== # init #=================================================================== def __init__(self, ident=None, **kwds): super(HasManyIdents, self).__init__(**kwds) # init ident if ident is not None: ident = self._norm_ident(ident) elif self.use_defaults: ident = self.default_ident assert validate_default_value(self, ident, self._norm_ident, param="default_ident") else: raise TypeError("no ident specified") self.ident = ident @classmethod def _norm_ident(cls, ident): """ helper which normalizes & validates 'ident' value. """ # handle bytes assert ident is not None if isinstance(ident, bytes): ident = ident.decode('ascii') # check if identifier is valid iv = cls.ident_values if ident in iv: return ident # resolve aliases, and recheck against ident_values ia = cls.ident_aliases if ia: try: value = ia[ident] except KeyError: pass else: if value in iv: return value # failure! raise ValueError("invalid ident: %r" % (ident,)) #=================================================================== # password hash api #=================================================================== @classmethod def identify(cls, hash): hash = to_unicode_for_identify(hash) return hash.startswith(cls.ident_values) @classmethod def _parse_ident(cls, hash): """extract ident prefix from hash, helper for subclasses' from_string()""" hash = to_unicode(hash, "ascii", "hash") for ident in cls.ident_values: if hash.startswith(ident): return ident, hash[len(ident):] raise exc.InvalidHashError(cls) # XXX: implement a needs_update() helper that marks everything but default_ident as deprecated? #=================================================================== # eoc #=================================================================== #------------------------------------------------------------------------ # salt mixins #------------------------------------------------------------------------ class HasSalt(GenericHandler): """mixin for validating salts. This :class:`GenericHandler` mixin adds a ``salt`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_salt` method, which takes care of validating salt length and content, as well as generating new salts if one it not provided. :param salt: optional salt string :param salt_size: optional size of salt (only used if no salt provided); defaults to :attr:`default_salt_size`. Class Attributes ================ In order for :meth:`!_norm_salt` to do its job, the following attributes should be provided by the handler subclass: .. attribute:: min_salt_size The minimum number of characters allowed in a salt string. An :exc:`ValueError` will be throw if the provided salt is too small. Defaults to ``0``. .. attribute:: max_salt_size The maximum number of characters allowed in a salt string. By default an :exc:`ValueError` will be throw if the provided salt is too large; but if ``relaxed=True``, it will be clipped and a warning issued instead. Defaults to ``None``, for no maximum. .. attribute:: default_salt_size [required] If no salt is provided, this should specify the size of the salt that will be generated by :meth:`_generate_salt`. By default this will fall back to :attr:`max_salt_size`. .. attribute:: salt_chars A string containing all the characters which are allowed in the salt string. An :exc:`ValueError` will be throw if any other characters are encountered. May be set to ``None`` to skip this check (but see in :attr:`default_salt_chars`). .. attribute:: default_salt_chars [required] This attribute controls the set of characters use to generate *new* salt strings. By default, it mirrors :attr:`salt_chars`. If :attr:`!salt_chars` is ``None``, this attribute must be specified in order to generate new salts. Aside from that purpose, the main use of this attribute is for hashes which wish to generate salts from a restricted subset of :attr:`!salt_chars`; such as accepting all characters, but only using a-z. Instance Attributes =================== .. attribute:: salt This instance attribute will be filled in with the salt provided to the constructor (as adapted by :meth:`_norm_salt`) Subclassable Methods ==================== .. automethod:: _norm_salt .. automethod:: _generate_salt """ # TODO: document _truncate_salt() # XXX: allow providing raw salt to this class, and encoding it? #=================================================================== # class attrs #=================================================================== min_salt_size = 0 max_salt_size = None salt_chars = None @classproperty def default_salt_size(cls): """default salt size (defaults to *max_salt_size*)""" return cls.max_salt_size @classproperty def default_salt_chars(cls): """charset used to generate new salt strings (defaults to *salt_chars*)""" return cls.salt_chars # private helpers for HasRawSalt, shouldn't be used by subclasses _salt_is_bytes = False _salt_unit = "chars" # TODO: could support using(min/max_desired_salt_size) via using() and needs_update() #=================================================================== # instance attrs #=================================================================== salt = None #=================================================================== # variant constructor #=================================================================== @classmethod def using(cls, # keyword only... default_salt_size=None, salt_size=None, # aliases used by CryptContext salt=None, **kwds): # check for aliases used by CryptContext if salt_size is not None: if default_salt_size is not None: raise TypeError("'salt_size' and 'default_salt_size' aliases are mutually exclusive") default_salt_size = salt_size # generate new subclass subcls = super(HasSalt, cls).using(**kwds) # replace default_rounds relaxed = kwds.get("relaxed") if default_salt_size is not None: if isinstance(default_salt_size, native_string_types): default_salt_size = int(default_salt_size) subcls.default_salt_size = subcls._clip_to_valid_salt_size(default_salt_size, param="salt_size", relaxed=relaxed) # if salt specified, replace _generate_salt() with fixed output. # NOTE: this is mainly useful for testing / debugging. if salt is not None: salt = subcls._norm_salt(salt, relaxed=relaxed) subcls._generate_salt = staticmethod(lambda: salt) return subcls # XXX: would like to combine w/ _norm_salt() code below, but doesn't quite fit. @classmethod def _clip_to_valid_salt_size(cls, salt_size, param="salt_size", relaxed=True): """ internal helper -- clip salt size value to handler's absolute limits (min_salt_size / max_salt_size) :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :returns: clipped rounds value """ mn = cls.min_salt_size mx = cls.max_salt_size # check if salt size is fixed if mn == mx: if salt_size != mn: msg = "%s: %s (%d) must be exactly %d" % (cls.name, param, salt_size, mn) if relaxed: warn(msg, PasslibHashWarning) else: raise ValueError(msg) return mn # check min size if salt_size < mn: msg = "%s: %s (%r) below min_salt_size (%d)" % (cls.name, param, salt_size, mn) if relaxed: warn(msg, PasslibHashWarning) salt_size = mn else: raise ValueError(msg) # check max size if mx and salt_size > mx: msg = "%s: %s (%r) above max_salt_size (%d)" % (cls.name, param, salt_size, mx) if relaxed: warn(msg, PasslibHashWarning) salt_size = mx else: raise ValueError(msg) return salt_size #=================================================================== # init #=================================================================== def __init__(self, salt=None, **kwds): super(HasSalt, self).__init__(**kwds) if salt is not None: salt = self._parse_salt(salt) elif self.use_defaults: salt = self._generate_salt() assert self._norm_salt(salt) == salt, "generated invalid salt: %r" % (salt,) else: raise TypeError("no salt specified") self.salt = salt # NOTE: split out mainly so sha256_crypt can subclass this def _parse_salt(self, salt): return self._norm_salt(salt) @classmethod def _norm_salt(cls, salt, relaxed=False): """helper to normalize & validate user-provided salt string :arg salt: salt string :raises TypeError: If salt not correct type. :raises ValueError: * if salt contains chars that aren't in :attr:`salt_chars`. * if salt contains less than :attr:`min_salt_size` characters. * if ``relaxed=False`` and salt has more than :attr:`max_salt_size` characters (if ``relaxed=True``, the salt is truncated and a warning is issued instead). :returns: normalized salt """ # check type if cls._salt_is_bytes: if not isinstance(salt, bytes): raise exc.ExpectedTypeError(salt, "bytes", "salt") else: if not isinstance(salt, unicode): # NOTE: allowing bytes under py2 so salt can be native str. if isinstance(salt, bytes) and (PY2 or relaxed): salt = salt.decode("ascii") else: raise exc.ExpectedTypeError(salt, "unicode", "salt") # check charset sc = cls.salt_chars if sc is not None and any(c not in sc for c in salt): raise ValueError("invalid characters in %s salt" % cls.name) # check min size mn = cls.min_salt_size if mn and len(salt) < mn: msg = "salt too small (%s requires %s %d %s)" % (cls.name, "exactly" if mn == cls.max_salt_size else ">=", mn, cls._salt_unit) raise ValueError(msg) # check max size mx = cls.max_salt_size if mx and len(salt) > mx: msg = "salt too large (%s requires %s %d %s)" % (cls.name, "exactly" if mx == mn else "<=", mx, cls._salt_unit) if relaxed: warn(msg, PasslibHashWarning) salt = cls._truncate_salt(salt, mx) else: raise ValueError(msg) return salt @staticmethod def _truncate_salt(salt, mx): # NOTE: some hashes (e.g. bcrypt) has structure within their # salt string. this provides a method to override to perform # the truncation properly return salt[:mx] @classmethod def _generate_salt(cls): """ helper method for _init_salt(); generates a new random salt string. """ return getrandstr(rng, cls.default_salt_chars, cls.default_salt_size) @classmethod def bitsize(cls, salt_size=None, **kwds): """[experimental method] return info about bitsizes of hash""" info = super(HasSalt, cls).bitsize(**kwds) if salt_size is None: salt_size = cls.default_salt_size # FIXME: this may overestimate size due to padding bits # FIXME: this will be off by 1 for case-insensitive hashes. info['salt'] = _bitsize(salt_size, cls.default_salt_chars) return info #=================================================================== # eoc #=================================================================== class HasRawSalt(HasSalt): """mixin for classes which use decoded salt parameter A variant of :class:`!HasSalt` which takes in decoded bytes instead of an encoded string. .. todo:: document this class's usage """ salt_chars = ALL_BYTE_VALUES # NOTE: all HasRawSalt code is currently part of HasSalt, using private # '_salt_is_bytes' flag. this arrangement may be changed in the future. _salt_is_bytes = True _salt_unit = "bytes" @classmethod def _generate_salt(cls): assert cls.salt_chars in [None, ALL_BYTE_VALUES] return getrandbytes(rng, cls.default_salt_size) #------------------------------------------------------------------------ # rounds mixin #------------------------------------------------------------------------ class HasRounds(GenericHandler): """mixin for validating rounds parameter This :class:`GenericHandler` mixin adds a ``rounds`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_rounds` method, which takes care of validating the number of rounds. :param rounds: optional number of rounds hash should use Class Attributes ================ In order for :meth:`!_norm_rounds` to do its job, the following attributes must be provided by the handler subclass: .. attribute:: min_rounds The minimum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is too small. Defaults to ``0``. .. attribute:: max_rounds The maximum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is larger than this. Defaults to ``None`` which indicates no limit to the rounds value. .. attribute:: default_rounds If no rounds value is provided to constructor, this value will be used. If this is not specified, a rounds value *must* be specified by the application. .. attribute:: rounds_cost [required] The ``rounds`` parameter typically encodes a cpu-time cost for calculating a hash. This should be set to ``"linear"`` (the default) or ``"log2"``, depending on how the rounds value relates to the actual amount of time that will be required. Class Methods ============= .. todo:: document using() and needs_update() options Instance Attributes =================== .. attribute:: rounds This instance attribute will be filled in with the rounds value provided to the constructor (as adapted by :meth:`_norm_rounds`) Subclassable Methods ==================== .. automethod:: _norm_rounds """ #=================================================================== # class attrs #=================================================================== #----------------- # algorithm options -- not application configurable #----------------- # XXX: rename to min_valid_rounds / max_valid_rounds, # to clarify role compared to min_desired_rounds / max_desired_rounds? min_rounds = 0 max_rounds = None rounds_cost = "linear" # default to the common case # hack to pass info to _CryptRecord (will be removed in passlib 2.0) using_rounds_kwds = ("min_desired_rounds", "max_desired_rounds", "min_rounds", "max_rounds", "default_rounds", "vary_rounds") #----------------- # desired & default rounds -- configurable via .using() classmethod #----------------- min_desired_rounds = None max_desired_rounds = None default_rounds = None vary_rounds = None #=================================================================== # instance attrs #=================================================================== rounds = None #=================================================================== # variant constructor #=================================================================== @classmethod def using(cls, # keyword only... min_desired_rounds=None, max_desired_rounds=None, default_rounds=None, vary_rounds=None, min_rounds=None, max_rounds=None, rounds=None, # aliases used by CryptContext **kwds): # check for aliases used by CryptContext if min_rounds is not None: if min_desired_rounds is not None: raise TypeError("'min_rounds' and 'min_desired_rounds' aliases are mutually exclusive") min_desired_rounds = min_rounds if max_rounds is not None: if max_desired_rounds is not None: raise TypeError("'max_rounds' and 'max_desired_rounds' aliases are mutually exclusive") max_desired_rounds = max_rounds # use 'rounds' as fallback for min, max, AND default # XXX: would it be better to make 'default_rounds' and 'rounds' # aliases, and have a separate 'require_rounds' parameter for this behavior? if rounds is not None: if min_desired_rounds is None: min_desired_rounds = rounds if max_desired_rounds is None: max_desired_rounds = rounds if default_rounds is None: default_rounds = rounds # generate new subclass subcls = super(HasRounds, cls).using(**kwds) # replace min_desired_rounds relaxed = kwds.get("relaxed") if min_desired_rounds is None: explicit_min_rounds = False min_desired_rounds = cls.min_desired_rounds else: explicit_min_rounds = True if isinstance(min_desired_rounds, native_string_types): min_desired_rounds = int(min_desired_rounds) subcls.min_desired_rounds = subcls._norm_rounds(min_desired_rounds, param="min_desired_rounds", relaxed=relaxed) # replace max_desired_rounds if max_desired_rounds is None: max_desired_rounds = cls.max_desired_rounds else: if isinstance(max_desired_rounds, native_string_types): max_desired_rounds = int(max_desired_rounds) if min_desired_rounds and max_desired_rounds < min_desired_rounds: msg = "%s: max_desired_rounds (%r) below min_desired_rounds (%r)" % \ (subcls.name, max_desired_rounds, min_desired_rounds) if explicit_min_rounds: raise ValueError(msg) else: warn(msg, PasslibConfigWarning) max_desired_rounds = min_desired_rounds subcls.max_desired_rounds = subcls._norm_rounds(max_desired_rounds, param="max_desired_rounds", relaxed=relaxed) # replace default_rounds if default_rounds is not None: if isinstance(default_rounds, native_string_types): default_rounds = int(default_rounds) if min_desired_rounds and default_rounds < min_desired_rounds: raise ValueError("%s: default_rounds (%r) below min_desired_rounds (%r)" % (subcls.name, default_rounds, min_desired_rounds)) elif max_desired_rounds and default_rounds > max_desired_rounds: raise ValueError("%s: default_rounds (%r) above max_desired_rounds (%r)" % (subcls.name, default_rounds, max_desired_rounds)) subcls.default_rounds = subcls._norm_rounds(default_rounds, param="default_rounds", relaxed=relaxed) # clip default rounds to new limits. if subcls.default_rounds is not None: subcls.default_rounds = subcls._clip_to_desired_rounds(subcls.default_rounds) # replace / set vary_rounds if vary_rounds is not None: if isinstance(vary_rounds, native_string_types): if vary_rounds.endswith("%"): vary_rounds = float(vary_rounds[:-1]) * 0.01 elif "." in vary_rounds: vary_rounds = float(vary_rounds) else: vary_rounds = int(vary_rounds) if vary_rounds < 0: raise ValueError("%s: vary_rounds (%r) below 0" % (subcls.name, vary_rounds)) elif isinstance(vary_rounds, float): # TODO: deprecate / disallow vary_rounds=1.0 if vary_rounds > 1: raise ValueError("%s: vary_rounds (%r) above 1.0" % (subcls.name, vary_rounds)) elif not isinstance(vary_rounds, int): raise TypeError("vary_rounds must be int or float") if vary_rounds: warn("The 'vary_rounds' option is deprecated as of Passlib 1.7, " "and will be removed in Passlib 2.0", PasslibConfigWarning) subcls.vary_rounds = vary_rounds # XXX: could cache _calc_vary_rounds_range() here if needed, # but would need to handle user manually changing .default_rounds return subcls @classmethod def _clip_to_desired_rounds(cls, rounds): """ helper for :meth:`_generate_rounds` -- clips rounds value to desired min/max set by class (if any) """ # NOTE: min/max_desired_rounds are None if unset. # check minimum mnd = cls.min_desired_rounds or 0 if rounds < mnd: return mnd # check maximum mxd = cls.max_desired_rounds if mxd and rounds > mxd: return mxd return rounds @classmethod def _calc_vary_rounds_range(cls, default_rounds): """ helper for :meth:`_generate_rounds` -- returns range for vary rounds generation. :returns: (lower, upper) limits suitable for random.randint() """ # XXX: could precalculate output of this in using() method, and save per-hash cost. # but then users patching cls.vary_rounds / cls.default_rounds would get wrong value. assert default_rounds vary_rounds = cls.vary_rounds # if vary_rounds specified as % of default, convert it to actual rounds def linear_to_native(value, upper): return value if isinstance(vary_rounds, float): assert 0 <= vary_rounds <= 1 # TODO: deprecate vary_rounds==1 if cls.rounds_cost == "log2": # special case -- have to convert default_rounds to linear scale, # apply +/- vary_rounds to that, and convert back to log scale again. # linear_to_native() takes care of the "convert back" step. default_rounds = 1 << default_rounds def linear_to_native(value, upper): if value <= 0: # log() undefined for <= 0 return 0 elif upper: # use smallest upper bound for start of range return int(math.log(value, 2)) else: # use greatest lower bound for end of range return int(math.ceil(math.log(value, 2))) # calculate integer vary rounds based on current default_rounds vary_rounds = int(default_rounds * vary_rounds) # calculate bounds based on default_rounds +/- vary_rounds assert vary_rounds >= 0 and isinstance(vary_rounds, int_types) lower = linear_to_native(default_rounds - vary_rounds, False) upper = linear_to_native(default_rounds + vary_rounds, True) return cls._clip_to_desired_rounds(lower), cls._clip_to_desired_rounds(upper) #=================================================================== # init #=================================================================== def __init__(self, rounds=None, **kwds): super(HasRounds, self).__init__(**kwds) if rounds is not None: rounds = self._parse_rounds(rounds) elif self.use_defaults: rounds = self._generate_rounds() assert self._norm_rounds(rounds) == rounds, "generated invalid rounds: %r" % (rounds,) else: raise TypeError("no rounds specified") self.rounds = rounds # NOTE: split out mainly so sha256_crypt & bsdi_crypt can subclass this def _parse_rounds(self, rounds): return self._norm_rounds(rounds) @classmethod def _norm_rounds(cls, rounds, relaxed=False, param="rounds"): """ helper for normalizing rounds value. :arg rounds: an integer cost parameter. :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :raises TypeError: * if ``use_defaults=False`` and no rounds is specified * if rounds is not an integer. :raises ValueError: * if rounds is ``None`` and class does not specify a value for :attr:`default_rounds`. * if ``relaxed=False`` and rounds is outside bounds of :attr:`min_rounds` and :attr:`max_rounds` (if ``relaxed=True``, the rounds value will be clamped, and a warning issued). :returns: normalized rounds value """ return norm_integer(cls, rounds, cls.min_rounds, cls.max_rounds, param=param, relaxed=relaxed) @classmethod def _generate_rounds(cls): """ internal helper for :meth:`_norm_rounds` -- returns default rounds value, incorporating vary_rounds, and any other limitations hash may place on rounds parameter. """ # load default rounds rounds = cls.default_rounds if rounds is None: raise TypeError("%s rounds value must be specified explicitly" % (cls.name,)) # randomly vary the rounds slightly basic on vary_rounds parameter. # reads default_rounds internally. if cls.vary_rounds: lower, upper = cls._calc_vary_rounds_range(rounds) assert lower <= rounds <= upper if lower < upper: rounds = rng.randint(lower, upper) return rounds #=================================================================== # migration interface #=================================================================== def _calc_needs_update(self, **kwds): """ mark hash as needing update if rounds is outside desired bounds. """ min_desired_rounds = self.min_desired_rounds if min_desired_rounds and self.rounds < min_desired_rounds: return True max_desired_rounds = self.max_desired_rounds if max_desired_rounds and self.rounds > max_desired_rounds: return True return super(HasRounds, self)._calc_needs_update(**kwds) #=================================================================== # experimental methods #=================================================================== @classmethod def bitsize(cls, rounds=None, vary_rounds=.1, **kwds): """[experimental method] return info about bitsizes of hash""" info = super(HasRounds, cls).bitsize(**kwds) # NOTE: this essentially estimates how many bits of "salt" # can be added by varying the rounds value just a little bit. if cls.rounds_cost != "log2": # assume rounds can be randomized within the range # rounds*(1-vary_rounds) ... rounds*(1+vary_rounds) # then this can be used to encode # log2(rounds*(1+vary_rounds)-rounds*(1-vary_rounds)) # worth of salt-like bits. this works out to # 1+log2(rounds*vary_rounds) import math if rounds is None: rounds = cls.default_rounds info['rounds'] = max(0, int(1+math.log(rounds*vary_rounds,2))) ## else: # log2 rounds # all bits of the rounds value are critical to choosing # the time-cost, and can't be randomized. return info #=================================================================== # eoc #=================================================================== #------------------------------------------------------------------------ # other common parameters #------------------------------------------------------------------------ class ParallelismMixin(GenericHandler): """ mixin which provides common behavior for 'parallelism' setting """ #=================================================================== # class attrs #=================================================================== # NOTE: subclasses should add "parallelism" to their settings_kwds #=================================================================== # instance attrs #=================================================================== #: parallelism setting (class-level value used as default) parallelism = 1 #=================================================================== # variant constructor #=================================================================== @classmethod def using(cls, parallelism=None, **kwds): subcls = super(ParallelismMixin, cls).using(**kwds) if parallelism is not None: if isinstance(parallelism, native_string_types): parallelism = int(parallelism) subcls.parallelism = subcls._norm_parallelism(parallelism, relaxed=kwds.get("relaxed")) return subcls #=================================================================== # init #=================================================================== def __init__(self, parallelism=None, **kwds): super(ParallelismMixin, self).__init__(**kwds) # init parallelism if parallelism is None: assert validate_default_value(self, self.parallelism, self._norm_parallelism, param="parallelism") else: self.parallelism = self._norm_parallelism(parallelism) @classmethod def _norm_parallelism(cls, parallelism, relaxed=False): return norm_integer(cls, parallelism, min=1, param="parallelism", relaxed=relaxed) #=================================================================== # hash migration #=================================================================== def _calc_needs_update(self, **kwds): """ mark hash as needing update if rounds is outside desired bounds. """ # XXX: for now, marking all hashes which don't have matching parallelism setting if self.parallelism != type(self).parallelism: return True return super(ParallelismMixin, self)._calc_needs_update(**kwds) #=================================================================== # eoc #=================================================================== #------------------------------------------------------------------------ # backend mixin & helpers #------------------------------------------------------------------------ #: global lock that must be held when changing backends. #: not bothering to make this more granular, as backend switching #: isn't a speed-critical path. lock is needed since there is some #: class-level state that may be modified during a "dry run" _backend_lock = threading.RLock() class BackendMixin(PasswordHash): """ PasswordHash mixin which provides generic framework for supporting multiple backends within the class. Public API ---------- .. attribute:: backends This attribute should be a tuple containing the names of the backends which are supported. Two common names are ``"os_crypt"`` (if backend uses :mod:`crypt`), and ``"builtin"`` (if the backend is a pure-python fallback). .. automethod:: get_backend .. automethod:: set_backend .. automethod:: has_backend .. warning:: :meth:`set_backend` is intended to be called during application startup -- it affects global state, and switching backends is not guaranteed threadsafe. Private API (Subclass Hooks) ---------------------------- Subclasses should set the :attr:`!backends` attribute to a tuple of the backends they wish to support. They should also define one method: .. classmethod:: _load_backend_{name}(dryrun=False) One copy of this method should be defined for each :samp:`name` within :attr:`!backends`. It will be called in order to load the backend, and should take care of whatever is needed to enable the backend. This may include importing modules, running tests, issuing warnings, etc. :param name: [Optional] name of backend. :param dryrun: [Optional] True/False if currently performing a "dry run". if True, the method should perform all setup actions *except* switching the class over to the new backend. :raises passlib.exc.PasslibSecurityError: if the backend is available, but cannot be loaded due to a security issue. :returns: False if backend not available, True if backend loaded. .. warning:: Due to the way passlib's internals are arranged, backends should generally store stateful data at the class level (not the module level), and be prepared to be called on subclasses which may be set to a different backend from their parent. (Idempotent module-level data such as lazy imports are fine). .. automethod:: _finalize_backend .. versionadded:: 1.7 """ #=================================================================== # class attrs #=================================================================== #: list of backend names, provided by subclass. backends = None #: private attr mixin uses to hold currently loaded backend (or ``None``) __backend = None #: optional class-specific text containing suggestion about what to do #: when no backends are available. _no_backend_suggestion = None #: shared attr used by set_backend() to indicate what backend it's loaded; #: meaningless while not in set_backend(). _pending_backend = None #: shared attr used by set_backend() to indicate if it's in "dry run" mode; #: meaningless while not in set_backend(). _pending_dry_run = False #=================================================================== # public api #=================================================================== @classmethod def get_backend(cls): """ Return name of currently active backend. if no backend has been loaded, loads and returns name of default backend. :raises passlib.exc.MissingBackendError: if no backends are available. :returns: name of active backend """ if not cls.__backend: cls.set_backend() assert cls.__backend, "set_backend() failed to load a default backend" return cls.__backend @classmethod def has_backend(cls, name="any"): """ Check if support is currently available for specified backend. :arg name: name of backend to check for. can be any string accepted by :meth:`set_backend`. :raises ValueError: if backend name is unknown :returns: * ``True`` if backend is available. * ``False`` if it's available / can't be loaded. * ``None`` if it's present, but won't load due to a security issue. """ try: cls.set_backend(name, dryrun=True) return True except (exc.MissingBackendError, exc.PasslibSecurityError): return False @classmethod def set_backend(cls, name="any", dryrun=False): """ Load specified backend. :arg name: name of backend to load, can be any of the following: * ``"any"`` -- use current backend if one is loaded, otherwise load the first available backend. * ``"default"`` -- use the first available backend. * any string in :attr:`backends`, loads specified backend. :param dryrun: If True, this perform all setup actions *except* switching over to the new backend. (this flag is used to implement :meth:`has_backend`). .. versionadded:: 1.7 :raises ValueError: If backend name is unknown. :raises passlib.exc.MissingBackendError: If specific backend is missing; or in the case of ``"any"`` / ``"default"``, if *no* backends are available. :raises passlib.exc.PasslibSecurityError: If ``"any"`` or ``"default"`` was specified, but the only backend available has a PasslibSecurityError. """ # check if active backend is acceptable if (name == "any" and cls.__backend) or (name and name == cls.__backend): return cls.__backend # if this isn't the final subclass, whose bases we can modify, # find that class, and recursively call this method for the proper class. owner = cls._get_backend_owner() if owner is not cls: return owner.set_backend(name, dryrun=dryrun) # pick first available backend if name == "any" or name == "default": default_error = None for name in cls.backends: try: return cls.set_backend(name, dryrun=dryrun) except exc.MissingBackendError: continue except exc.PasslibSecurityError as err: # backend is available, but refuses to load due to security issue. if default_error is None: default_error = err continue if default_error is None: msg = "%s: no backends available" % cls.name if cls._no_backend_suggestion: msg += cls._no_backend_suggestion default_error = exc.MissingBackendError(msg) raise default_error # validate name if name not in cls.backends: raise exc.UnknownBackendError(cls, name) # hand off to _set_backend() with _backend_lock: orig = cls._pending_backend, cls._pending_dry_run try: cls._pending_backend = name cls._pending_dry_run = dryrun cls._set_backend(name, dryrun) finally: cls._pending_backend, cls._pending_dry_run = orig if not dryrun: cls.__backend = name return name #=================================================================== # subclass hooks #=================================================================== @classmethod def _get_backend_owner(cls): """ return class that set_backend() should actually be modifying. for SubclassBackendMixin, this may not always be the class that was invoked. """ return cls @classmethod def _set_backend(cls, name, dryrun): """ Internal method invoked by :meth:`set_backend`. handles actual loading of specified backend. global _backend_lock will be held for duration of this method, and _pending_dry_run & _pending_backend will also be set. should return True / False. """ loader = cls._get_backend_loader(name) kwds = {} if accepts_keyword(loader, "name"): kwds['name'] = name if accepts_keyword(loader, "dryrun"): kwds['dryrun'] = dryrun ok = loader(**kwds) if ok is False: raise exc.MissingBackendError("%s: backend not available: %s" % (cls.name, name)) elif ok is not True: raise AssertionError("backend loaders must return True or False" ": %r" % (ok,)) @classmethod def _get_backend_loader(cls, name): """ Hook called to get the specified backend's loader. Should return callable which optionally takes ``"name"`` and/or ``"dryrun"`` keywords. Callable should return True if backend initialized successfully. If backend can't be loaded, callable should return False OR raise MissingBackendError directly. """ raise NotImplementedError("implement in subclass") @classmethod def _stub_requires_backend(cls): """ helper for subclasses to create stub methods which auto-load backend. """ if cls.__backend: raise AssertionError("%s: _finalize_backend(%r) failed to replace lazy loader" % (cls.name, cls.__backend)) cls.set_backend() if not cls.__backend: raise AssertionError("%s: set_backend() failed to load a default backend" % (cls.name)) #=================================================================== # eoc #=================================================================== class SubclassBackendMixin(BackendMixin): """ variant of BackendMixin which allows backends to be implemented as separate mixin classes, and dynamically switches them out. backend classes should implement a _load_backend() classmethod, which will be invoked with an optional 'dryrun' keyword, and should return True or False. _load_backend() will be invoked with ``cls`` equal to the mixin, *not* the overall class. .. versionadded:: 1.7 """ #=================================================================== # class attrs #=================================================================== # 'backends' required by BackendMixin #: NON-INHERITED flag that this class's bases should be modified by SubclassBackendMixin. #: should only be set to True in *one* subclass in hierarchy. _backend_mixin_target = False #: map of backend name -> mixin class _backend_mixin_map = None #=================================================================== # backend loading #=================================================================== @classmethod def _get_backend_owner(cls): """ return base class that we're actually switching backends on (needed in since backends frequently modify class attrs, and .set_backend may be called from a subclass). """ if not cls._backend_mixin_target: raise AssertionError("_backend_mixin_target not set") for base in cls.__mro__: if base.__dict__.get("_backend_mixin_target"): return base raise AssertionError("expected to find class w/ '_backend_mixin_target' set") @classmethod def _set_backend(cls, name, dryrun): # invoke backend loader (will throw error if fails) super(SubclassBackendMixin, cls)._set_backend(name, dryrun) # sanity check call args (should trust .set_backend, but will really # foul things up if this isn't the owner) assert cls is cls._get_backend_owner(), "_finalize_backend() not invoked on owner" # pick mixin class mixin_map = cls._backend_mixin_map assert mixin_map, "_backend_mixin_map not specified" mixin_cls = mixin_map[name] assert issubclass(mixin_cls, SubclassBackendMixin), "invalid mixin class" # modify to remove existing backend mixins, and insert the new one update_mixin_classes(cls, add=mixin_cls, remove=mixin_map.values(), append=True, before=SubclassBackendMixin, dryrun=dryrun, ) @classmethod def _get_backend_loader(cls, name): assert cls._backend_mixin_map, "_backend_mixin_map not specified" return cls._backend_mixin_map[name]._load_backend_mixin #=================================================================== # eoc #=================================================================== # XXX: rename to ChecksumBackendMixin? class HasManyBackends(BackendMixin, GenericHandler): """ GenericHandler mixin which provides selecting from multiple backends. .. todo:: finish documenting this class's usage For hashes which need to select from multiple backends, depending on the host environment, this class offers a way to specify alternate :meth:`_calc_checksum` methods, and will dynamically chose the best one at runtime. .. versionchanged:: 1.7 This class now derives from :class:`BackendMixin`, which abstracts out a more generic framework for supporting multiple backends. The public api (:meth:`!get_backend`, :meth:`!has_backend`, :meth:`!set_backend`) is roughly the same. Private API (Subclass Hooks) ---------------------------- As of version 1.7, classes should implement :meth:`!_load_backend_{name}`, per :class:`BackendMixin`. This hook should invoke :meth:`!_set_calc_checksum_backcend` to install it's backend method. .. deprecated:: 1.7 The following api is deprecated, and will be removed in Passlib 2.0: .. attribute:: _has_backend_{name} private class attribute checked by :meth:`has_backend` to see if a specific backend is available, it should be either ``True`` or ``False``. One of these should be provided by the subclass for each backend listed in :attr:`backends`. .. classmethod:: _calc_checksum_{name} private class method that should implement :meth:`_calc_checksum` for a given backend. it will only be called if the backend has been selected by :meth:`set_backend`. One of these should be provided by the subclass for each backend listed in :attr:`backends`. """ #=================================================================== # digest calculation #=================================================================== def _calc_checksum(self, secret): "wrapper for backend, for common code""" # NOTE: not overwriting _calc_checksum() directly, so that classes can provide # common behavior in that method, # and then invoke _calc_checksum_backend() to do the work. return self._calc_checksum_backend(secret) def _calc_checksum_backend(self, secret): """ stub for _calc_checksum_backend() -- should load backend if one hasn't been loaded; if one has been loaded, this method should have been monkeypatched by _finalize_backend(). """ self._stub_requires_backend() return self._calc_checksum_backend(secret) #=================================================================== # BackendMixin hooks #=================================================================== @classmethod def _get_backend_loader(cls, name): """ subclassed to support legacy 1.6 HasManyBackends api. (will be removed in passlib 2.0) """ # check for 1.7 loader loader = getattr(cls, "_load_backend_" + name, None) if loader is None: # fallback to pre-1.7 _has_backend_xxx + _calc_checksum_xxx() api def loader(): return cls.__load_legacy_backend(name) else: # make sure 1.6 api isn't defined at same time assert not hasattr(cls, "_has_backend_" + name), ( "%s: can't specify both ._load_backend_%s() " "and ._has_backend_%s" % (cls.name, name, name) ) return loader @classmethod def __load_legacy_backend(cls, name): value = getattr(cls, "_has_backend_" + name) warn("%s: support for ._has_backend_%s is deprecated as of Passlib 1.7, " "and will be removed in Passlib 1.9/2.0, please implement " "._load_backend_%s() instead" % (cls.name, name, name), DeprecationWarning, ) if value: func = getattr(cls, "_calc_checksum_" + name) cls._set_calc_checksum_backend(func) return True else: return False @classmethod def _set_calc_checksum_backend(cls, func): """ helper used by subclasses to validate & set backend-specific calc checksum helper. """ backend = cls._pending_backend assert backend, "should only be called during set_backend()" if not callable(func): raise RuntimeError("%s: backend %r returned invalid callable: %r" % (cls.name, backend, func)) if not cls._pending_dry_run: cls._calc_checksum_backend = func #=================================================================== # eoc #=================================================================== #============================================================================= # wrappers #============================================================================= # XXX: should this inherit from PasswordHash? class PrefixWrapper(object): """wraps another handler, adding a constant prefix. instances of this class wrap another password hash handler, altering the constant prefix that's prepended to the wrapped handlers' hashes. this is used mainly by the :doc:`ldap crypt ` handlers; such as :class:`~passlib.hash.ldap_md5_crypt` which wraps :class:`~passlib.hash.md5_crypt` and adds a ``{CRYPT}`` prefix. usage:: myhandler = PrefixWrapper("myhandler", "md5_crypt", prefix="$mh$", orig_prefix="$1$") :param name: name to assign to handler :param wrapped: handler object or name of registered handler :param prefix: identifying prefix to prepend to all hashes :param orig_prefix: prefix to strip (defaults to ''). :param lazy: if True and wrapped handler is specified by name, don't look it up until needed. """ #: list of attributes which should be cloned by .using() _using_clone_attrs = () def __init__(self, name, wrapped, prefix=u(''), orig_prefix=u(''), lazy=False, doc=None, ident=None): self.name = name if isinstance(prefix, bytes): prefix = prefix.decode("ascii") self.prefix = prefix if isinstance(orig_prefix, bytes): orig_prefix = orig_prefix.decode("ascii") self.orig_prefix = orig_prefix if doc: self.__doc__ = doc if hasattr(wrapped, "name"): self._set_wrapped(wrapped) else: self._wrapped_name = wrapped if not lazy: self._get_wrapped() if ident is not None: if ident is True: # signal that prefix is identifiable in itself. if prefix: ident = prefix else: raise ValueError("no prefix specified") if isinstance(ident, bytes): ident = ident.decode("ascii") # XXX: what if ident includes parts of wrapped hash's ident? if ident[:len(prefix)] != prefix[:len(ident)]: raise ValueError("ident must agree with prefix") self._ident = ident _wrapped_name = None _wrapped_handler = None def _set_wrapped(self, handler): # check this is a valid handler if 'ident' in handler.setting_kwds and self.orig_prefix: # TODO: look into way to fix the issues. warn("PrefixWrapper: 'orig_prefix' option may not work correctly " "for handlers which have multiple identifiers: %r" % (handler.name,), exc.PasslibRuntimeWarning) # store reference self._wrapped_handler = handler def _get_wrapped(self): handler = self._wrapped_handler if handler is None: handler = get_crypt_handler(self._wrapped_name) self._set_wrapped(handler) return handler wrapped = property(_get_wrapped) _ident = False @property def ident(self): value = self._ident if value is False: value = None # XXX: how will this interact with orig_prefix ? # not exposing attrs for now if orig_prefix is set. if not self.orig_prefix: wrapped = self.wrapped ident = getattr(wrapped, "ident", None) if ident is not None: value = self._wrap_hash(ident) self._ident = value return value _ident_values = False @property def ident_values(self): value = self._ident_values if value is False: value = None # XXX: how will this interact with orig_prefix ? # not exposing attrs for now if orig_prefix is set. if not self.orig_prefix: wrapped = self.wrapped idents = getattr(wrapped, "ident_values", None) if idents: value = tuple(self._wrap_hash(ident) for ident in idents) ##else: ## ident = self.ident ## if ident is not None: ## value = [ident] self._ident_values = value return value # attrs that should be proxied # XXX: change this to proxy everything that doesn't start with "_"? _proxy_attrs = ( "setting_kwds", "context_kwds", "default_rounds", "min_rounds", "max_rounds", "rounds_cost", "min_desired_rounds", "max_desired_rounds", "vary_rounds", "default_salt_size", "min_salt_size", "max_salt_size", "salt_chars", "default_salt_chars", "backends", "has_backend", "get_backend", "set_backend", "is_disabled", "truncate_size", "truncate_error", "truncate_verify_reject", # internal info attrs needed for test inspection "_salt_is_bytes", ) def __repr__(self): args = [ repr(self._wrapped_name or self._wrapped_handler) ] if self.prefix: args.append("prefix=%r" % self.prefix) if self.orig_prefix: args.append("orig_prefix=%r" % self.orig_prefix) args = ", ".join(args) return 'PrefixWrapper(%r, %s)' % (self.name, args) def __dir__(self): attrs = set(dir(self.__class__)) attrs.update(self.__dict__) wrapped = self.wrapped attrs.update( attr for attr in self._proxy_attrs if hasattr(wrapped, attr) ) return list(attrs) def __getattr__(self, attr): """proxy most attributes from wrapped class (e.g. rounds, salt size, etc)""" if attr in self._proxy_attrs: return getattr(self.wrapped, attr) raise AttributeError("missing attribute: %r" % (attr,)) def __setattr__(self, attr, value): # if proxy attr present on wrapped object, # and we own it, modify *it* instead. # TODO: needs UTs # TODO: any other cases where wrapped is "owned"? # currently just if created via .using() if attr in self._proxy_attrs and self._derived_from: wrapped = self.wrapped if hasattr(wrapped, attr): setattr(wrapped, attr, value) return return object.__setattr__(self, attr, value) def _unwrap_hash(self, hash): """given hash belonging to wrapper, return orig version""" # NOTE: assumes hash has been validated as unicode already prefix = self.prefix if not hash.startswith(prefix): raise exc.InvalidHashError(self) # NOTE: always passing to handler as unicode, to save reconversion return self.orig_prefix + hash[len(prefix):] def _wrap_hash(self, hash): """given orig hash; return one belonging to wrapper""" # NOTE: should usually be native string. # (which does mean extra work under py2, but not py3) if isinstance(hash, bytes): hash = hash.decode("ascii") orig_prefix = self.orig_prefix if not hash.startswith(orig_prefix): raise exc.InvalidHashError(self.wrapped) wrapped = self.prefix + hash[len(orig_prefix):] return uascii_to_str(wrapped) #: set by _using(), helper for test harness' handler_derived_from() _derived_from = None def using(self, **kwds): # generate subclass of wrapped handler subcls = self.wrapped.using(**kwds) assert subcls is not self.wrapped # then create identical wrapper which wraps the new subclass. wrapper = PrefixWrapper(self.name, subcls, prefix=self.prefix, orig_prefix=self.orig_prefix) wrapper._derived_from = self for attr in self._using_clone_attrs: setattr(wrapper, attr, getattr(self, attr)) return wrapper def needs_update(self, hash, **kwds): hash = self._unwrap_hash(hash) return self.wrapped.needs_update(hash, **kwds) def identify(self, hash): hash = to_unicode_for_identify(hash) if not hash.startswith(self.prefix): return False hash = self._unwrap_hash(hash) return self.wrapped.identify(hash) @deprecated_method(deprecated="1.7", removed="2.0") def genconfig(self, **kwds): config = self.wrapped.genconfig(**kwds) if config is None: raise RuntimeError(".genconfig() must return a string, not None") return self._wrap_hash(config) @deprecated_method(deprecated="1.7", removed="2.0") def genhash(self, secret, config, **kwds): # TODO: under 2.0, throw TypeError if config is None, rather than passing it through if config is not None: config = to_unicode(config, "ascii", "config/hash") config = self._unwrap_hash(config) return self._wrap_hash(self.wrapped.genhash(secret, config, **kwds)) @deprecated_method(deprecated="1.7", removed="2.0", replacement=".hash()") def encrypt(self, secret, **kwds): return self.hash(secret, **kwds) def hash(self, secret, **kwds): return self._wrap_hash(self.wrapped.hash(secret, **kwds)) def verify(self, secret, hash, **kwds): hash = to_unicode(hash, "ascii", "hash") hash = self._unwrap_hash(hash) return self.wrapped.verify(secret, hash, **kwds) #============================================================================= # eof #============================================================================= binary.py000064400000075276147221702050006423 0ustar00""" passlib.utils.binary - binary data encoding/decoding/manipulation """ #============================================================================= # imports #============================================================================= # core from __future__ import absolute_import, division, print_function from base64 import ( b64encode, b64decode, b32decode as _b32decode, b32encode as _b32encode, ) from binascii import b2a_base64, a2b_base64, Error as _BinAsciiError import logging log = logging.getLogger(__name__) # site # pkg from passlib import exc from passlib.utils.compat import ( PY3, bascii_to_str, irange, imap, iter_byte_chars, join_byte_values, join_byte_elems, nextgetter, suppress_cause, u, unicode, unicode_or_bytes_types, ) from passlib.utils.decor import memoized_property # from passlib.utils import BASE64_CHARS, HASH64_CHARS # local __all__ = [ # constants "BASE64_CHARS", "PADDED_BASE64_CHARS", "AB64_CHARS", "HASH64_CHARS", "BCRYPT_CHARS", "HEX_CHARS", "LOWER_HEX_CHARS", "UPPER_HEX_CHARS", "ALL_BYTE_VALUES", # misc "compile_byte_translation", # base64 'ab64_encode', 'ab64_decode', 'b64s_encode', 'b64s_decode', # base32 "b32encode", "b32decode", # custom encodings 'Base64Engine', 'LazyBase64Engine', 'h64', 'h64big', 'bcrypt64', ] #============================================================================= # constant strings #============================================================================= #------------------------------------------------------------- # common salt_chars & checksum_chars values #------------------------------------------------------------- #: standard base64 charmap BASE64_CHARS = u("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") #: alt base64 charmap -- "." instead of "+" AB64_CHARS = u("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./") #: charmap used by HASH64 encoding. HASH64_CHARS = u("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") #: charmap used by BCrypt BCRYPT_CHARS = u("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") #: std base64 chars + padding char PADDED_BASE64_CHARS = BASE64_CHARS + u("=") #: all hex chars HEX_CHARS = u("0123456789abcdefABCDEF") #: upper case hex chars UPPER_HEX_CHARS = u("0123456789ABCDEF") #: lower case hex chars LOWER_HEX_CHARS = u("0123456789abcdef") #------------------------------------------------------------- # byte strings #------------------------------------------------------------- #: special byte string containing all possible byte values #: NOTE: for efficiency, this is treated as singleton by some of the code ALL_BYTE_VALUES = join_byte_values(irange(256)) #: some string constants we reuse B_EMPTY = b'' B_NULL = b'\x00' B_EQUAL = b'=' #============================================================================= # byte translation #============================================================================= #: base list used to compile byte translations _TRANSLATE_SOURCE = list(iter_byte_chars(ALL_BYTE_VALUES)) def compile_byte_translation(mapping, source=None): """ return a 256-byte string for translating bytes using specified mapping. bytes not specified by mapping will be left alone. :param mapping: dict mapping input byte (str or int) -> output byte (str or int). :param source: optional existing byte translation string to use as base. (must be 255-length byte string). defaults to identity mapping. :returns: 255-length byte string for passing to bytes().translate. """ if source is None: target = _TRANSLATE_SOURCE[:] else: assert isinstance(source, bytes) and len(source) == 255 target = list(iter_byte_chars(source)) for k, v in mapping.items(): if isinstance(k, unicode_or_bytes_types): k = ord(k) assert isinstance(k, int) and 0 <= k < 256 if isinstance(v, unicode): v = v.encode("ascii") assert isinstance(v, bytes) and len(v) == 1 target[k] = v return B_EMPTY.join(target) #============================================================================= # unpadding / stripped base64 encoding #============================================================================= def b64s_encode(data): """ encode using shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. """ return b2a_base64(data).rstrip(_BASE64_STRIP) def b64s_decode(data): """ decode from shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. """ if isinstance(data, unicode): # needs bytes for replace() call, but want to accept ascii-unicode ala a2b_base64() try: data = data.encode("ascii") except UnicodeEncodeError: raise suppress_cause(ValueError("string argument should contain only ASCII characters")) off = len(data) & 3 if off == 0: pass elif off == 2: data += _BASE64_PAD2 elif off == 3: data += _BASE64_PAD1 else: # off == 1 raise ValueError("invalid base64 input") try: return a2b_base64(data) except _BinAsciiError as err: raise suppress_cause(TypeError(err)) #============================================================================= # adapted-base64 encoding #============================================================================= _BASE64_STRIP = b"=\n" _BASE64_PAD1 = b"=" _BASE64_PAD2 = b"==" # XXX: Passlib 1.8/1.9 -- deprecate everything that's using ab64_encode(), # have it start outputing b64s_encode() instead? can use a64_decode() to retain backwards compat. def ab64_encode(data): """ encode using shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars. it is primarily used by Passlib's custom pbkdf2 hashes. """ return b64s_encode(data).replace(b"+", b".") def ab64_decode(data): """ decode from shortened base64 format which omits padding & whitespace. uses custom ``./`` altchars, but supports decoding normal ``+/`` altchars as well. it is primarily used by Passlib's custom pbkdf2 hashes. """ if isinstance(data, unicode): # needs bytes for replace() call, but want to accept ascii-unicode ala a2b_base64() try: data = data.encode("ascii") except UnicodeEncodeError: raise suppress_cause(ValueError("string argument should contain only ASCII characters")) return b64s_decode(data.replace(b".", b"+")) #============================================================================= # base32 codec #============================================================================= def b32encode(source): """ wrapper around :func:`base64.b32encode` which strips padding, and returns a native string. """ # NOTE: using upper case by default here, since 'I & L' are less # visually ambiguous than 'i & l' return bascii_to_str(_b32encode(source).rstrip(B_EQUAL)) #: byte translation map to replace common mistyped base32 chars. #: XXX: could correct '1' -> 'I', but could be a mistyped lower-case 'l', so leaving it alone. _b32_translate = compile_byte_translation({"8": "B", "0": "O"}) #: helper to add padding _b32_decode_pad = B_EQUAL * 8 def b32decode(source): """ wrapper around :func:`base64.b32decode` which handles common mistyped chars. padding optional, ignored if present. """ # encode & correct for typos if isinstance(source, unicode): source = source.encode("ascii") source = source.translate(_b32_translate) # pad things so final string is multiple of 8 remainder = len(source) & 0x7 if remainder: source += _b32_decode_pad[:-remainder] # XXX: py27 stdlib's version of this has some inefficiencies, # could look into using optimized version. return _b32decode(source, True) #============================================================================= # base64-variant encoding #============================================================================= class Base64Engine(object): """Provides routines for encoding/decoding base64 data using arbitrary character mappings, selectable endianness, etc. :arg charmap: A string of 64 unique characters, which will be used to encode successive 6-bit chunks of data. A character's position within the string should correspond to its 6-bit value. :param big: Whether the encoding should be big-endian (default False). .. note:: This class does not currently handle base64's padding characters in any way what so ever. Raw Bytes <-> Encoded Bytes =========================== The following methods convert between raw bytes, and strings encoded using the engine's specific base64 variant: .. automethod:: encode_bytes .. automethod:: decode_bytes .. automethod:: encode_transposed_bytes .. automethod:: decode_transposed_bytes .. .. automethod:: check_repair_unused .. automethod:: repair_unused Integers <-> Encoded Bytes ========================== The following methods allow encoding and decoding unsigned integers to and from the engine's specific base64 variant. Endianess is determined by the engine's ``big`` constructor keyword. .. automethod:: encode_int6 .. automethod:: decode_int6 .. automethod:: encode_int12 .. automethod:: decode_int12 .. automethod:: encode_int24 .. automethod:: decode_int24 .. automethod:: encode_int64 .. automethod:: decode_int64 Informational Attributes ======================== .. attribute:: charmap unicode string containing list of characters used in encoding; position in string matches 6bit value of character. .. attribute:: bytemap bytes version of :attr:`charmap` .. attribute:: big boolean flag indicating this using big-endian encoding. """ #=================================================================== # instance attrs #=================================================================== # public config bytemap = None # charmap as bytes big = None # little or big endian # filled in by init based on charmap. # (byte elem: single byte under py2, 8bit int under py3) _encode64 = None # maps 6bit value -> byte elem _decode64 = None # maps byte elem -> 6bit value # helpers filled in by init based on endianness _encode_bytes = None # throws IndexError if bad value (shouldn't happen) _decode_bytes = None # throws KeyError if bad char. #=================================================================== # init #=================================================================== def __init__(self, charmap, big=False): # validate charmap, generate encode64/decode64 helper functions. if isinstance(charmap, unicode): charmap = charmap.encode("latin-1") elif not isinstance(charmap, bytes): raise exc.ExpectedStringError(charmap, "charmap") if len(charmap) != 64: raise ValueError("charmap must be 64 characters in length") if len(set(charmap)) != 64: raise ValueError("charmap must not contain duplicate characters") self.bytemap = charmap self._encode64 = charmap.__getitem__ lookup = dict((value, idx) for idx, value in enumerate(charmap)) self._decode64 = lookup.__getitem__ # validate big, set appropriate helper functions. self.big = big if big: self._encode_bytes = self._encode_bytes_big self._decode_bytes = self._decode_bytes_big else: self._encode_bytes = self._encode_bytes_little self._decode_bytes = self._decode_bytes_little # TODO: support padding character ##if padding is not None: ## if isinstance(padding, unicode): ## padding = padding.encode("latin-1") ## elif not isinstance(padding, bytes): ## raise TypeError("padding char must be unicode or bytes") ## if len(padding) != 1: ## raise ValueError("padding must be single character") ##self.padding = padding @property def charmap(self): """charmap as unicode""" return self.bytemap.decode("latin-1") #=================================================================== # encoding byte strings #=================================================================== def encode_bytes(self, source): """encode bytes to base64 string. :arg source: byte string to encode. :returns: byte string containing encoded data. """ if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) chunks, tail = divmod(len(source), 3) if PY3: next_value = nextgetter(iter(source)) else: next_value = nextgetter(ord(elem) for elem in source) gen = self._encode_bytes(next_value, chunks, tail) out = join_byte_elems(imap(self._encode64, gen)) ##if tail: ## padding = self.padding ## if padding: ## out += padding * (3-tail) return out def _encode_bytes_little(self, next_value, chunks, tail): """helper used by encode_bytes() to handle little-endian encoding""" # # output bit layout: # # first byte: v1 543210 # # second byte: v1 ....76 # +v2 3210.. # # third byte: v2 ..7654 # +v3 10.... # # fourth byte: v3 765432 # idx = 0 while idx < chunks: v1 = next_value() v2 = next_value() v3 = next_value() yield v1 & 0x3f yield ((v2 & 0x0f)<<2)|(v1>>6) yield ((v3 & 0x03)<<4)|(v2>>4) yield v3>>2 idx += 1 if tail: v1 = next_value() if tail == 1: # note: 4 msb of last byte are padding yield v1 & 0x3f yield v1>>6 else: assert tail == 2 # note: 2 msb of last byte are padding v2 = next_value() yield v1 & 0x3f yield ((v2 & 0x0f)<<2)|(v1>>6) yield v2>>4 def _encode_bytes_big(self, next_value, chunks, tail): """helper used by encode_bytes() to handle big-endian encoding""" # # output bit layout: # # first byte: v1 765432 # # second byte: v1 10.... # +v2 ..7654 # # third byte: v2 3210.. # +v3 ....76 # # fourth byte: v3 543210 # idx = 0 while idx < chunks: v1 = next_value() v2 = next_value() v3 = next_value() yield v1>>2 yield ((v1&0x03)<<4)|(v2>>4) yield ((v2&0x0f)<<2)|(v3>>6) yield v3 & 0x3f idx += 1 if tail: v1 = next_value() if tail == 1: # note: 4 lsb of last byte are padding yield v1>>2 yield (v1&0x03)<<4 else: assert tail == 2 # note: 2 lsb of last byte are padding v2 = next_value() yield v1>>2 yield ((v1&0x03)<<4)|(v2>>4) yield ((v2&0x0f)<<2) #=================================================================== # decoding byte strings #=================================================================== def decode_bytes(self, source): """decode bytes from base64 string. :arg source: byte string to decode. :returns: byte string containing decoded data. """ if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) ##padding = self.padding ##if padding: ## # TODO: add padding size check? ## source = source.rstrip(padding) chunks, tail = divmod(len(source), 4) if tail == 1: # only 6 bits left, can't encode a whole byte! raise ValueError("input string length cannot be == 1 mod 4") next_value = nextgetter(imap(self._decode64, source)) try: return join_byte_values(self._decode_bytes(next_value, chunks, tail)) except KeyError as err: raise ValueError("invalid character: %r" % (err.args[0],)) def _decode_bytes_little(self, next_value, chunks, tail): """helper used by decode_bytes() to handle little-endian encoding""" # # input bit layout: # # first byte: v1 ..543210 # +v2 10...... # # second byte: v2 ....5432 # +v3 3210.... # # third byte: v3 ......54 # +v4 543210.. # idx = 0 while idx < chunks: v1 = next_value() v2 = next_value() v3 = next_value() v4 = next_value() yield v1 | ((v2 & 0x3) << 6) yield (v2>>2) | ((v3 & 0xF) << 4) yield (v3>>4) | (v4<<2) idx += 1 if tail: # tail is 2 or 3 v1 = next_value() v2 = next_value() yield v1 | ((v2 & 0x3) << 6) # NOTE: if tail == 2, 4 msb of v2 are ignored (should be 0) if tail == 3: # NOTE: 2 msb of v3 are ignored (should be 0) v3 = next_value() yield (v2>>2) | ((v3 & 0xF) << 4) def _decode_bytes_big(self, next_value, chunks, tail): """helper used by decode_bytes() to handle big-endian encoding""" # # input bit layout: # # first byte: v1 543210.. # +v2 ......54 # # second byte: v2 3210.... # +v3 ....5432 # # third byte: v3 10...... # +v4 ..543210 # idx = 0 while idx < chunks: v1 = next_value() v2 = next_value() v3 = next_value() v4 = next_value() yield (v1<<2) | (v2>>4) yield ((v2&0xF)<<4) | (v3>>2) yield ((v3&0x3)<<6) | v4 idx += 1 if tail: # tail is 2 or 3 v1 = next_value() v2 = next_value() yield (v1<<2) | (v2>>4) # NOTE: if tail == 2, 4 lsb of v2 are ignored (should be 0) if tail == 3: # NOTE: 2 lsb of v3 are ignored (should be 0) v3 = next_value() yield ((v2&0xF)<<4) | (v3>>2) #=================================================================== # encode/decode helpers #=================================================================== # padmap2/3 - dict mapping last char of string -> # equivalent char with no padding bits set. def __make_padset(self, bits): """helper to generate set of valid last chars & bytes""" pset = set(c for i,c in enumerate(self.bytemap) if not i & bits) pset.update(c for i,c in enumerate(self.charmap) if not i & bits) return frozenset(pset) @memoized_property def _padinfo2(self): """mask to clear padding bits, and valid last bytes (for strings 2 % 4)""" # 4 bits of last char unused (lsb for big, msb for little) bits = 15 if self.big else (15<<2) return ~bits, self.__make_padset(bits) @memoized_property def _padinfo3(self): """mask to clear padding bits, and valid last bytes (for strings 3 % 4)""" # 2 bits of last char unused (lsb for big, msb for little) bits = 3 if self.big else (3<<4) return ~bits, self.__make_padset(bits) def check_repair_unused(self, source): """helper to detect & clear invalid unused bits in last character. :arg source: encoded data (as ascii bytes or unicode). :returns: `(True, result)` if the string was repaired, `(False, source)` if the string was ok as-is. """ # figure out how many padding bits there are in last char. tail = len(source) & 3 if tail == 2: mask, padset = self._padinfo2 elif tail == 3: mask, padset = self._padinfo3 elif not tail: return False, source else: raise ValueError("source length must != 1 mod 4") # check if last char is ok (padset contains bytes & unicode versions) last = source[-1] if last in padset: return False, source # we have dirty bits - repair the string by decoding last char, # clearing the padding bits via , and encoding new char. if isinstance(source, unicode): cm = self.charmap last = cm[cm.index(last) & mask] assert last in padset, "failed to generate valid padding char" else: # NOTE: this assumes ascii-compat encoding, and that # all chars used by encoding are 7-bit ascii. last = self._encode64(self._decode64(last) & mask) assert last in padset, "failed to generate valid padding char" if PY3: last = bytes([last]) return True, source[:-1] + last def repair_unused(self, source): return self.check_repair_unused(source)[1] ##def transcode(self, source, other): ## return ''.join( ## other.charmap[self.charmap.index(char)] ## for char in source ## ) ##def random_encoded_bytes(self, size, random=None, unicode=False): ## "return random encoded string of given size" ## data = getrandstr(random or rng, ## self.charmap if unicode else self.bytemap, size) ## return self.repair_unused(data) #=================================================================== # transposed encoding/decoding #=================================================================== def encode_transposed_bytes(self, source, offsets): """encode byte string, first transposing source using offset list""" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) tmp = join_byte_elems(source[off] for off in offsets) return self.encode_bytes(tmp) def decode_transposed_bytes(self, source, offsets): """decode byte string, then reverse transposition described by offset list""" # NOTE: if transposition does not use all bytes of source, # the original can't be recovered... and join_byte_elems() will throw # an error because 1+ values in will be None. tmp = self.decode_bytes(source) buf = [None] * len(offsets) for off, char in zip(offsets, tmp): buf[off] = char return join_byte_elems(buf) #=================================================================== # integer decoding helpers - mainly used by des_crypt family #=================================================================== def _decode_int(self, source, bits): """decode base64 string -> integer :arg source: base64 string to decode. :arg bits: number of bits in resulting integer. :raises ValueError: * if the string contains invalid base64 characters. * if the string is not long enough - it must be at least ``int(ceil(bits/6))`` in length. :returns: a integer in the range ``0 <= n < 2**bits`` """ if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) big = self.big pad = -bits % 6 chars = (bits+pad)/6 if len(source) != chars: raise ValueError("source must be %d chars" % (chars,)) decode = self._decode64 out = 0 try: for c in source if big else reversed(source): out = (out<<6) + decode(c) except KeyError: raise ValueError("invalid character in string: %r" % (c,)) if pad: # strip padding bits if big: out >>= pad else: out &= (1< 6 bit integer""" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) if len(source) != 1: raise ValueError("source must be exactly 1 byte") if PY3: # convert to 8bit int before doing lookup source = source[0] try: return self._decode64(source) except KeyError: raise ValueError("invalid character") def decode_int12(self, source): """decodes 2 char string -> 12-bit integer""" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) if len(source) != 2: raise ValueError("source must be exactly 2 bytes") decode = self._decode64 try: if self.big: return decode(source[1]) + (decode(source[0])<<6) else: return decode(source[0]) + (decode(source[1])<<6) except KeyError: raise ValueError("invalid character") def decode_int24(self, source): """decodes 4 char string -> 24-bit integer""" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) if len(source) != 4: raise ValueError("source must be exactly 4 bytes") decode = self._decode64 try: if self.big: return decode(source[3]) + (decode(source[2])<<6)+ \ (decode(source[1])<<12) + (decode(source[0])<<18) else: return decode(source[0]) + (decode(source[1])<<6)+ \ (decode(source[2])<<12) + (decode(source[3])<<18) except KeyError: raise ValueError("invalid character") def decode_int30(self, source): """decode 5 char string -> 30 bit integer""" return self._decode_int(source, 30) def decode_int64(self, source): """decode 11 char base64 string -> 64-bit integer this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. """ return self._decode_int(source, 64) #=================================================================== # integer encoding helpers - mainly used by des_crypt family #=================================================================== def _encode_int(self, value, bits): """encode integer into base64 format :arg value: non-negative integer to encode :arg bits: number of bits to encode :returns: a string of length ``int(ceil(bits/6.0))``. """ assert value >= 0, "caller did not sanitize input" pad = -bits % 6 bits += pad if self.big: itr = irange(bits-6, -6, -6) # shift to add lsb padding. value <<= pad else: itr = irange(0, bits, 6) # padding is msb, so no change needed. return join_byte_elems(imap(self._encode64, ((value>>off) & 0x3f for off in itr))) #--------------------------------------------------------------- # optimized versions for common integer sizes #--------------------------------------------------------------- def encode_int6(self, value): """encodes 6-bit integer -> single hash64 character""" if value < 0 or value > 63: raise ValueError("value out of range") if PY3: return self.bytemap[value:value+1] else: return self._encode64(value) def encode_int12(self, value): """encodes 12-bit integer -> 2 char string""" if value < 0 or value > 0xFFF: raise ValueError("value out of range") raw = [value & 0x3f, (value>>6) & 0x3f] if self.big: raw = reversed(raw) return join_byte_elems(imap(self._encode64, raw)) def encode_int24(self, value): """encodes 24-bit integer -> 4 char string""" if value < 0 or value > 0xFFFFFF: raise ValueError("value out of range") raw = [value & 0x3f, (value>>6) & 0x3f, (value>>12) & 0x3f, (value>>18) & 0x3f] if self.big: raw = reversed(raw) return join_byte_elems(imap(self._encode64, raw)) def encode_int30(self, value): """decode 5 char string -> 30 bit integer""" if value < 0 or value > 0x3fffffff: raise ValueError("value out of range") return self._encode_int(value, 30) def encode_int64(self, value): """encode 64-bit integer -> 11 char hash64 string this format is used primarily by des-crypt & variants to encode the DES output value used as a checksum. """ if value < 0 or value > 0xffffffffffffffff: raise ValueError("value out of range") return self._encode_int(value, 64) #=================================================================== # eof #=================================================================== class LazyBase64Engine(Base64Engine): """Base64Engine which delays initialization until it's accessed""" _lazy_opts = None def __init__(self, *args, **kwds): self._lazy_opts = (args, kwds) def _lazy_init(self): args, kwds = self._lazy_opts super(LazyBase64Engine, self).__init__(*args, **kwds) del self._lazy_opts self.__class__ = Base64Engine def __getattribute__(self, attr): if not attr.startswith("_"): self._lazy_init() return object.__getattribute__(self, attr) #------------------------------------------------------------- # common variants #------------------------------------------------------------- h64 = LazyBase64Engine(HASH64_CHARS) h64big = LazyBase64Engine(HASH64_CHARS, big=True) bcrypt64 = LazyBase64Engine(BCRYPT_CHARS, big=True) #============================================================================= # eof #============================================================================= decor.pyc000064400000017703147221702050006365 0ustar00 Xc@`sdZddlmZmZmZddlZejeZddl m Z m Z ddl Z ddl mZddlmZddd d d d gZdefd YZdefdYZdZd efdYZdddededdZdddeddZdS(s7 passlib.utils.decor -- helper decorators & properties i(tabsolute_importtdivisiontprint_functionN(twrapstupdate_wrapper(twarn(tPY3t classpropertyt hybrid_methodtmemoize_single_valuetmemoized_propertytdeprecated_functiontdeprecated_methodcB`s/eZdZdZdZedZRS(sjFunction decorator which acts like a combination of classmethod+property (limited to read-only properties)cC`s ||_dS(N(tim_func(tselftfunc((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__init__#scC`s |j|S(N(R (Rtobjtcls((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__get__&scC`s|jS(spy3 compatible alias(R (R((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt__func__)s(t__name__t __module__t__doc__RRtpropertyR(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s  cB`s eZdZdZdZRS(s decorator which invokes function with class if called as class method, and with object if called at instance level. cC`s||_t||dS(N(RR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR4s cC`sH|dkr|}ntr.tj|j|Stj|j||SdS(N(tNoneRttypest MethodTypeR(RRR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR8s   (RRRRR(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR.s c`s@itfd}fd}||_|S(s decorator for function which takes no args, and memoizes result. exposes a ``.clear_cache`` method to clear the cached value. c`s5y tSWntk rnX}t<|S(N(tTruetKeyError(tvalue(tcacheR(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pytwrapperLs   c`sjtddS(N(tpopRR((R(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt clear_cacheUs(RR"(RR R"((RRs7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR Ds   cB`sMeZdZdZdZes6edZndZddZ RS(sM decorator which invokes method once, then replaces attr with result cC`s%||_|j|_|j|_dS(N(RRR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR_s  cC`s6|dkr|S|j|}t||j||S(N(RRtsetattrR(RRRR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyRds  cC`s|jS(s py2 alias(R(R((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR mscC`s|jj|jddS(s class-level helper to clear stored value (if any). usage: :samp:`type(self).{attr}.clear_cache(self)` N(t__dict__R!RR(RR((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR"rscC`s|jj|j|S(s class-level helper to peek at stored value usage: :samp:`value = type(self).{attr}.clear_cache(self)` (R$tgetR(RRtdefault((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyt peek_cachezsN( RRRRRRRR R"RR'(((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR [s   c`sdkrkrdndr4d7nrGd7nr^d7nd7nfd}|S( sbdecorator to deprecate a function. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when function was first deprecated :kwd removed: version when function will be removed :kwd replacement: alternate name / instructions for replacing this function. :kwd updoc: add notice to docstring (default ``True``) s5the method %(mod)s.%(klass)s.%(name)s() is deprecateds-the function %(mod)s.%(name)s() is deprecateds as of Passlib %(deprecated)ss,, and will be removed in Passlib %(removed)ss, use %s insteadt.c `sottr3jdtjntdpEjdjddrfd}nfd}t | rsr|j rd|j krpd}s rG|d 7}r|d f7}n r:r)|d 7}n|d 7}n|d 7}n|j j dj dst|j d7_ n|j d|f7_ nrt|}n|S(Ntmodtnamet deprecatedtremovedc`sij}r|dn |dj}|jd|jd|jt|tdd||S(NitklassR)t stackleveli(tcopyt __class__tupdateRRRtDeprecationWarning(targstkwdsttmpR-(Rtis_classmethodtmsgtopts(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s  c`s ttdd||S(NR.i(RR2(R3R4(Rttext(s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR ss.. deprecated::ts s!and will be removed in version %ss, suse %s insteadR(t s s .. deprecated:: %s ( t isinstancet classmethodRRttypeRtdictRRRRtstriptendswith(RR ttxt(t _is_methodR+t func_moduleR7R,t replacementtupdoc(RR6R8R9s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pytbuilds>         N(R(R7R+R,RFRERCRDRG((RCR+RDR7R,RERFs7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s     !*cC`st|||||dtS(sZdecorator to deprecate a method. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when method was first deprecated :kwd removed: version when method will be removed :kwd replacement: alternate name / instructions for replacing this method. :kwd updoc: add notice to docstring (default ``True``) RC(R R(R7R+R,RFRE((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyR s (Rt __future__RRRtloggingt getLoggerRtlogt functoolsRRRtwarningsRtpasslib.utils.compatRt__all__tobjectRRR R RRtFalseR R (((s7/usr/lib/python2.7/site-packages/passlib/utils/decor.pyts,    <  A handlers.pyc000064400000232336147221702050007072 0ustar00 Xc@s:dZddlmZddlZddlZejeZddlZddl Z ddl m Z ddl j Z ddljZddl mZmZmZddlmZddlmZddlmZmZmZmZmZmZmZmZmZm Z m!Z!dd l"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dd l*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m0Z0m3Z3m4Z4m5Z5dd l6m7Z7m8Z8d d ddddddddddddgZ9e$Z:e#Z;e%Z<e'Z=e(Z>dZ?ddZ@dZAdZBe-dZCe-d ZDd!ZEd"ZFeCeGd#ZHeCd$eGeGd%ZId$eGd&eGd'ZJe-dd(ZKe-dd$d)ZLd&d*ZMdeGd&eNd+ZOd,efd-YZPd.ePfd/YZQdePfd0YZRdeRfd1YZSd2eRfd3YZTdeRfd4YZUdeRfd5YZVdeRfd6YZWdeRfd7YZXdeXfd8YZYdeRfd9YZZd:eRfd;YZ[e j\Z]d<efd=YZ^d>e^fd?YZ_de^eRfd@YZ`deafdAYZbdS(BsRpasslib.handler - code for implementing handlers, and global registry for handlersi(twith_statementN(twarn(tMissingBackendErrortPasslibConfigWarningtPasslibHashWarning(t PasswordHash(tget_crypt_handler( tconsteqt getrandstrt getrandbytestrngt to_native_strtis_crypt_handlert to_unicodetMAX_PASSWORD_SIZEtaccepts_keywordtas_booltupdate_mixin_classes(t BASE64_CHARSt HASH64_CHARStPADDED_BASE64_CHARSt HEX_CHARStUPPER_HEX_CHARStLOWER_HEX_CHARStALL_BYTE_VALUES( tjoin_byte_valuestirangetutnative_string_typest uascii_to_strt join_unicodetunicodet str_to_uasciiRtunicode_or_bytes_typestPY2t int_types(t classpropertytdeprecated_methodt parse_mc2t parse_mc3t render_mc2t render_mc3tGenericHandlert StaticHandlertHasUserContexttHasRawChecksumt HasManyIdentstHasSaltt HasRawSaltt HasRoundstHasManyBackendst PrefixWrappercCs@|r8|r8ddl}t||jt|dSdSdS(shelper for bitsize() methodsiNii(tmathtinttlogtlen(tcounttcharsR4((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_bitsizeJs   icCstj}| }zix^|rv|jjdd}|jdsS|jd r`td|S|d7}|j}qW|SWd~XdS(si try to guess stacklevel for application warning. looks for first frame not part of passlib. t__name__tspasslib.tests.spasslib.iN(tinspectt currentframet f_globalstgett startswithtmaxtf_back(tstarttframeR8tname((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytguess_app_stacklevelRs     cCs-tdtd|jtdtddS(Nspassing settings to %(handler)s.hash() is deprecated, and won't be supported in Passlib 2.0; use '%(handler)s.using(**settings).hash(secret)' insteadthandlert stackleveli(RtdictRFtDeprecationWarningRG(RHtkwds((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytwarn_hash_settings_deprecationdscs2t|jtfdtDS(s helper to extract settings kwds from mix of context & settings kwds. pops settings keys from kwds, returns them as a dict. c3s0|]&}|kr|j|fVqdS(N(tpop(t.0tkey(t context_keysRL(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys os(tsett context_kwdsRJtlist(RHRL((RQRLs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytextract_settings_kwdsist$t0cCsLt|ts$tj|dnt|tkrHtjtndS(s%ensure secret has correct type & sizetsecretN(t isinstanceR!texctExpectedStringErrorR7RtPasswordSizeError(RX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_secretwscCsjt|tr|St|trTy|jdSWqftk rP|jdSXntj|ddS(s+convert hash to unicode for identify methodsutf-8slatin-1thashN(RYRtbytestdecodetUnicodeDecodeErrorRZR[(R^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytto_unicode_for_identify~s cCst|dd}t|ts't|j|sHtj|nt|ts]t|t|j|}t|dkr|\}}||pdfSt|dkr|ddfStj |dS(sparse hash using 2-part modular crypt format. this expects a hash of the format :samp:`{prefix}{salt}[${checksum}]`, such as md5_crypt, and parses it into salt / checksum portions. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param handler: handler class to pass to error constructors. :returns: a ``(salt, chk | None)`` tuple. tasciiR^iiiN( R RYRtAssertionErrorRARZtInvalidHashErrorR7tsplittNonetMalformedHashError(R^tprefixtsepRHtpartstsalttchk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR&s i c CsOt|dd}t|ts't|j|sHtj|nt|ts]t|t|j|}t|dkr|\}}} n6t|dkr|\}}d} ntj ||jt r|t krtj |n?|rt ||}n'|dkr6tj |dn|}||| pKdfS(srparse hash using 3-part modular crypt format. this expects a hash of the format :samp:`{prefix}[{rounds}]${salt}[${checksum}]`, such as sha1_crypt, and parses it into rounds / salt / checksum portions. tries to convert the rounds to an integer, and throws error if it has zero-padding. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param rounds_base: the numeric base the rounds are encoded in (defaults to base 10). :param default_rounds: the default rounds value to return if the rounds field was omitted. if this is ``None`` (the default), the rounds field is *required*. :param handler: handler class to pass to error constructors. :returns: a ``(rounds : int, salt, chk | None)`` tuple. RcR^iisempty rounds fieldN(R RYRRdRARZReR7RfRgRht_UZEROtZeroPaddedRoundsErrorR5( R^RiRjt rounds_basetdefault_roundsRHRktroundsRlRm((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR's(   tvaluecCst|jtr4|tkr4tj|d|n<|rGt||S|dkrltj|d|n|SdS(s helper to parse an integer config field :arg source: unicode source string :param base: numeric base :param default: optional default if source is empty :param param: name of variable, for error msgs :param handler: handler class, for error msgs szero-padded %s fieldsempty %s fieldN(RARnRZRhR5Rg(tsourcetbasetdefaulttparamRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parse_ints   cCs7|r||||g}n ||g}tt|S(sformat hash using 2-part modular crypt format; inverse of parse_mc2() returns native string with format :samp:`{ident}{salt}[${checksum}]`, such as used by md5_crypt. :arg ident: identifier prefix (unicode) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :returns: config or hash (native str) (RR(tidentRltchecksumRjRk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR( s cCs|dkrtd}n=|dkr:td|}n|dksLtt|}|ry||||||g}n||||g}tt|S(s.format hash using 3-part modular crypt format; inverse of parse_mc3() returns native string with format :samp:`{ident}[{rounds}$]{salt}[${checksum}]`, such as used by sha1_crypt. :arg ident: identifier prefix (unicode) :arg rounds: rounds field (int or None) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :param rounds_base: base to encode rounds value (defaults to base 10) :returns: config or hash (native str) R<is%xi N(RgRRdRRR(RyRrRlRzRjRpRk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)!s   cCsW|dk s%td|j|f|||ksStd|j||ftS(s assert helper that quickly validates default value. designed to get out of the way and reduce overhead when asserts are stripped. s%s lacks default %ss%s: invalid default %s: %rN(RgRdRFtTrue(RHRvtnormRw((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_default_valueBs%.cCst|ts'tj|d|n||krzd|j|||f}|rkt|tj|}qzt|n|r||krd|j|||f}|rt|tj|}qt|n|S(s helper to normalize and validate an integer value (e.g. rounds, salt_size) :arg value: value provided to constructor :arg default: default value if none provided. if set to ``None``, value is required. :arg param: name of parameter (xxx: move to first arg?) :param min: minimum value (defaults to 1) :param max: maximum value (default ``None`` means no maximum) :returns: validated value tintegers+%s: %s (%d) is too low, must be at least %ds0%s: %s (%d) is too large, cannot be more than %d(RYR#RZtExpectedTypeErrorRFRRt ValueError(RHRstminRBRwtrelaxedtmsg((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt norm_integerKs    tMinimalHandlercBs&eZdZeZeedZRS(s helper class for implementing hash handlers. provides nothing besides a base implementation of the .using() subclass constructor. cCsD|j}|jsd|}nt||ftd|jdtS(Nst __module__t _configured(R;RttypeRJRR{(tclsRRF((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytusings   (R;Rt__doc__tFalseRt classmethodR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRrst TruncateMixincBs;eZdZeZeZeddZedZ RS(s PasswordHash mixin which provides a method that will check if secret would be truncated, and can be configured to throw an error. .. warning:: Hashers using this mixin will generally need to override the default PasswordHash.truncate_error policy of "True", and will similarly want to override .truncate_verify_reject as well. TODO: This should be done explicitly, but for now this mixin sets these flags implicitly. cKsUtt|j|}|dk rQt|dd}|dk rQ||_qQn|S(NRwttruncate_error(tsuperRRRgRR(RRRLtsubcls((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   cCsO|jdk std|jrKt||jkrKtj|ndS(s make sure secret won't be truncated. NOTE: this should only be called for .hash(), not for .verify(), which should honor the .truncate_verify_reject policy. s%truncate_size must be set by subclassN(t truncate_sizeRgRdRR7RZtPasswordTruncateError(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_check_truncate_policysN( R;RRRRttruncate_verify_rejectRRgRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cBsseZdZdZdZdZdZdZdZ e Z dZ de dZ e dZedZedZdZedZdZedZed Zed d d d edZed d d d edZeddZddZdZdZedZ e!e"ddZ#ee$e dZ%edZ&RS(s4helper class for implementing hash handlers. GenericHandler-derived classes will have (at least) the following constructor options, though others may be added by mixins and by the class itself: :param checksum: this should contain the digest portion of a parsed hash (mainly provided when the constructor is called by :meth:`from_string()`). defaults to ``None``. :param use_defaults: If ``False`` (the default), a :exc:`TypeError` should be thrown if any settings required by the handler were not explicitly provided. If ``True``, the handler should attempt to provide a default for any missing values. This means generate missing salts, fill in default cost parameters, etc. This is typically only set to ``True`` when the constructor is called by :meth:`hash`, allowing user-provided values to be handled in a more permissive manner. :param relaxed: If ``False`` (the default), a :exc:`ValueError` should be thrown if any settings are out of bounds or otherwise invalid. If ``True``, they should be corrected if possible, and a warning issue. If not possible, only then should an error be raised. (e.g. under ``relaxed=True``, rounds values will be clamped to min/max rounds). This is mainly used when parsing the config strings of certain hashes, whose specifications implementations to be tolerant of incorrect values in salt strings. Class Attributes ================ .. attribute:: ident [optional] If this attribute is filled in, the default :meth:`identify` method will use it as a identifying prefix that can be used to recognize instances of this handler's hash. Filling this out is recommended for speed. This should be a unicode str. .. attribute:: _hash_regex [optional] If this attribute is filled in, the default :meth:`identify` method will use it to recognize instances of the hash. If :attr:`ident` is specified, this will be ignored. This should be a unique regex object. .. attribute:: checksum_size [optional] Specifies the number of characters that should be expected in the checksum string. If omitted, no check will be performed. .. attribute:: checksum_chars [optional] A string listing all the characters allowed in the checksum string. If omitted, no check will be performed. This should be a unicode str. .. attribute:: _stub_checksum Placeholder checksum that will be used by genconfig() in lieu of actually generating a hash for the empty string. This should be a string of the same datatype as :attr:`checksum`. Instance Attributes =================== .. attribute:: checksum The checksum string provided to the constructor (after passing it through :meth:`_norm_checksum`). Required Subclass Methods ========================= The following methods must be provided by handler subclass: .. automethod:: from_string .. automethod:: to_string .. automethod:: _calc_checksum Default Methods =============== The following methods have default implementations that should work for most cases, though they may be overridden if the hash subclass needs to: .. automethod:: _norm_checksum .. automethod:: genconfig .. automethod:: genhash .. automethod:: identify .. automethod:: hash .. automethod:: verify cKsD||_tt|j||dk r@|j||_ndS(N(t use_defaultsRR*t__init__Rgt_norm_checksumRz(tselfRzRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRLs  cs|j}|r9t|tstj|ddqn[t|tst|tr||r|tdt|jd}qtj|ddn|j }|rt ||krtj |d|n|s|j rt fd|Drtd|jfqn|S( sovalidates checksum keyword against class requirements, returns normalized version of checksum. R_Rzs%checksum should be unicode, not bytesRcRtrawc3s|]}|kVqdS(N((ROtc(tcs(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys tss!invalid characters in %s checksum(t_checksum_is_bytesRYR_RZRRRRR`t checksum_sizeR7tChecksumSizeErrortchecksum_charstanyRRF(RRzRRtcc((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRUs"    "cCst|}|stS|j}|dk r8|j|S|j}|dk r`|j|dk Sy|j|tSWnt k rtSXdS(N( RbRRyRgRAt _hash_regextmatcht from_stringR{R(RR^Rytpat((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytidentify|s        cKstd|fdS(sV return parsed instance from hash/configuration string :param \*\*context: context keywords to pass to constructor (if applicable). :raises ValueError: if hash is incorrectly formatted :returns: hash parsed into components, for formatting / calculating checksum. s%s must implement from_string()N(tNotImplementedError(RR^tcontext((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstd|jfdS(srender instance to hash or configuration string :returns: hash string with salt & digest included. should return native string type (ascii-bytes under python 2, unicode under python 3) s%s must implement from_string()N(Rt __class__(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt to_strings cCs|jr;|jrd|jS|jr;|jd|jSnt|tr|j}|jp_d|_z|jdSWd||_Xn|jdS(si placeholder used by default .genconfig() so it can avoid expense of calculating digest. tiiR<N(RRRRYR1Rrt min_roundst_calc_checksum(Rtorig((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_stub_checksums      cCstd|jfdS(sgiven secret; calcuate and return encoded checksum portion of hash string, taking config from object state calc checksum implementations may assume secret is always either unicode or bytes, checks are performed by verify/etc. s"%s must implement _calc_checksum()N(RR(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKs||rDt||}|rDt|||j|j||Snt||dt|}|j||_|jS(NR( RURMRR^R]R{RRzR(RRXRLtsettingsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^s  cKsYt||j||}|j}|dkrCtj|nt|j||S(N(R]RRzRgRZtMissingDigestErrorRR(RRXR^RRRm((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytverifys    t deprecateds1.7tremoveds2.0cKsSt||}|r+|j|j|S|dt|}|j|_|jS(NR(RURt genconfigR{RRzR(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cKsS|dkrtdnt||j||}|j||_|jS(Nsconfig must be string(Rgt TypeErrorR]RRRzR(RRXtconfigRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytgenhash s   cKs7|j|}t||s$t|jd||S(NRX(RRYRdt_calc_needs_update(RR^RXRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt needs_updatescCstS(s; internal helper for :meth:`needs_update`. (R(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR"st salt_sizeRRlRzcsfdjDS(Nc3s$|]}|jkr|VqdS(N(t_unparsed_settings(RORP(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys 3s(t setting_kwds(R((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_parsed_settings1st*cCs|dkrdSt|trGddlm}||jd}nt|tset|}nt|}td|d}|| |||S(s*default method to obscure sensitive fieldsi(t ab64_encodeRciiN( RgRYR_tpasslib.utils.binaryRR`RR7R(RstcharRtsizetclip((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _sanitize7s  csj|ttfdjD}|rbjdk rbj|d]sRzN( RtobjectRJRRzRgR{Rt_unsafe_settings(RR^RztsanitizeRLRP((RRRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parsehashEs %   cKszytt|j|}Wntk r5i}nX|jrEtn|j}|jrv|rvt|j||dt k r}t |dkrt dfqnXt dtt|S( s{given secret; calcuate and return encoded checksum portion of hash string, taking config from object state cstdfdS(Ns"%s must implement _calc_checksum()(R(RRX(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytinnerst_wrapperRRc3s$|]}|t|fVqdS(N(R(ROtk(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssconfig must be strings"%s must implement _calc_checksum()s%r should be updated to implement StaticHandler._calc_checksum() instead of StaticHandler.genhash(), support for the latter style will be removed in Passlib 1.8N(RRR;Rdt_StaticHandler__cc_compat_hackRgRRJRSRRtstrRRRKR (RRXt wrapper_clsRRR^terr((RRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs&    +(N( R;RRRRRRRRRRgRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+{s  tHasEncodingContextcBs&eZdZdZdZddZRS(s?helper for classes which require knowledge of the encoding usedtencodingsutf-8cKs,tt|j||p"|j|_dS(N(RRRtdefault_encodingR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(sencodingN(R;RRRSRRgR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscBskeZdZd Zd dZed dZed dZe dddded d Z RS( s7helper for classes which require a user context keywordtusercKs#tt|j|||_dS(N(RR,RR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKstt|j|d||S(NR(RR,R^(RRXRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^scKs"tt|j||d||S(NR(RR,R(RRXR^RR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRsRs1.7Rs2.0cKs"tt|j||d||S(NR(RR,R(RRXRRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(suserN( R;RRRSRgRRR^RR%R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR,s cBseZdZeZRS(sqmixin for classes which work with decoded checksum bytes .. todo:: document this class's usage (R;RRR{R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR-scBsteZdZdZdZdZdZedddZ ddZ edZ edZ edZ RS(s mixin for hashes which use multiple prefix identifiers For the hashes which may use multiple identifier prefixes, this mixin adds an ``ident`` keyword to constructor. Any value provided is passed through the :meth:`norm_idents` method, which takes care of validating the identifier, as well as allowing aliases for easier specification of the identifiers by the user. .. todo:: document this class's usage Class Methods ============= .. todo:: document using() and needs_update() options cKsv|dk r0|dk r'tdn|}ntt|j|}|dk rr|d|dtj|_n|S(s4 This mixin adds support for the following :meth:`~passlib.ifc.PasswordHash.using` keywords: :param default_ident: default identifier that will be used by resulting customized hasher. :param ident: supported as alternate alias for **default_ident**. s2'default_ident' and 'ident' are mutually exclusiveRyRN(RgRRR.RR{Ryt default_ident(RRRyRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR>s    cKstt|j||dk r4|j|}nB|jrj|j}t|||jddsvtn t d||_ dS(NRwRsno ident specified( RR.RRgt _norm_identRRR}RdRRy(RRyRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR\s   $ cCs|dk stt|tr3|jd}n|j}||krL|S|j}|ry||}Wntk r|qX||kr|Sntd|fdS(sD helper which normalizes & validates 'ident' value. Rcsinvalid ident: %rN( RgRdRYR_R`t ident_valuest ident_aliasestKeyErrorR(RRytivtiaRs((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRis     cCst|}|j|jS(N(RbRAR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cCs\t|dd}x4|jD])}|j|r||t|fSqWtj|dS(sDextract ident prefix from hash, helper for subclasses' from_string()RcR^N(R RRAR7RZRe(RR^Ry((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _parse_idents N(R;RRRgRRRRyRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR.s   cBseZdZdZdZdZedZedZ e Z dZ dZ eddddZededZddZd Zee d Zed Zed Zedd ZRS(s2 mixin for validating salts. This :class:`GenericHandler` mixin adds a ``salt`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_salt` method, which takes care of validating salt length and content, as well as generating new salts if one it not provided. :param salt: optional salt string :param salt_size: optional size of salt (only used if no salt provided); defaults to :attr:`default_salt_size`. Class Attributes ================ In order for :meth:`!_norm_salt` to do its job, the following attributes should be provided by the handler subclass: .. attribute:: min_salt_size The minimum number of characters allowed in a salt string. An :exc:`ValueError` will be throw if the provided salt is too small. Defaults to ``0``. .. attribute:: max_salt_size The maximum number of characters allowed in a salt string. By default an :exc:`ValueError` will be throw if the provided salt is too large; but if ``relaxed=True``, it will be clipped and a warning issued instead. Defaults to ``None``, for no maximum. .. attribute:: default_salt_size [required] If no salt is provided, this should specify the size of the salt that will be generated by :meth:`_generate_salt`. By default this will fall back to :attr:`max_salt_size`. .. attribute:: salt_chars A string containing all the characters which are allowed in the salt string. An :exc:`ValueError` will be throw if any other characters are encountered. May be set to ``None`` to skip this check (but see in :attr:`default_salt_chars`). .. attribute:: default_salt_chars [required] This attribute controls the set of characters use to generate *new* salt strings. By default, it mirrors :attr:`salt_chars`. If :attr:`!salt_chars` is ``None``, this attribute must be specified in order to generate new salts. Aside from that purpose, the main use of this attribute is for hashes which wish to generate salts from a restricted subset of :attr:`!salt_chars`; such as accepting all characters, but only using a-z. Instance Attributes =================== .. attribute:: salt This instance attribute will be filled in with the salt provided to the constructor (as adapted by :meth:`_norm_salt`) Subclassable Methods ==================== .. automethod:: _norm_salt .. automethod:: _generate_salt icCs|jS(s/default salt size (defaults to *max_salt_size*)(t max_salt_size(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_sizescCs|jS(sDcharset used to generate new salt strings (defaults to *salt_chars*)(t salt_chars(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_charssR9c s|dk r0|dk r'tdn|}ntt|j|}|jd}|dk rt|trt|}n|j |ddd||_ ndk r|j d|t fd|_ n|S(NsB'salt_size' and 'default_salt_size' aliases are mutually exclusiveRRwRcsS(N(((Rl(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt&s(RgRRR/RR@RYRR5t_clip_to_valid_salt_sizeRt _norm_saltRt_generate_salt(RRRRlRLRR((Rls:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s       RcCs|j}|j}||krl||krhd|j|||f}|rYt|tqht|n|S||krd|j|||f}|rt|t|}qt|n|r||krd|j|||f}|rt|t|}qt|n|S(s internal helper -- clip salt size value to handler's absolute limits (min_salt_size / max_salt_size) :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :returns: clipped rounds value s%s: %s (%d) must be exactly %ds$%s: %s (%r) below min_salt_size (%d)s$%s: %s (%r) above max_salt_size (%d)(t min_salt_sizeRRFRRR(RRRwRtmntmxR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+s,         cKstt|j||dk r4|j|}nL|jrt|j}|j||kstd|fn t d||_ dS(Nsgenerated invalid salt: %rsno salt specified( RR/RRgt _parse_saltRRRRdRRl(RRlRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR_s   + cCs |j|S(N(R(RRl((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRksc s|jr3t|tstj|ddqnt|tst|trots]|ro|jd}qtj|ddn|jd k rt fd|Drt d|j n|j }|r/t||kr/d|j ||jkr dnd ||jf}t |n|j}|rt||krd |j ||krkdnd ||jf}|rt|t|j||}qt |n|S( sThelper to normalize & validate user-provided salt string :arg salt: salt string :raises TypeError: If salt not correct type. :raises ValueError: * if salt contains chars that aren't in :attr:`salt_chars`. * if salt contains less than :attr:`min_salt_size` characters. * if ``relaxed=False`` and salt has more than :attr:`max_salt_size` characters (if ``relaxed=True``, the salt is truncated and a warning is issued instead). :returns: normalized salt R_RlRcRc3s|]}|kVqdS(N((ROR(tsc(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssinvalid characters in %s salts%salt too small (%s requires %s %d %s)texactlys>=s%salt too large (%s requires %s %d %s)s<=N(t_salt_is_bytesRYR_RZRRR"R`RRgRRRFRR7Rt _salt_unitRRt_truncate_salt(RRlRRRR((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRns0  (  (  % cCs|| S(N((RlR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstt|j|jS(sU helper method for _init_salt(); generates a new random salt string. (RR RR(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKsJtt|j|}|dkr0|j}nt||j|d<|S(s8[experimental method] return info about bitsizes of hashRlN(RR/RRgRR:R(RRRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   N(R;RRRRgRRR$RRRRRRlRRR{RRRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR/s.E3 9cBs/eZdZeZeZdZedZ RS(smixin for classes which use decoded salt parameter A variant of :class:`!HasSalt` which takes in decoded bytes instead of an encoded string. .. todo:: document this class's usage R_cCs+|jdtgksttt|jS(N(RRgRRdR R R(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs( R;RRRRR{RRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR0s c BseZdZdZdZdZdZdZdZ dZ dZ dZ e dddddddd Ze d Ze d Zdd Zd Ze eddZe dZdZe dddZRS(s3mixin for validating rounds parameter This :class:`GenericHandler` mixin adds a ``rounds`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_rounds` method, which takes care of validating the number of rounds. :param rounds: optional number of rounds hash should use Class Attributes ================ In order for :meth:`!_norm_rounds` to do its job, the following attributes must be provided by the handler subclass: .. attribute:: min_rounds The minimum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is too small. Defaults to ``0``. .. attribute:: max_rounds The maximum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is larger than this. Defaults to ``None`` which indicates no limit to the rounds value. .. attribute:: default_rounds If no rounds value is provided to constructor, this value will be used. If this is not specified, a rounds value *must* be specified by the application. .. attribute:: rounds_cost [required] The ``rounds`` parameter typically encodes a cpu-time cost for calculating a hash. This should be set to ``"linear"`` (the default) or ``"log2"``, depending on how the rounds value relates to the actual amount of time that will be required. Class Methods ============= .. todo:: document using() and needs_update() options Instance Attributes =================== .. attribute:: rounds This instance attribute will be filled in with the rounds value provided to the constructor (as adapted by :meth:`_norm_rounds`) Subclassable Methods ==================== .. automethod:: _norm_rounds itlineartmin_desired_roundstmax_desired_roundsRt max_roundsRqt vary_roundsc Ks|dk r0|dk r'tdn|}n|dk r`|dk rWtdn|}n|dk r|dkr|}n|dkr|}n|dkr|}qntt|j|} |jd} |dkrt} |j}nBt} t |t rt |}n| j |ddd| | _|dkrM|j }nt |t rkt |}n|r||krd| j||f} | rt| qt| t|}n| j |ddd| | _ |dk rt |t rt |}n|r7||kr7td| j||fn1|rh||krhtd | j||fn| j |dd d| | _n| jdk r| j| j| _n|dk rt |t r|jd rt|d d }qd|kr t|}qt |}n|dkrCtd| j|fnXt |tr}|dkrtd| j|fqnt |t stdn|rtdtn|| _n| S(NsD'min_rounds' and 'min_desired_rounds' aliases are mutually exclusivesD'max_rounds' and 'max_desired_rounds' aliases are mutually exclusiveRRwRs9%s: max_desired_rounds (%r) below min_desired_rounds (%r)Rs5%s: default_rounds (%r) below min_desired_rounds (%r)s5%s: default_rounds (%r) above max_desired_rounds (%r)Rqt%ig{Gz?t.is%s: vary_rounds (%r) below 0is%s: vary_rounds (%r) above 1.0s vary_rounds must be int or floats\The 'vary_rounds' option is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0(RgRRR1RR@RRR{RYRR5t _norm_roundsRRFRRRRqt_clip_to_desired_roundstendswithtfloatR( RRRRqRRRRrRLRRtexplicit_min_roundsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR6s                               cCsB|jp d}||kr|S|j}|r>||kr>|S|S(s| helper for :meth:`_generate_rounds` -- clips rounds value to desired min/max set by class (if any) i(RR(RRrtmndtmxd((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cCs|s t|j}d}t|trd|koDdknsOt|jdkrtd|>}d}nt||}n|dkrt|tst|||t}|||t}|j ||j |fS(s helper for :meth:`_generate_rounds` -- returns range for vary rounds generation. :returns: (lower, upper) limits suitable for random.randint() cSs|S(N((Rstupper((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytlinear_to_nativesiitlog2cSsO|dkrdS|r,ttj|dSttjtj|dSdS(Nii(R5R4R6tceil(RsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  ( RdRRYRt rounds_costR5R#RR{R(RRqRRtlowerR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_calc_vary_rounds_ranges   "  !cKstt|j||dk r4|j|}nL|jrt|j}|j||kstd|fn t d||_ dS(Nsgenerated invalid rounds: %rsno rounds specified( RR1RRgt _parse_roundsRt_generate_roundsRRdRRr(RRrRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   + cCs |j|S(N(R(RRr((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR sRrc Cs%t|||j|jd|d|S(s helper for normalizing rounds value. :arg rounds: an integer cost parameter. :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :raises TypeError: * if ``use_defaults=False`` and no rounds is specified * if rounds is not an integer. :raises ValueError: * if rounds is ``None`` and class does not specify a value for :attr:`default_rounds`. * if ``relaxed=False`` and rounds is outside bounds of :attr:`min_rounds` and :attr:`max_rounds` (if ``relaxed=True``, the rounds value will be clamped, and a warning issued). :returns: normalized rounds value RwR(RRR(RRrRRw((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCs|j}|dkr.td|jfn|jr|j|\}}||koc|knsnt||krtj||}qn|S(s internal helper for :meth:`_norm_rounds` -- returns default rounds value, incorporating vary_rounds, and any other limitations hash may place on rounds parameter. s,%s rounds value must be specified explicitlyN( RqRgRRFRR RdR trandint(RRrR R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   " cKsZ|j}|r"|j|kr"tS|j}|rD|j|krDtStt|j|S(sR mark hash as needing update if rounds is outside desired bounds. (RRrR{RRR1R(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)s  g?cKstt|j|}|jdkr{ddl}|dkrK|j}ntdtd|j ||d|dtbackend((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR=j s   ( R;RRRR7RR%R9R=(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR2 s +  cBs[eZdZd2Zededed3d3dZd3Zd3Z dZ dZ e e Z eZe dZeZe dZd4ZdZdZd Zd!Zd"Zd#Zd3Zd$Zd%Zd&Zed'd(d)d*d+Zed'd(d)d*d,Zed'd(d)d*d-d.d/Z d0Z!d1Z"RS(5sUwraps another handler, adding a constant prefix. instances of this class wrap another password hash handler, altering the constant prefix that's prepended to the wrapped handlers' hashes. this is used mainly by the :doc:`ldap crypt ` handlers; such as :class:`~passlib.hash.ldap_md5_crypt` which wraps :class:`~passlib.hash.md5_crypt` and adds a ``{CRYPT}`` prefix. usage:: myhandler = PrefixWrapper("myhandler", "md5_crypt", prefix="$mh$", orig_prefix="$1$") :param name: name to assign to handler :param wrapped: handler object or name of registered handler :param prefix: identifying prefix to prepend to all hashes :param orig_prefix: prefix to strip (defaults to ''). :param lazy: if True and wrapped handler is specified by name, don't look it up until needed. R<cCs@||_t|tr*|jd}n||_t|trT|jd}n||_|ro||_nt|dr|j|n||_ |s|j n|dk r<|t kr|r|}qt dnt|tr|jd}n|t| |t| kr0t dn||_ndS(NRcRFsno prefix specifiedsident must agree with prefix(RFRYR_R`Rit orig_prefixRR;t _set_wrappedt _wrapped_namet _get_wrappedRgR{RR7t_ident(RRFtwrappedRiRCtlazytdocRy((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s0          cCsBd|jkr5|jr5td|jftjn||_dS(NRyskPrefixWrapper: 'orig_prefix' option may not work correctly for handlers which have multiple identifiers: %r(RRCRRFRZtPasslibRuntimeWarningt_wrapped_handler(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRD scCs8|j}|dkr4t|j}|j|n|S(N(RLRgRRERD(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRF s   cCsp|j}|tkrld}|js`|j}t|dd}|dk r`|j|}q`n||_n|S(NRy(RGRRgRCRHRt _wrap_hash(RRsRHRy((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRy s      cswj}|tkrsd}jsgj}t|dd}|rgtfd|D}qgn|_n|S(NRc3s|]}j|VqdS(N(RM(RORy(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys s(t _ident_valuesRRgRCRHRttuple(RRsRHtidents((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s    " RRSRqRRR RRRRRRRRRRRRt is_disabledRRRRcCs{t|jp|jg}|jr;|jd|jn|jr[|jd|jndj|}d|j|fS(Ns prefix=%rsorig_prefix=%rs, sPrefixWrapper(%r, %s)(treprRERLRiR/RCtjoinRF(Rtargs((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__repr__ s  csXtt|j}|j|j|j|jfd|jDt|S(Nc3s$|]}t|r|VqdS(N(R;(ROtattr(RH(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys  s(RRtdirRtupdateR,RHt _proxy_attrsRT(Rtattrs((RHs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__dir__ s  cCs6||jkrt|j|Std|fdS(sFproxy most attributes from wrapped class (e.g. rounds, salt size, etc)smissing attribute: %rN(RYRRHR(RRV((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt __getattr__ scCsZ||jkrG|jrG|j}t||rGt|||dSntj|||S(N(RYt _derived_fromRHR;tsetattrRt __setattr__(RRVRsRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR_ s  cCs?|j}|j|s*tj|n|j|t|S(s4given hash belonging to wrapper, return orig version(RiRARZReRCR7(RR^Ri((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _unwrap_hash+ s cCsot|tr!|jd}n|j}|j|sNtj|jn|j|t |}t |S(s0given orig hash; return one belonging to wrapperRc( RYR_R`RCRARZReRHRiR7R(RR^RCRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRM4 s cKs|jj|}||jk s'tt|j|d|jd|j}||_x*|jD]}t ||t ||q^W|S(NRiRC( RHRRdR3RFRiRCR]t_using_clone_attrsR^R(RRLRtwrapperRV((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRC s$ cKs"|j|}|jj||S(N(R`RHR(RR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRN scCsAt|}|j|js"tS|j|}|jj|S(N(RbRARiRR`RHR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRR s  Rs1.7Rs2.0cKs:|jj|}|dkr-tdn|j|S(Ns+.genconfig() must return a string, not None(RHRRgRARM(RRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRY s cKsO|dk r0t|dd}|j|}n|j|jj|||S(NRcs config/hash(RgR R`RMRHR(RRXRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR` s t replacements.hash()cKs|j||S(N(R^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytencrypth scKs|j|jj||S(N(RMRHR^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^l scKs7t|dd}|j|}|jj|||S(NRcR^(R R`RHR(RRXR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRo s(N(s setting_kwdss context_kwdssdefault_roundss min_roundss max_roundss rounds_costsmin_desired_roundssmax_desired_roundss vary_roundssdefault_salt_sizes min_salt_sizes max_salt_sizes salt_charssdefault_salt_charssbackendss has_backends get_backends set_backendRQs truncate_sizestruncate_errorstruncate_verify_rejects_salt_is_bytes(#R;RRRaRRRgRRERLRDRFRRHRGRyRNRRYRUR[R\R_R`RMR]RRRR%RRRdR^R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR3 sJ      $ (cRt __future__RR=tloggingt getLoggerR;R6R4t threadingtwarningsRt passlib.excRZt passlib.ifctifcRRRRtpasslib.registryRt passlib.utilsRRR R R R R RRRRRRRRRRRRtpasslib.utils.compatRRRRRRRR R!R"R#tpasslib.utils.decorR$R%t__all__t H64_CHARSt B64_CHARStPADDED_B64_CHARSt UC_HEX_CHARSt LC_HEX_CHARSR:RGRMRUt_UDOLLARRnR]RbRgR&R'RxR(R)R}RRRRR*R+RR,R-R.R/R0R1RtRLockRRR)R2RR3(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyts    L4R        J! &!*Z '&xH N|pbkdf2.pyc000064400000013743147221702050006441 0ustar00 5Xc @ sdZddlmZddlZejeZddlmZddl m Z ddl m Z ddl mZmZmZmZmZdd d d gZdd lmZed ee dddddeddeZiadZdZdddZdddZdS(spasslib.pbkdf2 - PBKDF2 support this module is getting increasingly poorly named. maybe rename to "kdf" since it's getting more key derivation functions added. i(tdivisionN(tExpectedTypeError(tdeprecated_function(tnative_string_types(tnorm_hash_namet lookup_hashtpbkdf1t pbkdf2_hmact compile_hmacRtget_prfRtpbkdf2(twarnsthe module 'passlib.utils.pbkdf2' is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0, please use 'passlib.crypto' insteadt deprecateds1.7tremoveds1.8t func_modulet replacements$passlib.crypto.digest.norm_hash_namethmac_shmac-c s|tkrt|St|tr|jtsHtd|fnt|djfd}||jj f}nBt |rt |dd}||f}nt |dd|t|<|S(sLookup pseudo-random family (PRF) by name. :arg name: This must be the name of a recognized prf. Currently this only recognizes names with the format :samp:`hmac-{digest}`, where :samp:`{digest}` is the name of a hash function such as ``md5``, ``sha256``, etc. todo: restore text about callables. :raises ValueError: if the name is not known :raises TypeError: if the name is not a callable or string :returns: a tuple of :samp:`({prf_func}, {digest_size})`, where: * :samp:`{prf_func}` is a function implementing the specified PRF, and has the signature ``prf_func(secret, message) -> digest``. * :samp:`{digest_size}` is an integer indicating the number of bytes the function returns. Usage example:: >>> from passlib.utils.pbkdf2 import get_prf >>> hmac_sha256, dsize = get_prf("hmac-sha256") >>> hmac_sha256 >>> dsize 32 >>> digest = hmac_sha256('password', 'message') .. deprecated:: 1.7 This function is deprecated, and will be removed in Passlib 2.0. This only related replacement is :func:`passlib.crypto.digest.compile_hmac`. sunknown prf algorithm: %ric st||S(N(R(tkeytmsg(tdigest(s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pythmachstxtysstr or callablesprf name( t _prf_cachet isinstanceRt startswitht_HMAC_PREFIXESt ValueErrorRtnamet digest_infot digest_sizetcallabletlenR(RRtrecordR((Rs8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyR 9s)   tsha1cC st|||||S(sLpkcs#5 password-based key derivation v1.5 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate (if ``None``, uses digest's native size) :param hash: hash function to use. must be name of a hash recognized by hashlib. :returns: raw bytes of generated key .. note:: This algorithm has been deprecated, new code should use PBKDF2. Among other limitations, ``keylen`` cannot be larger than the digest size of the specified hash. .. deprecated:: 1.7 This has been relocated to :func:`passlib.crypto.digest.pbkdf1`, and this version will be removed in Passlib 2.0. *Note the call signature has changed.* (t_pbkdf1(tsecrettsalttroundstkeylenthash((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyRwss hmac-sha1cC sZt|s+t|tr:|jt r:tdn|d}t|||||S(sWpkcs#5 password-based key derivation v2.0 :arg secret: passphrase to use to generate key :arg salt: salt string to use when generating key :param rounds: number of rounds to use to generate key :arg keylen: number of bytes to generate. if set to ``None``, will use digest size of selected prf. :param prf: psuedo-random family to use for key strengthening. this must be a string starting with ``"hmac-"``, followed by the name of a known digest. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in the PBKDF2 specification) .. rst-class:: warning .. versionchanged 1.7: This argument no longer supports arbitrary PRF callables -- These were rarely / never used, and created too many unwanted codepaths. :returns: raw bytes of generated key .. deprecated:: 1.7 This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`, and will be removed in Passlib 2.0. *Note the call signature has changed.* s1non-HMAC prfs are not supported as of Passlib 1.7i(RRRRRtNotImplementedErrorR(R$R%R&R'tprfR((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyR s%+ (Rshmac-(t__doc__t __future__Rtloggingt getLoggert__name__tlogt passlib.excRtpasslib.utils.decorRtpasslib.utils.compatRtpasslib.crypto.digestRRRR#RRt__all__twarningsR tDeprecationWarningRRR tNoneR (((s8/usr/lib/python2.7/site-packages/passlib/utils/pbkdf2.pyts* (  >des.pyc000064400000003052147221702050006034 0ustar00 5Xc@sdZddlmZededdlmZddlmZmZm Z edddd d d eZedddd d d eZedddd d d e Z ddl Z e j dj Z edddd d ddddZdS(st passlib.utils.des - DEPRECATED LOCATION, WILL BE REMOVED IN 2.0 This has been moved to :mod:`passlib.crypto.des`. i(twarnsthe 'passlib.utils.des' module has been relocated to 'passlib.crypto.des' as of passlib 1.7, and the old location will be removed in passlib 2.0(tdeprecated_function(texpand_des_keytdes_encrypt_blocktdes_encrypt_int_blockt deprecateds1.7tremoveds1.8t replacements!passlib.crypto.des.expand_des_keys$passlib.crypto.des.des_encrypt_blocks(passlib.crypto.des.des_encrypt_int_blockNs>Qs1.6s*passlib.crypto.des.des_encrypt_int_block()iicCsVt|trCt|dkr0t|}nt|d}nt||||S(Nii(t isinstancetbytestlenRt_unpack_uint64R(tkeytinputtsalttrounds((s5/usr/lib/python2.7/site-packages/passlib/utils/des.pytmdes_encrypt_int_block#s (t__doc__twarningsRtDeprecationWarningtpasslib.utils.decorRtpasslib.crypto.desRRRtstructtStructtunpackR R(((s5/usr/lib/python2.7/site-packages/passlib/utils/des.pyts  decor.py000064400000016743147221702050006225 0ustar00""" passlib.utils.decor -- helper decorators & properties """ #============================================================================= # imports #============================================================================= # core from __future__ import absolute_import, division, print_function import logging log = logging.getLogger(__name__) from functools import wraps, update_wrapper import types from warnings import warn # site # pkg from passlib.utils.compat import PY3 # local __all__ = [ "classproperty", "hybrid_method", "memoize_single_value", "memoized_property", "deprecated_function", "deprecated_method", ] #============================================================================= # class-level decorators #============================================================================= class classproperty(object): """Function decorator which acts like a combination of classmethod+property (limited to read-only properties)""" def __init__(self, func): self.im_func = func def __get__(self, obj, cls): return self.im_func(cls) @property def __func__(self): """py3 compatible alias""" return self.im_func class hybrid_method(object): """ decorator which invokes function with class if called as class method, and with object if called at instance level. """ def __init__(self, func): self.func = func update_wrapper(self, func) def __get__(self, obj, cls): if obj is None: obj = cls if PY3: return types.MethodType(self.func, obj) else: return types.MethodType(self.func, obj, cls) #============================================================================= # memoization #============================================================================= def memoize_single_value(func): """ decorator for function which takes no args, and memoizes result. exposes a ``.clear_cache`` method to clear the cached value. """ cache = {} @wraps(func) def wrapper(): try: return cache[True] except KeyError: pass value = cache[True] = func() return value def clear_cache(): cache.pop(True, None) wrapper.clear_cache = clear_cache return wrapper class memoized_property(object): """ decorator which invokes method once, then replaces attr with result """ def __init__(self, func): self.__func__ = func self.__name__ = func.__name__ self.__doc__ = func.__doc__ def __get__(self, obj, cls): if obj is None: return self value = self.__func__(obj) setattr(obj, self.__name__, value) return value if not PY3: @property def im_func(self): """py2 alias""" return self.__func__ def clear_cache(self, obj): """ class-level helper to clear stored value (if any). usage: :samp:`type(self).{attr}.clear_cache(self)` """ obj.__dict__.pop(self.__name__, None) def peek_cache(self, obj, default=None): """ class-level helper to peek at stored value usage: :samp:`value = type(self).{attr}.clear_cache(self)` """ return obj.__dict__.get(self.__name__, default) # works but not used ##class memoized_class_property(object): ## """function decorator which calls function as classmethod, ## and replaces itself with result for current and all future invocations. ## """ ## def __init__(self, func): ## self.im_func = func ## ## def __get__(self, obj, cls): ## func = self.im_func ## value = func(cls) ## setattr(cls, func.__name__, value) ## return value ## ## @property ## def __func__(self): ## "py3 compatible alias" #============================================================================= # deprecation #============================================================================= def deprecated_function(msg=None, deprecated=None, removed=None, updoc=True, replacement=None, _is_method=False, func_module=None): """decorator to deprecate a function. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when function was first deprecated :kwd removed: version when function will be removed :kwd replacement: alternate name / instructions for replacing this function. :kwd updoc: add notice to docstring (default ``True``) """ if msg is None: if _is_method: msg = "the method %(mod)s.%(klass)s.%(name)s() is deprecated" else: msg = "the function %(mod)s.%(name)s() is deprecated" if deprecated: msg += " as of Passlib %(deprecated)s" if removed: msg += ", and will be removed in Passlib %(removed)s" if replacement: msg += ", use %s instead" % replacement msg += "." def build(func): is_classmethod = _is_method and isinstance(func, classmethod) if is_classmethod: # NOTE: PY26 doesn't support "classmethod().__func__" directly... func = func.__get__(None, type).__func__ opts = dict( mod=func_module or func.__module__, name=func.__name__, deprecated=deprecated, removed=removed, ) if _is_method: def wrapper(*args, **kwds): tmp = opts.copy() klass = args[0] if is_classmethod else args[0].__class__ tmp.update(klass=klass.__name__, mod=klass.__module__) warn(msg % tmp, DeprecationWarning, stacklevel=2) return func(*args, **kwds) else: text = msg % opts def wrapper(*args, **kwds): warn(text, DeprecationWarning, stacklevel=2) return func(*args, **kwds) update_wrapper(wrapper, func) if updoc and (deprecated or removed) and \ wrapper.__doc__ and ".. deprecated::" not in wrapper.__doc__: txt = deprecated or '' if removed or replacement: txt += "\n " if removed: txt += "and will be removed in version %s" % (removed,) if replacement: if removed: txt += ", " txt += "use %s instead" % replacement txt += "." if not wrapper.__doc__.strip(" ").endswith("\n"): wrapper.__doc__ += "\n" wrapper.__doc__ += "\n.. deprecated:: %s\n" % (txt,) if is_classmethod: wrapper = classmethod(wrapper) return wrapper return build def deprecated_method(msg=None, deprecated=None, removed=None, updoc=True, replacement=None): """decorator to deprecate a method. :arg msg: optional msg, default chosen if omitted :kwd deprecated: version when method was first deprecated :kwd removed: version when method will be removed :kwd replacement: alternate name / instructions for replacing this method. :kwd updoc: add notice to docstring (default ``True``) """ return deprecated_function(msg, deprecated, removed, updoc, replacement, _is_method=True) #============================================================================= # eof #=============================================================================