import 'dart:convert'; import 'navigation_policy.dart'; const undergraduateProbeBase = r'''(() => { const capture=__CAPTURE__; const topUrl=location.href; const result={topUrl,authenticated:false,pages:[]}; const trusted=value=>{try{const u=new URL(value);return u.protocol==='https:' && u.hostname==='eams.uestc.edu.cn' && (!u.port || u.port==='443') && !u.username && !u.password && u.pathname.startsWith('/eams/');}catch(_){return false;}}; if(!trusted(topUrl) || document.querySelector('input[type="password"]'))return JSON.stringify(result); const origin=new URL(topUrl).origin,seen=new Set();let total=0; const headers=['课程序号','课程名称','考试日期','考试安排','考试地点','座位号','考试情况','考试类型','其它说明']; const add=(kind,url,body)=>{ total+=new TextEncoder().encode(body).byteLength; if(total>2*1024*1024)throw new Error('capture_limit'); result.pages.push({kind,url,html:body}); }; const visit=(doc,depth)=>{ if(!doc || seen.has(doc))return; let url;try{url=doc.location.href;}catch(_){return;} if(!trusted(url) || new URL(url).origin!==origin || doc.querySelector('input[type="password"]'))return; if(depth>4 || seen.size>=16)throw new Error('capture_limit');seen.add(doc); const timetable=doc.querySelector('#manualArrangeCourseTable'); const exams=Array.from(doc.querySelectorAll('table')).filter(table=>{ const row=table.querySelector('tr');if(!row)return false; const values=Array.from(row.children).map(c=>c.textContent.trim()); return values.length===9 && headers.every((v,i)=>values[i]===v); }); const logout=Array.from(doc.querySelectorAll('a[href]')).some(a=>{try{return new URL(a.getAttribute('href'),url).pathname==='/eams/logout.action';}catch(_){return false;}}); result.authenticated=result.authenticated || Boolean(logout || timetable || exams.length); if(capture && (timetable || exams.length)){ const fields=Array.from(doc.querySelectorAll('input[name="semester.id"],input[name="examType.id"],input[name="params"]')).map(input=>{ const clone=input.cloneNode(true);clone.setAttribute('value',input.value);return clone.outerHTML; }).join(''); const scripts=Array.from(doc.querySelectorAll('script')).filter(s=>/new\s+TaskActivity|\bunitCount\s*=|\bvar\s+params\s*=/.test(s.textContent)).map(s=>s.outerHTML).join(''); if(timetable){ const roster=Array.from(doc.querySelectorAll('table')).filter(table=>{ const row=table.querySelector('tr');return row && Array.from(row.children).some(c=>c.textContent.trim()==='课程序号') && Array.from(row.children).some(c=>c.textContent.trim()==='课程代码'); }).map(t=>t.outerHTML).join(''); add('timetable',url,fields+timetable.outerHTML+roster+scripts); } for(const table of exams)add('exams',url,'
'+table.outerHTML+scripts); } for(const frame of doc.querySelectorAll('iframe,frame')){ let child;try{child=frame.contentDocument;}catch(_){continue;}visit(child,depth+1); } }; try{visit(document,0);}catch(_){result.error='capture_limit';result.pages=[];} return JSON.stringify(result); })()'''; final undergraduateStatusProbeScript = undergraduateProbeBase.replaceAll( '__CAPTURE__', 'false', ); final undergraduateCaptureScript = undergraduateProbeBase.replaceAll( '__CAPTURE__', 'true', ); class UndergraduateFragment { const UndergraduateFragment(this.kind, this.url, this.html); final String kind, html; final Uri url; } class UndergraduatePageEvidence { const UndergraduatePageEvidence(this.authenticated, this.pages); final bool authenticated; final List