/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.lang.reflect.*;
import java.util.*;
import java.net.*;
import java.io.*;
import javax.tv.service.*;
import javax.tv.service.selection.*;
import javax.tv.service.navigation.*;
import org.dvb.internet.*;
import tv.osmosys.tci.util.*;
import com.adb.xion.net.www.content.*;
import tv.osmosys.net.*;
import com.adb.xion.net.*;

public class Xion {
 public static final String SE_ARG0  = "se.arg.0";
 public static final String SE_ARG1  = "se.arg.1";

 public static final String SE_INIT  = "se.init";
 public static final String SE_RES   = "se.res";
 public static final String SE_DONE  = "se.done";

 public static class URIHandler implements URIConnectionHandler {
  public URIConnection createConnection(com.adb.xion.net.URI uri) {
   String scheme=uri.getScheme();

   if (scheme==null) return null;

   scheme=scheme.toLowerCase();
 
   URIConnection conn=null;

   if (scheme.equals("http")||scheme.equals("https")) {
    conn=new com.adb.xion.net.nativehttp.URIConnection(uri);
   } else {
    conn=URIConnectionFactory.getInstance().createURIConnection(uri);
   }   

   return conn;
  }

  public static URIConnection nativeConnection(com.adb.xion.net.URI uri) throws URIConnectionException {
   String scheme=uri.getScheme();

   if (scheme==null) return null;

   scheme=scheme.toLowerCase();
    
   return new com.adb.xion.net.nativehttp.URIConnection(uri);
  }
 }

 public static void init_handlers() {
  try {
   URIHandler uh=new URIHandler();  

   Class c=Class.forName("com.adb.xion.net.URIConnectionFactory");
   Field f=c.getDeclaredField("handlers");
   f.setAccessible(true);
 
   f.set(null,new ArrayList());

   URIConnectionFactory.getInstance().registerURIConnectionHandler(uh);
  } catch(Throwable t) {}
 }

 public static class BrowserListener implements InternetClientListener {
  public void receiveInternetClientEvent(InternetClientEvent event) {
   ApiMonitor.log("InternetClientListener "+event);

   if (event instanceof InternetClientSuccessEvent) {
    opened=true;
    lresult=true;
   } else
   
   if (event instanceof InternetClientFailureEvent) {
    opened=false;
    lresult=true;
   }
  }
 }

 public static class ContextListener implements ServiceContextListener {
  public void receiveServiceContextEvent(ServiceContextEvent servicecontextevent) {
  }
 }

 static URL url;
 static boolean opened;
 static boolean lresult;
 static InternetClientListener listener;
 static WWWBrowser browser;
 static ServiceContext ctx;

 private static void create_key(String key,int type) {
  try {
   Registry.removeKey(key);
  } catch(Throwable t) {}

  try {
   Registry.createKey(key,0,type);
  } catch(Throwable t) {}
 }

 static {
  try {
   create_key(SE_ARG0,Registry.TYPE_STRING);
   create_key(SE_ARG1,Registry.TYPE_STRING);
   create_key(SE_RES ,Registry.TYPE_STRING);

   create_key(SE_INIT,Registry.TYPE_INTEGER);
   create_key(SE_DONE,Registry.TYPE_INTEGER);

   create_page(XionDefs.ALERT_PATH,alert_page());
   create_page(XionDefs.CONFIRM_PATH,confirm_page());
   create_page(XionDefs.PROMPT_PATH,prompt_page());

   Class c=Class.forName("com.adb.xion.net.nativehttp.Init");
   Field f_inst=c.getDeclaredField("instance");
   f_inst.setAccessible(true);

   Field f_props=c.getDeclaredField("props");
   f_props.setAccessible(true);

   Object instance=f_inst.get(null);
   Properties props=(Properties)f_props.get(instance);

   ApiMonitor.log("props: "+props); 
  } catch(Throwable t) {}
 }

 private static String alert_page() {
  String s="";

  s+="<html>";
  s+="<body>";
  s+="<script>";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_INIT+ "\",1);";
  s+="var s=Packages.tv.osmosys.tci.util.Registry.getValue(\""+SE_ARG0+"\");";
  s+="alert(s);";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\""+SE_DONE+"\",1);";
  s+="document.location.href=\"exit:\";";
  s+="</script>";
  s+="</body>";
  s+="</html>";

  return s;
 }

 private static String confirm_page() {
  String s="";

  s+="<html>";
  s+="<body>";
  s+="<script>";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_INIT+ "\",1);";
  s+="var s=Packages.tv.osmosys.tci.util.Registry.getValue(\""+SE_ARG0+"\");";
  s+="var res=confirm(s);";
  s+="if (res==true) Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_RES+ "\",\"true\");";
  s+=" else Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_RES+ "\",\"false\");";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\""+SE_DONE+"\",1);";
  s+="document.location.href=\"exit:\";";
  s+="</script>";
  s+="</body>";
  s+="</html>";

  return s;
 }

 private static String prompt_page() {
  String s="";

  s+="<html>";
  s+="<body>";
  s+="<script>";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_INIT+ "\",1);";
  s+="var s1=Packages.tv.osmosys.tci.util.Registry.getValue(\""+SE_ARG0+"\");";
  s+="var s2=Packages.tv.osmosys.tci.util.Registry.getValue(\""+SE_ARG1+"\");";
  s+="var res=prompt(s1,s2);";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\"" +SE_RES+ "\",res);";
  s+="Packages.tv.osmosys.tci.util.Registry.setValue(\""+SE_DONE+"\",1);";
  s+="document.location.href=\"exit:\";";
  s+="</script>";
  s+="</body>";
  s+="</html>";

  return s;
 }

