diff --git a/src/app/formatxml.py b/src/app/formatxml.py new file mode 100644 index 00000000..6ed590c9 --- /dev/null +++ b/src/app/formatxml.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +# +# quick-n-dirty formatter for SPDX licenses in XML format +# +# Copyright (c) 2017 Alexios Zavras +# SPDX-License-Identifier: MIT +# + +#----------------------------------------------------------------- +# configuration parameters, self-explanatory :-) +# they are simply defaults; can be overwritten by command-line options + +INDENT = 2 +LINE_LENGTH = 80 + +# which tags are inline and which appear on their own lines +TAGS_inline = [ + 'alt', + 'b', + 'br', + 'copyright', + 'url', + + 'crossRef', + 'bullet', + + ] +TAGS_block = [ + 'body', + 'header', + 'li', + 'license', + 'list', + 'notes', + 'optional', + 'p', + 'SPDX', + 'title', + 'urls', + + 'SPDXLicenseCollection', + 'license', + 'crossRefs', + 'standardLicenseHeader', + 'notes', + 'titleText', + 'item', + 'copyrightText', + 'text' + + ] + +# attributes for tags, in the order we want them to appear +ATTRS_SEQ = { + 'SPDXLicenseCollection': [ + 'xmlns', + ], + 'license': [ + 'isOsiApproved', + 'licenseId', + 'name', + 'listVersionAdded', + ], + 'alt': [ + 'name', + 'match', + ], + } + +# namespace for all tags +NAMESPACE_URL = 'http://www.spdx.org/license' +NAMESPACE='{http://www.spdx.org/license}' + +#----------------------------------------------------------------- + +VERSION = '1.0' + +import argparse +import datetime +import logging +import re +import shutil +import sys +import xml.etree.ElementTree as et + +NL = '\n' +XML_PROLOG = """""" + +logging.basicConfig(filename="error.log", format="%(levelname)s : %(asctime)s : %(message)s") +logger = logging.getLogger() + +def process(fname): + tree = et.parse(fname) + root = tree.getroot() + if root.tag == 'spdx': + root.tag = 'SPDX' + logger.error('changing root element to SPDX (capital letters)') + #ts = '{:%Y%m%d%H%M%S%z}'.format(datetime.datetime.now()) + root.set('xmlns', NAMESPACE_URL) + blocks = pretty(root, 0) + ser = fmt(blocks) + + with open(fname, 'w') as f: + f.write(XML_PROLOG+"\n") + f.write(ser) + + + +def pretty(node, level): + ser = '' + tag = node.tag + if tag.startswith(NAMESPACE): + tag = tag[len(NAMESPACE):] + text = singlespaceline(node.text) + tail = singlespaceline(node.tail) + # print("\t", level, tag, 'text=', text, 'tail=', tail, node.attrib) + start_tag = "<" + tag + if node.attrib: + for a in ATTRS_SEQ[tag]: + if a in node.attrib: + start_tag += ' {}="{}"'.format(a, node.attrib[a]) + del node.attrib[a] + if node.attrib: + logger.error('more attrs remaining in {}: {}'.format(tag, node.attrib.keys())) + start_tag += ">" + end_tag = "" + if tag in config['block']: + child_level = level + 1 + before = '{0}{1}#{2}{0}{3}#'.format(NL, level, start_tag, child_level) + after = '{0}{1}#{2}{0}'.format(NL, level, end_tag) + elif tag in config['inline']: + child_level = level + before = start_tag + after = '{1}{0}{2}#'.format(NL, end_tag, level) + else: + logger.error('Tag "{}" neither block nor inline!'.format(tag)) + child_level = level + before = start_tag + after = end_tag + ser += before + if text: + text = text.replace('&', '&').replace('>', '>').replace('<', '<') + ser += text + for child in node: + ser += pretty(child, child_level) + ser += after + if tail: + ser += tail + ser = ser.replace('\n\n', '\n') + return ser + +def fmt(blocks): + bregexp = re.compile(r'((?P\d+)#)?(?P.*)') + ser = '' + for line in blocks.split('\n'): + if line == '': + continue + m = bregexp.match(line) + if m.group('level'): + l = int(m.group('level')) + else: + logger.error('Block without level: "{}"'.format(line)) + par = m.group('paragraph') + if par == '': + continue + indent = l * config['lvl_indent'] + width = config['max_width'] - indent + for fmtline in to_lines(par, width): + ser += indent * ' ' + fmtline + '\n' + return ser + + +def to_lines(text, width): + words = text.split() + count = len(words) + last_offset = 0 + offsets = [last_offset] + for w in words: + last_offset += len(w) + offsets.append(last_offset) + + cost = [0] + [10 ** 20] * count + breaks = [0] + [0] * count + for i in range(count): + j = i + 1 + while j <= count: + w = offsets[j] - offsets[i] + j - i - 1 + if w > width: + break + penalty = cost[i] + (width - w) ** 2 + if penalty < cost[j]: + cost[j] = penalty + breaks[j] = i + j += 1 + lines = [] + last = count + while last > 0: + first = breaks[last] + lines.append(' '.join(words[first:last])) + last = first + lines.reverse() + return lines + + +def singlespaceline(txt): + if txt: + txt = txt.strip() + txt = re.sub(r'\s+', ' ', txt) + return txt + + +# main program + +if NAMESPACE: + full_TAGS_inline = list(NAMESPACE+e for e in TAGS_inline) + full_TAGS_block = list(NAMESPACE+e for e in TAGS_block) + full_ATTRS_SEQ = dict((NAMESPACE+k, v) for k,v in ATTRS_SEQ.items()) + +if __name__ == '__main__': + + parser = argparse.ArgumentParser( + description='Indent XML file(s)') + parser.add_argument('filename', nargs='+', + help='the XML files to process') + parser.add_argument('-w', '--width', action='store', type=int, + default = LINE_LENGTH, + help='the maximum width of the lines in output') + parser.add_argument('-i', '--indent', action='store', type=int, + default = INDENT, + help='the number of spaces each level is indented') + parser.add_argument('--inline-tags', action='store', + help='space-separated list of tags to be rendered inline') + parser.add_argument('--block-tags', action='store', + help='space-separated list of tags to be rendered as blocks') + parser.add_argument('-V', '--version', action='version', + version='%(prog)s ' + VERSION, + help='print the program version') + + args = parser.parse_args() + + config = dict() + config['inline'] = TAGS_inline + config['block'] = TAGS_block + config['max_width'] = args.width + config['lvl_indent'] = args.indent + if args.inline_tags: + config['inline'] = args.inline_tags.split() + if args.block_tags: + config['block'] = args.block_tags.split() + + for fname in args.filename: + try: + process(fname) + except et.ParseError as e: + logger.error('XML Parse Error: ' + str(e)) + print('XML Parse Error: ' + str(e)) diff --git a/src/app/generateXml.py b/src/app/generateXml.py new file mode 100644 index 00000000..781ef54e --- /dev/null +++ b/src/app/generateXml.py @@ -0,0 +1,156 @@ +import math +import os +import re +import subprocess +import xml.etree.ElementTree as ET +from itertools import chain, izip, tee + +entityMap = { + '>': '>', + '<': '<', + "'": ''', + '"': '"', + '&': '&' +} +letterBullets = r"^(\s*)([^\s\w]?(?!(v|V) ?\.)(?:[a-zA-Z]|[MDCLXVImdclxvi]+)[^\s\w])(\s)" +numberBullets = r"^(\s*)([^\s\w]?[0-9]+[^\s\w]|[^\s\w]?[0-9]+(?:\.[0-9]+)[^\s\w]?)(\s)" +symbolBullets = r"^(\s*)([*\u2022\-])(\s)" + + +def previous_and_current(some_iterable): + prevs, items = tee(some_iterable, 2) + prevs = chain([None], prevs) + return izip(prevs, items) + + +def escapeXmlData(string): + for initial,final in entityMap.items(): + string.replace(initial, final) + return string + + +def isBullet(string): + """ To check if the line has bullet or not. + """ + isLetterBullet = re.search(letterBullets, string) + isNumberBullet = re.search(numberBullets, string) + isSymbolBullet = re.search(symbolBullets, string) + if isLetterBullet or isNumberBullet or isSymbolBullet: + return True + return False + + +def wrapBullets(string, item): + """ Wrap bullets around the bullet tags. + """ + letterBullet = re.search(letterBullets, string) + numberBullet = re.search(numberBullets, string) + symbolBullet = re.search(symbolBullets, string) + bullet = letterBullet or numberBullet or symbolBullet + ET.SubElement(item, "bullet").text = bullet.group(2) + string = string.replace(bullet.group(2), '').strip() + return string + + +def groupLines(lines): + """ Creates a list of dictionary of each line containing data, tagType and depth of the line. + """ + lis = [] + for line in lines: + if isBullet(line): + line = re.sub(r"\t", ' ', line) + matches = re.search(r"^( *)", line).group(1) + if not matches: + depth = 0 + else: + depth = int(math.floor(len(matches)/4)) + tagType = 'item' + lis.append({'data':line, 'depth':depth, 'tagType':tagType}) + else: + tagType = 'p' + lis.append({'data':line, 'tagType':tagType}) + return lis + + +def insertOls(lines): + """ Insert dictionary of tagType list before the the begining and after the ending of a list. + """ + depth = -1 + newLines = [] + for line in lines: + if isBullet(line.get('data')): + if line.get('depth') < depth: + while line.get('depth') < depth: + newLines.append({ 'tagType': 'list', 'isStart': False, 'data': '' }) + depth -= 1 + elif line.get('depth') > depth: + while line.get('depth') > depth: + newLines.append({ 'tagType': 'list', 'isStart': True, 'data': '' }) + depth += 1 + newLines.append(line) + while 0 <= depth: + newLines.append({ 'tagType': 'list', 'isStart': False, 'data': '' }) + depth -= 1 + #newLines.append({ 'tagType': 'list', 'isStart': False, 'data': '' }) + return newLines + + +def getTextElement(points): + """ Returns the text element of the license XML. + """ + licenseTextElement = ET.Element("text") + elements = [] + elements.append(licenseTextElement) + for pp,point in previous_and_current(points): + if point.get('isStart'): + elements.append(ET.Element("list")) + + elif point.get('isStart') is False: + n = len(elements) + if elements[n-2].findall('item'): + elements[n-2].findall('item')[-1].append(elements[n-1]) + else: + elements[n-2].append(elements[n-1]) + elements.pop() + else: + if pp: + if point.get('tagType') == "p" and pp.get('tagType') == "item": + p = ET.Element("p") + p.text = point.get('data') + elements[-1].findall('item')[-1].append(p) + continue + if point.get('tagType') == "p": + p = ET.Element("p") + p.text = point.get('data') + elements[-1].append(p) + + elif point.get('tagType') == "item": + item = ET.Element("item") + ET.SubElement(item, "p").text = wrapBullets(point.get('data'), item) + elements[-1].append(item) + return elements[0] + + +def generateLicenseXml(licenseOsi, licenseIdentifier, licenseName, listVersionAdded, licenseSourceUrls, licenseHeader, licenseNotes, licenseText): + """ Generate a spdx license xml + returns the license xml as a string + """ + root = ET.Element("SPDXLicenseCollection", xmlns="http://www.spdx.org/license") + if licenseOsi=="Approved": + licenseOsi = "true" + else: + licenseOsi = "false" + license = ET.SubElement(root, "license", isOsiApproved=licenseOsi, licenseId=licenseIdentifier, name=licenseName, listVersionAdded=listVersionAdded) + crossRefs = ET.SubElement(license, "crossRefs") + for sourceUrl in licenseSourceUrls: + ET.SubElement(crossRefs, "crossRef").text = sourceUrl + ET.SubElement(license, "standardLicenseHeader").text = licenseHeader + ET.SubElement(license, "notes").text = licenseNotes + licenseText = escapeXmlData(licenseText) + licenseLines = licenseText.replace('\r','').split('\n\n') + objList = groupLines(licenseLines) + points = insertOls(objList) + textElement = getTextElement(points) + license.append(textElement) + xmlString = ET.tostring(root, method='xml') + return xmlString diff --git a/src/app/static/js/editor/script.js b/src/app/static/js/editor/script.js index 0c7bb3e0..a0c9094c 100644 --- a/src/app/static/js/editor/script.js +++ b/src/app/static/js/editor/script.js @@ -91,7 +91,7 @@ var xml_schema = { * initialXmlText: contains initial xml text, global variable * latestXmlText: contains updated and valid xml text , global variable */ -var editor = "", splitTextEditor = "", initialXmlText = "", latestXmlText = ''; +var editor = "", splitTextEditor = "", initialXmlText = "", latestXmlText = '', beautifiedXmlText = ''; $(document).ready(function(){ /* initialize bootstrap tooltip */ $('[data-toggle="tooltip"]').tooltip(); @@ -159,8 +159,10 @@ $(document).ready(function(){ $(".CodeMirror").css("font-size",fontSize+'px'); editor.setSize(($(window).width)*(0.9), 500); splitTextEditor.setSize(($(".splitTextEditorContainer").width)*(0.9), 550); - initialXmlText = beautify(editor.getValue().trim()); - latestXmlText = beautify(editor.getValue().trim()); + beautify(editor.getValue().trim()); + initialXmlText = beautifiedXmlText; + beautify(editor.getValue().trim()); + latestXmlText = beautifiedXmlText; /* Decrease editor font size */ $("#dec-fontsize").click(function(){ @@ -230,7 +232,8 @@ $(document).ready(function(){ /* beautify XML */ $("#beautify").on("click",function(){ var xmlText = editor.getValue().trim(); - editor.setValue(beautify(xmlText)); + beautify(xmlText); + editor.setValue(beautifiedXmlText); editor.focus(); }) @@ -268,7 +271,8 @@ $(document).ready(function(){ $('#tabSplitView, #tabTreeEditor').removeAttr("data-toggle"); $(this).attr("data-toggle","tab"); /* update the text editor with the value of split view editor */ - latestXmlText = beautify(splitTextEditor.getValue().trim()); + beautify(splitTextEditor.getValue().trim()); + latestXmlText = beautifiedXmlText; editor.setValue(latestXmlText); /* refresh and focus on the editor */ setTimeout(function(){ @@ -287,7 +291,8 @@ $(document).ready(function(){ $(this).attr("data-toggle","tab"); /* convert the xml text to tree and update latestXmlText */ convertTextToTree(editor, 'treeView') - latestXmlText = beautify(editor.getValue().trim()); + beautify(editor.getValue().trim()); + latestXmlText = beautifiedXmlText; } else if(activeTab=='tabSplitView'){ /* check for any open textboxes */ @@ -297,7 +302,8 @@ $(document).ready(function(){ $(this).attr("data-toggle","tab"); /* convert the xml text in split editor to tree and update latestXmlText */ convertTextToTree(splitTextEditor, 'treeView') - latestXmlText = beautify(splitTextEditor.getValue().trim()); + beautify(splitTextEditor.getValue().trim()); + latestXmlText = beautifiedXmlText; } } }) @@ -327,7 +333,9 @@ $(document).ready(function(){ $('#tabTreeEditor, #tabTextEditor').removeAttr("data-toggle"); $(this).attr("data-toggle","tab"); /* update the split text editor with the value of text editor */ - latestXmlText = beautify(editor.getValue().trim()); + currentXmlText = editor.getValue().trim(); + beautify(currentXmlText); + latestXmlText = beautifiedXmlText; splitTextEditor.setValue(latestXmlText); /* use the text in split text editor to updated split tree editor */ convertTextToTree(splitTextEditor, 'splitTreeView'); @@ -573,7 +581,8 @@ function makePR(){ xmlText = latestXmlText } /* send ajax request with form data */ - xmlText = beautify(xmlText); + beautify(xmlText); + xmlText = beautifiedXmlText; var form = new FormData($("#githubPRForm")[0]); form.append("branchName", $("#branchName").val()); form.append("updateUpstream", $("#updateUpstream").is(":checked")); @@ -650,72 +659,42 @@ function generate_diff(base, newtxt){ $(".modal-dialog").addClass("diff-modal-dialog"); } +function getCookie(name) { + var value = "; " + document.cookie; + var parts = value.split("; " + name + "="); + if (parts.length == 2) return parts.pop().split(";").shift(); +} + + /* XML beautify script */ function beautify(text){ - var shift = ['\n'], i; - for(i=0;i<100;i++){ - shift.push(shift[i]+' '); - } - var array = text.replace(/>\s{0,}<") - .replace(/\s{0,} or -1){ - str += shift[deep]+array[i]; - inComment = true; - // if end comment or // - if(array[i].search(/-->/) > -1 || array[i].search(/\]>/) > -1 || array[i].search(/!DOCTYPE/) > -1 ){ - inComment = false; + csrf = getCookie('csrftoken'); + $.ajax({ + type: "POST", + url: "/app/beautify/", + dataType: 'json', + timeout: 600000, + async: false, + data: { + "xml" : text, + "csrfmiddlewaretoken" : csrf, + }, + success: function(data) { + beautifiedXmlText = data.data.toString(); + }, + error: function (e) { + try { + //var obj = JSON.parse(e.responseText); + console.log(e); + //displayModal(obj.data, "error"); + beautifiedXmlText = text; + } + catch (e){ + console.log(e) + displayModal(e,"error"); } - } - /* end comment or */ - else if(array[i].search(/-->/)>-1 || array[i].search(/\]>/) > -1){ - str += array[i]; - inComment = false; - } - /* */ - else if( /^<\w/.exec(array[i-1]) && /^<\/\w/.exec(array[i]) && - /^<[\w:\-\.\,]+/.exec(array[i-1]) == /^<\/[\w:\-\.\,]+/.exec(array[i])[0].replace('/','')){ - str += array[i]; - if(!inComment) deep--; - } - /* */ - else if(array[i].search(/<\w/) > -1 && array[i].search(/<\//) == -1 && array[i].search(/\/>/) == -1 ){ - str = !inComment ? str += shift[deep++]+array[i] : str += array[i]; - } - /* ... */ - else if(array[i].search(/<\w/) > -1 && array[i].search(/<\//) > -1){ - str = !inComment ? str += shift[deep]+array[i] : str += array[i]; - } - /* */ - else if(array[i].search(/<\//) > -1){ - str = !inComment ? str += shift[--deep]+array[i] : str += array[i]; - } - /* */ - else if(array[i].search(/\/>/) > -1 ){ - str = !inComment ? str += shift[deep]+array[i] : str += array[i]; - } - /* */ - else if(array[i].search(/<\?/) > -1){ - str += shift[deep]+array[i]; - } - /* xmlns */ - else if( array[i].search(/xmlns\:/) > -1 || array[i].search(/xmlns\=/) > -1){ - str += ' '+array[i]; - } - else { - str += array[i]; } - } - return (str[0] == '\n') ? str.slice(1) : str; + }); } /* display message using modal */ diff --git a/src/app/static/js/editor/treeview.js b/src/app/static/js/editor/treeview.js index fb72b688..475af1e5 100644 --- a/src/app/static/js/editor/treeview.js +++ b/src/app/static/js/editor/treeview.js @@ -352,7 +352,8 @@ function updateTextEditor(textEditor, treeEditor){ /* call convert function */ convertTreeToText($("#"+treeEditor)); /* update text editor */ - textEditor.setValue(beautify(new_xml)); + beautify(new_xml); + textEditor.setValue(beautifiedXmlText); textEditor.refresh(); return new_xml; } diff --git a/src/app/tests.py b/src/app/tests.py index 501f384c..861c96ab 100644 --- a/src/app/tests.py +++ b/src/app/tests.py @@ -20,7 +20,7 @@ from app.models import UserID from app.models import LicenseRequest, LicenseNamespace -from app.utils import generateLicenseXml +from app.generateXml import generateLicenseXml from django.contrib.auth.models import User from django.contrib.auth import authenticate from social_django.models import UserSocialAuth @@ -750,7 +750,7 @@ def test_split_tree_editor_attributes(self): driver.execute_script("document.getElementById('modalOk').click()") time.sleep(0.5) driver.execute_script("document.getElementById('tabTextEditor').click()") - finalXML = driver.execute_script("var xml = ''; var codemirror = document.querySelectorAll('pre.CodeMirror-line'); for (var i=1;i","> ") self.assertEqual(self.xml, xml) @skipIf(not getAccessToken() and not getGithubUserId() and not getGithubUserName(), "You need to set gihub parameters in the secret.py file for this test to be executed properly.") @@ -1310,7 +1310,7 @@ def test_promote_license_namespace_feature(self): table_contents = driver.find_element_by_css_selector('tbody').text self.assertEquals(table_contents, "No data available in table") xml = generateLicenseXml('', "0BSD", "BSD Zero Clause License-00", - '', "http://wwww.spdx.org", '', '', '') + '', ["http://wwww.spdx.org"], '', '', '') license_obj = LicenseNamespace.objects.create(fullname="BSD Zero Clause License-00", licenseAuthorName="John Doe", shortIdentifier="0BSD", @@ -1473,7 +1473,7 @@ def test_generate_xml(self): """View for generating an xml from license namespace submittal form fields""" self.initialise() xml = generateLicenseXml(self.osiApproved, self.shortIdentifier, self.fullname, self.listVersionAdded, - [self.sourceUrl], self.licenseHeader, self.notes, self.text).replace("\n"," ") + [self.sourceUrl], self.licenseHeader, self.notes, self.text).replace(">","> ") self.assertEqual(self.xml, xml) @skipIf(not getAccessToken() and not getGithubUserId() and not getGithubUserName(), "You need to set gihub parameters in the secret.py file for this test to be executed properly.") diff --git a/src/app/urls.py b/src/app/urls.py index 1a23fe0e..3a0cb885 100644 --- a/src/app/urls.py +++ b/src/app/urls.py @@ -43,6 +43,7 @@ url(r'^validate_xml/$', views.validate_xml, name='validate-xml'), url(r'^search/$',views.autocompleteModel, name='autocompleteModel'), url(r'^make_pr/$', views.pull_request, name='pull-request'), + url(r'^beautify/$', views.beautify, name='beautify'), url(r'^update_session/$',views.update_session_variables, name='update-session-variables'), url(r'^submit_new_license/$', views.submitNewLicense, name='submit-new-license'), url(r'^submit_new_license_namespace/$', views.submitNewLicenseNamespace, name='submit-new-license-namespace'), diff --git a/src/app/utils.py b/src/app/utils.py index 42515962..2055f471 100644 --- a/src/app/utils.py +++ b/src/app/utils.py @@ -440,29 +440,6 @@ def createLicenseNamespaceIssue(licenseNamespace, token, urlType): return r.status_code -def generateLicenseXml(licenseOsi, licenseIdentifier, licenseName, listVersionAdded, licenseSourceUrls, licenseHeader, licenseNotes, licenseText): - """ View for generating a spdx license xml - returns the license xml as a string - """ - root = ET.Element("SPDXLicenseCollection", xmlns="http://www.spdx.org/license") - if licenseOsi=="Approved": - licenseOsi = "true" - else: - licenseOsi = "false" - license = ET.SubElement(root, "license", isOsiApproved=licenseOsi, licenseId=licenseIdentifier, name=licenseName, listVersionAdded=listVersionAdded) - crossRefs = ET.SubElement(license, "crossRefs") - for sourceUrl in licenseSourceUrls: - ET.SubElement(crossRefs, "crossRef").text = sourceUrl - ET.SubElement(license, "standardLicenseHeader").text = licenseHeader - ET.SubElement(license, "notes").text = licenseNotes - licenseTextElement = ET.SubElement(license, "text") - licenseLines = licenseText.replace('\r','').split('\n') - for licenseLine in licenseLines: - ET.SubElement(licenseTextElement, "p").text = licenseLine - xmlString = ET.tostring(root, method='xml').replace('>','>\n') - return xmlString - - def createIssue(licenseAuthorName, licenseName, licenseIdentifier, licenseComments, licenseSourceUrls, licenseHeader, licenseOsi, licenseRequestUrl, token, urlType): """ View for creating an GitHub issue when submitting a new license request diff --git a/src/app/views.py b/src/app/views.py index 9c27d35d..8bab3853 100644 --- a/src/app/views.py +++ b/src/app/views.py @@ -27,7 +27,7 @@ from django.contrib.auth.decorators import login_required from django.http import JsonResponse - +import codecs import jpype import requests from lxml import etree @@ -45,12 +45,14 @@ import datetime from wsgiref.util import FileWrapper import os +import subprocess from social_django.models import UserSocialAuth from app.models import UserID, LicenseNames from app.forms import UserRegisterForm,UserProfileForm,InfoForm,OrgInfoForm import app.utils as utils from django.forms import model_to_dict +from app.generateXml import generateLicenseXml logging.basicConfig(filename="error.log", format="%(levelname)s : %(asctime)s : %(message)s") @@ -125,7 +127,8 @@ def submitNewLicense(request): # Check if the license text doesn't matches with the rejected as well as not yet approved licenses if not matches: - xml = utils.generateLicenseXml(licenseOsi, licenseIdentifier, licenseName, + licenseText = licenseText.decode('unicode-escape') + xml = generateLicenseXml(licenseOsi, licenseIdentifier, licenseName, listVersionAdded, licenseSourceUrls, licenseHeader, licenseNotes, licenseText) now = datetime.datetime.now() licenseRequest = LicenseRequest(licenseAuthorName=licenseAuthorName, fullname=licenseName, shortIdentifier=licenseIdentifier, @@ -1407,6 +1410,55 @@ def update_session_variables(request): return HttpResponse(response, status=400) return HttpResponse("Bad Request", status=400) +def beautify(request): + """ View that handles beautify xml requests """ + if request.method=="POST": + context_dict = {} + ajaxdict = {} + try: + """ Getting the license xml input by the user""" + xmlString = request.POST.get("xml", None) + if xmlString: + with open('test.xml','w') as f: + f.write(xmlString) + f.close() + commandRun = subprocess.call(["python", "app/formatxml.py","test.xml","-i", "3"]) + if commandRun == 0: + data = codecs.open("test.xml", 'r', encoding='string_escape').read() + data = unicode(data, 'utf-8') + os.remove('test.xml') + if (request.is_ajax()): + ajaxdict["type"] = "success" + ajaxdict["data"] = data + response = dumps(ajaxdict) + return HttpResponse(response,status=200) + return HttpResponse(response["data"],status=200) + else: + ajaxdict["type"] = "error" + ajaxdict["data"] = "Invalid XML cannot be beautified." + ajaxdict["xml"] = xmlString + response = dumps(ajaxdict) + return HttpResponse(response,status=500) + else: + """ Error while getting xml """ + if (request.is_ajax()): + ajaxdict["type"] = "xml_error" + ajaxdict["data"] = "Error getting the xml" + response = dumps(ajaxdict) + return HttpResponse(response,status=500) + return HttpResponse(response,status=500) + except: + """ Other errors raised """ + logger.error(str(format_exc())) + if (request.is_ajax()): + ajaxdict["type"] = "error" + ajaxdict["data"] = "Unexpected error, please email the SPDX technical workgroup that the following error has occurred: " + format_exc() + response = dumps(ajaxdict) + return HttpResponse(response,status=500) + return HttpResponse("Unexpected error, please email the SPDX technical workgroup that the following error has occurred: " + format_exc(), status=500) + else: + return HttpResponseRedirect(settings.HOME_URL) + def pull_request(request): """ View that handles pull request """ if request.user.is_authenticated():