Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions common/lib/xmodule/xmodule/modulestore/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
URL_VERSION_PREFIX = 'version/'

URL_RE = re.compile(r'^(edx://)?(.+)$', re.IGNORECASE)

ALLOWED_ID_CHARS = r'[a-zA-Z0-9_\-~.]'

def parse_url(string, tag_optional=False):
"""
Expand Down Expand Up @@ -45,17 +45,12 @@ def parse_url(string, tag_optional=False):
return parse_course_id(path)


BLOCK_RE = re.compile(r'^\w+$', re.IGNORECASE)
BLOCK_RE = re.compile(r'^' + ALLOWED_ID_CHARS + r'+$', re.IGNORECASE)


def parse_block_ref(string):
r"""
A block_ref is a string of word_chars.

<word_chars> matches one or more Unicode word characters; this includes most
characters that can be part of a word in any language, as well as numbers
and the underscore. (see definition of \w in python regular expressions,
at http://docs.python.org/dev/library/re.html)
A block_ref is a string of url safe characters (see ALLOWED_ID_CHARS)

If string is a block_ref, returns a dict with key 'block_ref' and the value,
otherwise returns None.
Expand All @@ -65,7 +60,10 @@ def parse_block_ref(string):
return None


GUID_RE = re.compile(r'^(?P<version_guid>[A-F0-9]+)(' + BLOCK_PREFIX + '(?P<block>\w+))?$', re.IGNORECASE)
GUID_RE = re.compile(
r'^(?P<version_guid>[A-F0-9]+)(' + BLOCK_PREFIX + '(?P<block>' + ALLOWED_ID_CHARS + r'+))?$',
re.IGNORECASE
)


def parse_guid(string):
Expand All @@ -83,10 +81,10 @@ def parse_guid(string):


COURSE_ID_RE = re.compile(
r'^(?P<id>(\w+)(\.\w+\w*)*)(' +
BRANCH_PREFIX + '(?P<branch>\w+))?(' +
VERSION_PREFIX + '(?P<version_guid>[A-F0-9]+))?(' +
BLOCK_PREFIX + '(?P<block>\w+))?$', re.IGNORECASE
r'^(?P<id>' + ALLOWED_ID_CHARS + r'+)(' +
BRANCH_PREFIX + r'(?P<branch>' + ALLOWED_ID_CHARS + r'+))?(' +
VERSION_PREFIX + r'(?P<version_guid>[A-F0-9]+))?(' +
BLOCK_PREFIX + r'(?P<block>' + ALLOWED_ID_CHARS + r'+))?$', re.IGNORECASE
)


Expand Down Expand Up @@ -117,12 +115,7 @@ def parse_course_id(string):

block = name

name = <word_chars>

<word_chars> matches one or more Unicode word characters; this includes most
characters that can be part of a word in any language, as well as numbers
and the underscore. (see definition of \w in python regular expressions,
at http://docs.python.org/dev/library/re.html)
name = ALLOWED_ID_CHARS

If string is a course_id, returns a dict with keys 'id', 'branch', and 'block'.
Revision is optional: if missing returned_dict['branch'] is None.
Expand Down
14 changes: 6 additions & 8 deletions common/lib/xmodule/xmodule/modulestore/tests/test_locators.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,13 @@ def test_course_constructor_bad_course_id(self):
"""
Test all sorts of badly-formed course_ids (and urls with those course_ids)
"""
for bad_id in ('mit.',
' mit.eecs',
for bad_id in (' mit.eecs',
'mit.eecs ',
URL_VERSION_PREFIX + 'mit.eecs',
BLOCK_PREFIX + 'block/mit.eecs',
'mit.ee cs',
'mit.ee,cs',
'mit.ee/cs',
'mit.ee$cs',
'mit.ee&cs',
'mit.ee()cs',
BRANCH_PREFIX + 'this',
Expand Down Expand Up @@ -130,17 +128,17 @@ def test_course_constructor_url(self):

def test_course_constructor_url_course_id_and_version_guid(self):
test_id_loc = '519665f6223ebd6980884f2b'
testobj = CourseLocator(url='edx://mit.eecs.6002x' + VERSION_PREFIX + test_id_loc)
testobj = CourseLocator(url='edx://mit.eecs-honors.6002x' + VERSION_PREFIX + test_id_loc)
self.check_course_locn_fields(testobj, 'error parsing url with both course ID and version GUID',
course_id='mit.eecs.6002x',
course_id='mit.eecs-honors.6002x',
version_guid=ObjectId(test_id_loc))

def test_course_constructor_url_course_id_branch_and_version_guid(self):
test_id_loc = '519665f6223ebd6980884f2b'
testobj = CourseLocator(url='edx://mit.eecs.6002x' + BRANCH_PREFIX + 'draft' + VERSION_PREFIX + test_id_loc)
testobj = CourseLocator(url='edx://mit.eecs.~6002x' + BRANCH_PREFIX + 'draft-1' + VERSION_PREFIX + test_id_loc)
self.check_course_locn_fields(testobj, 'error parsing url with both course ID branch, and version GUID',
course_id='mit.eecs.6002x',
branch='draft',
course_id='mit.eecs.~6002x',
branch='draft-1',
version_guid=ObjectId(test_id_loc))

def test_course_constructor_course_id_no_branch(self):
Expand Down