 private static void create_page(String name,String content) {
  try {
   FileOutputStream fos=new FileOutputStream(name,false);
   byte data[]=content.getBytes();

   fos.write(data);
   fos.flush();

   fos.close();
  } catch(Throwable t) {}
 }

 public static boolean openURL(String url) throws Throwable {
  if (opened) {
   close();
  }

  InternetServiceFilter filter=new InternetServiceFilter(InternetServiceFilter.WWW_CLIENT);
  WWWBrowserService srv=(WWWBrowserService)SIManager.createInstance().filterServices(filter).getService(0);

ApiMonitor.log("srv "+srv);

  srv.setInitialURL(new URL(url));

  ctx=ServiceContextFactory.getInstance().createServiceContext();
  ctx.addListener(new ContextListener());

  ctx.select(srv);

ApiMonitor.log("select");

  ServiceContentHandler chtab[]=ctx.getServiceContentHandlers();

  for(int j=0;j<chtab.length;j++) {
   if (chtab[j] instanceof WWWBrowser) {
    browser=(WWWBrowser)chtab[j];
   }
  }

ApiMonitor.log("browser "+browser);

  if (browser!=null) {
   listener=new BrowserListener();
   opened=false;
   lresult=false;

   browser.addInternetClientListener(listener);

   ((com.adb.xion.WWWBrowser)browser).goToURL(url);

   while(!lresult) Utils.sleep(10);

   if (!opened) {
    close();
   }
  }

ApiMonitor.log("open status: "+opened);

  return opened;
 }

 public static void close() {
  if (opened) {
   browser.removeInternetClientListener(listener);
   ctx.stop();
   ctx.destroy();

   browser=null;
   ctx=null;

   opened=false;
  }
 }

 private static void wait_for_js_init() {
  while(true) {
   int val=((Integer)Registry.getValue(SE_INIT)).intValue();
   if (val!=0) break;
    else Utils.sleep(50);
  }
 }

 private static void wait_for_js_end() {
  while(true) {
   int val=((Integer)Registry.getValue(SE_DONE)).intValue();
   if (val!=0) break;
    else Utils.sleep(50);
  }
 }

 public static void clear_from_cache(String uri) {
  try {
   ContentManager cm=ContentManager.getInstance();

   Class c=Class.forName("com.adb.xion.net.www.content.ContentManager");
   Field f=c.getDeclaredField("cacheMap");
   f.setAccessible(true);

   Map map=(Map)f.get(cm);
   
   if (map.get(uri)!=null) {
    map.remove(uri);
   }   
  } catch(Throwable t) {}
 }

 public static void alert(String s,boolean wait) throws Throwable {
  try {
   Registry.setValue(SE_INIT,0);
   Registry.setValue(SE_DONE,0);
   Registry.setValue(SE_ARG0,s);

   clear_from_cache(XionDefs.NPORTAL_URI);

   String olduri=HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,"flash:/"+ConfigDefs.DATA_PFX+"/"+XionDefs.ALERT_FILE);
   UserInput.key_sequence("<home>");

   wait_for_js_init();

   HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,olduri);
   clear_from_cache(XionDefs.NPORTAL_URI);

   if (wait) {
    wait_for_js_end();
   }
  } catch(Throwable t) {
   ApiMonitor.log("exception "+t);
  }
 }

 public static boolean confirm(String s,boolean wait) {
  boolean res=false;

  try {
   Registry.setValue(SE_INIT,0);
   Registry.setValue(SE_DONE,0);
   Registry.setValue(SE_ARG0,s);

   clear_from_cache(XionDefs.NPORTAL_URI);

   String olduri=HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,"flash:/"+ConfigDefs.DATA_PFX+"/"+XionDefs.CONFIRM_FILE);
   UserInput.key_sequence("<home>");

   wait_for_js_init();

   HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,olduri);
   clear_from_cache(XionDefs.NPORTAL_URI);

   if (wait) {
    wait_for_js_end();
   }

   res=((String)Registry.getValue(SE_RES)).equalsIgnoreCase("true");
  } catch(Throwable t) {
   ApiMonitor.log("exception "+t);
  }

  return res;
 }

 public static String prompt(String s1,String s2,boolean wait) {
  String res="";

  try {
   Registry.setValue(SE_INIT,0);
   Registry.setValue(SE_DONE,0);
   Registry.setValue(SE_ARG0,s1);
   Registry.setValue(SE_ARG1,s2);

   clear_from_cache(XionDefs.NPORTAL_URI);

   String olduri=HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,"flash:/"+ConfigDefs.DATA_PFX+"/"+XionDefs.PROMPT_FILE);
   UserInput.key_sequence("<home>");

   wait_for_js_init();

   HTTPSniffer.mapuri(XionDefs.NPORTAL_URI,olduri);
   clear_from_cache(XionDefs.NPORTAL_URI);

   if (wait) {
    wait_for_js_end();
   }

   res=(String)Registry.getValue(SE_RES);
  } catch(Throwable t) {
   ApiMonitor.log("exception "+t);
  }

  return res;
 }

 public static String[] login(String s1,String s2,boolean wait) {
  return null;
 }
}
