"""Original two-origin color access experiment. Run Python + Pillow, open localhost:8766.
Only binds loopback; no proxy, credentials, or external image service.
"""
from http.server import ThreadingHTTPServer,BaseHTTPRequestHandler
from threading import Thread
from pathlib import Path
from io import BytesIO
from PIL import Image
import hashlib,json

image=Image.new('RGB',(120,80),(36,132,184));buf=BytesIO();image.save(buf,format='PNG');PNG=buf.getvalue()
HTML='''<!doctype html><html lang="en"><meta charset="utf-8"><title>Original CORS color lab</title><style>body{font:18px system-ui;max-width:1100px;margin:32px auto}td,th{padding:12px;border:1px solid #ccc}pre{white-space:pre-wrap}img{width:120px;height:80px}button{padding:14px}</style><h1>Same PNG, different access</h1><p>Original RGB (36,132,184); 120 × 80 pixels. Change request mode and response headers only.</p><button id="run">Run experiment</button><table><thead><tr><th>Case</th><th>Load</th><th>Pixel read</th><th>Pixel / error</th><th>Image</th></tr></thead><tbody id="rows"></tbody></table><pre id="results"></pre><script>
const cross='http://127.0.0.1:8767';
const cases=[['same-origin image','image','/deny.png',false],['cross-origin image, no CORS','image',cross+'/deny.png',false],['anonymous image, no CORS','image',cross+'/deny.png',true],['anonymous image, CORS allowed','image',cross+'/allow.png',true],['ordinary image, CORS header only','image',cross+'/allow.png',false],['fetch cors, no CORS','cors',cross+'/deny.png',false],['fetch cors, CORS allowed','cors',cross+'/allow.png',false],['fetch no-cors, no CORS','no-cors',cross+'/deny.png',false]];
document.querySelector('#run').onclick=async()=>{document.querySelector('#rows').replaceChildren();let results=[];
for(const [name,mode,url,anonymous]of cases){const row={name,mode,url,anonymous,load:'not loaded',read:'not attempted'};const tr=document.createElement('tr');let img=new Image();let objectURL;
try{let src=url+'?case='+encodeURIComponent(name);if(mode!=='image'){const response=await fetch(src,{mode,credentials:'omit',referrerPolicy:'no-referrer'});row.responseType=response.type;row.status=response.status;const blob=await response.blob();row.blobBytes=blob.size;objectURL=URL.createObjectURL(blob);src=objectURL;}if(anonymous)img.crossOrigin='anonymous';await new Promise((ok,no)=>{img.onload=ok;img.onerror=()=>no(new Error('Image load error'));img.src=src});row.load='loaded';const c=document.createElement('canvas');c.width=120;c.height=80;const x=c.getContext('2d');x.drawImage(img,0,0);row.read='blocked';row.rgba=Array.from(x.getImageData(60,40,1,1).data);row.read='readable';}catch(e){row.errorName=e.name;row.error=e.message;}finally{if(objectURL)URL.revokeObjectURL(objectURL)}
for(const value of [name,row.load,row.read,row.rgba?row.rgba.join(','):row.errorName+': '+row.error]){const td=document.createElement('td');td.textContent=value;tr.append(td)}const td=document.createElement('td');if(row.load==='loaded')td.append(img);tr.append(td);document.querySelector('#rows').append(tr);results.push(row);}
document.querySelector('#results').textContent=JSON.stringify({checkedAt:new Date().toISOString(),browser:navigator.userAgent,fixture:{width:120,height:80,rgb:[36,132,184],sample:[60,40]},cases:results},null,2);};</script></html>'''
class Handler(BaseHTTPRequestHandler):
 def do_GET(self):
  data=HTML.encode() if self.path=='/' else PNG
  self.send_response(200);self.send_header('Content-Type','text/html; charset=utf-8' if self.path=='/' else 'image/png');self.send_header('Cache-Control','no-store');self.send_header('Content-Length',str(len(data)))
  if self.path.startswith('/allow.png'):self.send_header('Access-Control-Allow-Origin','*')
  self.end_headers();self.wfile.write(data)
 def log_message(self,*args):pass
if __name__=='__main__':
 out=Path(__file__).resolve().parent/'cors-fixture.png';out.write_bytes(PNG)
 print(json.dumps({'sha256':hashlib.sha256(PNG).hexdigest(),'bytes':len(PNG),'url':'http://127.0.0.1:8766'}),flush=True)
 Thread(target=ThreadingHTTPServer(('127.0.0.1',8767),Handler).serve_forever,daemon=True).start()
 ThreadingHTTPServer(('127.0.0.1',8766),Handler).serve_forever()
