/*## (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.util.*;
import java.text.*;

public class Subscription {
 public static final int NOT_PREPAID_BIT = 0x00002000;
 public static final int PREMIUM_HD_BIT  = 0x00080000;

 public static final int FROM    = 0;
 public static final int TO      = 1;

 public static final int DAY     = 0;
 public static final int MONTH   = 1;
 public static final int YEAR    = 2;

 public static final int MAX_IDX = 3;

 private static int max_day[] = {
  31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 }; 

 int[][] subsperiod;
 int bitmask;

 int value;

 private static Hashtable pkgmap;

 static {
  pkgmap=new Hashtable();
  pkgmap.put(new Integer(0x00000040) ,"Cinemax");
  pkgmap.put(new Integer(0x00000100) ,"nFilm HD");             
  pkgmap.put(new Integer(0x00000200) ,"Noc");
  pkgmap.put(new Integer(0x00000400) ,"Informacja i rozrywka");
  pkgmap.put(new Integer(0x00000800) ,"HBO");                  
  pkgmap.put(new Integer(0x00001000) ,"Filmbox");
  pkgmap.put(new Integer(0x00004000) ,"Kultura, Nauka, Swiat");
  pkgmap.put(new Integer(0x00008000) ,"Sport i Motoryzacja");
  pkgmap.put(new Integer(0x00010000) ,"Dzieci");
  pkgmap.put(new Integer(0x00020000) ,"Style, Moda, Muzyka");
  pkgmap.put(new Integer(0x00040000) ,"Hity filmowe");
 }

 public static String pkgname(int bit) {
  String pkg=(String)pkgmap.get(new Integer(bit));

  return pkg;
 }

 public Subscription(int[][] period,int mask) {
  subsperiod=period;
  bitmask=mask;

  value=int_value();
 }

 public int[][] subsperiod() {
  return subsperiod;
 }

 public int bitmask() {
  return bitmask;
 }

 public void bitmask(int mask) {
  bitmask=mask;
  value=int_value();
 }

 public int value() {
  return value;
 }

 private String number(int i) {
  String s=""+i;

  if (s.length()==1) s="0"+s;

  return s;  
 }

 public boolean is_prepaid() {
  boolean res=false;

  switch(Config.BOXTYPE) {
   case Config.NBOX_HDTV:
   case Config.NBOX_2850ST:
    if ((bitmask&NOT_PREPAID_BIT)==0) {
     res=true;
    }
    break;
   case Config.NBOX_2851S:
   case Config.NBOX_RECORDER:    
    res=false;
    break;
   case Config.NBOX_2849ST:
    res=true;
    break;
  }

  return res;
 }

 public boolean is_premium_hd() {
  boolean res=false;

  if ((bitmask&PREMIUM_HD_BIT)!=0) {
   res=true;
  }

  return res;
 }

 public void print(boolean primary) throws Throwable {
  if (is_prepaid()) {
   String s="   "+number(subsperiod[FROM][DAY])+"."+number(subsperiod[FROM][MONTH])+"."+subsperiod[FROM][YEAR]+" - "+number(subsperiod[TO][DAY])+"."+number(subsperiod[TO][MONTH])+"."+subsperiod[TO][YEAR]+"  0x"+Utils.hex_value(bitmask,8);
   Output.text(s);

   if (primary) {
    String pkg="Pakiet Domowy HD";
    s="                          - "+pkg;
    Output.text(s);

    if (is_premium_hd()) {
     pkg="Pakiet Domowy HD Premium";
     s="                          - "+pkg;
     Output.text(s);
    }
   }
  } else {
   String s="   "+number(subsperiod[FROM][DAY])+"."+number(subsperiod[FROM][MONTH])+"."+subsperiod[FROM][YEAR]+" - "+number(subsperiod[TO][DAY])+"."+number(subsperiod[TO][MONTH])+"."+subsperiod[TO][YEAR]+"  0x"+Utils.hex_value(bitmask,8);
   Output.text(s);

   if (primary) {
    for(int i=0;i<32;i++) {
     int bit=1<<i;

     if ((bitmask&bit)!=0) {
      String pkg=pkgname(bit);
      if (pkg!=null) {
       s="                          - "+pkg;
       Output.text(s);
      }
     }
    }
   }
  }
 }

 public void log() {
  String s="   "+number(subsperiod[FROM][DAY])+"."+number(subsperiod[FROM][MONTH])+"."+subsperiod[FROM][YEAR]+" - "+number(subsperiod[TO][DAY])+"."+number(subsperiod[TO][MONTH])+"."+subsperiod[TO][YEAR]+"  0x"+Utils.hex_value(bitmask,8);
  ApiMonitor.log(s);

  for(int i=0;i<32;i++) {
   int bit=1<<i;

   if ((bitmask&bit)!=0) {
    String pkg=pkgname(bit);
    if (pkg!=null) {
     s="                          - "+pkg;
     ApiMonitor.log(s);
    }
   }
  }
 }

 public int int_value() {
  int val=0;

  int v1=(subsperiod[FROM][DAY]<<10)|(subsperiod[FROM][MONTH]<<5)|((subsperiod[FROM][YEAR]-2000)&0x1f);
  int v2=(subsperiod[TO][DAY]<<10)|(subsperiod[TO][MONTH]<<5)|((subsperiod[TO][YEAR]-2000)&0x1f);
  
  val=(v1<<16)|v2;

  return val;
 }

 public boolean equals(Subscription s) {
  return (value==s.value());
 }

 public static Subscription create(int mask) {
  Subscription res=null;

  try {
   Date date=Calendar.getInstance().getTime();

   SimpleDateFormat df1=new SimpleDateFormat("MM");
   SimpleDateFormat df2=new SimpleDateFormat("yyyy");

   String month=df1.format(date);  
   String year=df2.format(date);  

   int mval=Integer.parseInt(month);
   int yval=Integer.parseInt(year);

   int period[][]=new int[2][];   
   period[FROM]=new int[3];
   period[TO]=new int[3];

   period[FROM][DAY]=1;
   period[FROM][MONTH]=mval;
   period[FROM][YEAR]=yval;

   period[TO][DAY]=max_day[mval-1];
   period[TO][MONTH]=mval;
   period[TO][YEAR]=yval;

   res=new Subscription(period,mask);
  } catch(Throwable t) {
   ApiMonitor.log_stacktrace(t);
  }

  return res;    
 }
}
