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
21 changes: 13 additions & 8 deletions games/handlers/flashcards.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ def student_view(xblock, context=None):

# Obfuscated decoder with unique function name
obf_decoder = (
f"function {init_function_name}({var_names['runtime']},{var_names['elem']}){{" # function header
f"var {var_names['tag']}=$('#{data_element_id}',{var_names['elem']});" # locate script tag
f"if(!{var_names['tag']}.length)return;try{{" # guard
f"var {var_names['payload']}=JSON.parse(atob({var_names['tag']}.text()));" # decode
f"{var_names['tag']}.remove();" # remove script
f"if({var_names['payload']}&&{var_names['payload']}.cards)" # validate
f"GamesXBlockFlashcardsInit({var_names['runtime']},{var_names['elem']},{var_names['payload']}.cards);" # init
f"}}catch({var_names['err']}){{console.warn('Decode failed');}}}}"
f"function {init_function_name}({var_names['runtime']},{var_names['elem']}){{"
f"try{{"
f"var {var_names['tag']}=$('#{data_element_id}',{var_names['elem']});"
f"if(!{var_names['tag']}.length){{console.error('Flashcards: Data element not found');return;}}"
f"var {var_names['payload']}=JSON.parse(atob({var_names['tag']}.text()));"
f"{var_names['tag']}.remove();"
f"if({var_names['payload']}&&{var_names['payload']}.cards){{"
f"if(typeof GamesXBlockFlashcardsInit==='function'){{"
f"GamesXBlockFlashcardsInit({var_names['runtime']},{var_names['elem']},{var_names['payload']}.cards);"
f"}}else{{console.error('Flashcards: GamesXBlockFlashcardsInit not defined');}}"
f"}}else{{console.error('Flashcards: Invalid payload');}}"
f"}}catch({var_names['err']}){{console.error('Flashcards decode failed:',{var_names['err']});}}}}"
)

template_context = {
Expand Down Expand Up @@ -97,5 +101,6 @@ def student_view(xblock, context=None):
__name__, "../static/js/src/flashcards.js"
).decode("utf8")
)
frag.add_javascript(obf_decoder)
frag.initialize_js(init_function_name)
return frag
13 changes: 10 additions & 3 deletions games/handlers/matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,18 @@ def student_view(xblock, context=None):
# Build obfuscated decoder function; initializes JS via payload
obf_decoder = (
f"function {init_function_name}({var_names['runtime']},{var_names['elem']}){{"
f"try{{"
f"var {var_names['tag']}=$('#{data_element_id}',{var_names['elem']});"
f"if(!{var_names['tag']}.length)return;try{{"
f"if(!{var_names['tag']}.length){{console.error('Matching: Data element not found');return;}}"
f"var {var_names['payload']}=JSON.parse(atob({var_names['tag']}.text()));"
f"{var_names['tag']}.remove();if({var_names['payload']}&&{var_names['payload']}.pages)"
f"{var_names['tag']}.remove();"
f"if({var_names['payload']}&&{var_names['payload']}.pages){{"
f"if(typeof GamesXBlockMatchingInit==='function'){{"
f"GamesXBlockMatchingInit({runtime},{elem},{payload}.pages,{payload}.key);"
f"}}else{{console.error('Matching: GamesXBlockMatchingInit not defined');}}"
f"}}else{{console.error('Matching: Invalid payload');}}"
f"$('#obf_decoder_script',{var_names['elem']}).remove();"
f"}}catch({var_names['err']}){{console.warn('Decode failed');}}}}"
f"}}catch({var_names['err']}){{console.error('Matching decode failed:',{var_names['err']});}}}}"
)

template_context["encoded_mapping"] = encoded_mapping
Expand Down Expand Up @@ -165,6 +170,8 @@ def student_view(xblock, context=None):
__name__, "../static/js/src/confetti.js"
).decode("utf8")
)
# Add decoder function AFTER main JS files so GamesXBlockMatchingInit is defined
frag.add_javascript(obf_decoder)
frag.initialize_js(init_function_name)
return frag

Expand Down
2 changes: 1 addition & 1 deletion games/static/html/flashcards.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<!-- Encoded data payload and decoder -->
<script type="application/json" id="{{data_element_id}}">{{encoded_mapping|safe}}</script>
<script type="text/javascript">{{obf_decoder|safe}}</script>
<script type="text/template" id="flashcards_decoder_script">{{obf_decoder|safe}}</script>

<div class="gamesxblock gamesxblock-flashcards">
<!-- Header -->
Expand Down
2 changes: 1 addition & 1 deletion games/static/html/matching.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>

<script type="application/json" id="{{data_element_id}}">{{encoded_mapping|safe}}</script>
<script type="text/javascript" id="obf_decoder_script">{{obf_decoder|safe}}</script>
<script type="text/template" id="obf_decoder_script">{{obf_decoder|safe}}</script>

<div class='gamesxblock gamesxblock-matching' data-timed="{{ has_timer|yesno:'true,false' }}">
<div class="matching-header">
Expand Down
2 changes: 1 addition & 1 deletion games/static/js/src/matching.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function GamesXBlockMatchingInit(runtime, element, pages, matching_key) {
var match = scriptContent.match(/function\s+(\w+)\s*\(/);
if (match) {
var initFuncName = match[1];
eval(scriptContent);
(1, eval)(scriptContent);
if (typeof window[initFuncName] === 'function') {
window[initFuncName](runtime, element);
setTimeout(function() {
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def package_data(pkg, roots):

setup(
name="edx-games",
version="1.0.10",
version="1.0.11",
description="Interactive games XBlock for Open edX - Create flashcards and matching games with image support",
author="edX",
author_email="edx@edx.org",
Expand Down