. */ /* * The @PACKAGE_*@-style defines. */ define('SP_PACKAGE_NAME', 'slate_permutate'); define('SP_PACKAGE_VERSION', '0.1_pre'); define('SP_PACKAGE_STRING', SP_PACKAGE_NAME . '-' . SP_PACKAGE_VERSION); /* * Set up include() path for user-supplied libs (in case if his system * doesn't have libs, such as phpcaptcha * (securimage/securimage.php)). Users would store such libs in /libs. * * Coding note: dirname(dirname('a/b/c')) returns 'a'. This is a * similar effect to dirname('a/b/c') . DIRECTORY_SEPARATOR . '..'. */ set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'libs'); /** * Not sure if there's a better place for this... it'd be a pita to * make a new include file like doconfig.inc but maybe that'll make * sense soon. */ /* defaults */ $base_uri = ''; $clean_urls = FALSE; $ga_trackers = array(); $ga_conversions = array(); $feedback_emails = array('ez@ethanzonca.com, ngelderloos7@gmail.com, ohnobinki@ohnopublishing.net'); $use_captcha = FALSE; $admin_enable_purge = FALSE; $qtips_always = FALSE; $input_warning_banner = FALSE; $feedback_disk_log = FALSE; $config_inc = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc'; if (file_exists($config_inc)) { require_once($config_inc); } /** * \brief * Produces XHTML output for the user and helps with other browser * interaction. * * Supports styled XHTML pages, modular script inclusion, and other * various features. */ class page { /* Site-wide configuration options */ private $base_title = array('SlatePermutate', 'Find the schedule that works for you!'); private $doctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"'; private $htmlargs = 'xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"'; private $pageGenTime = 0; private $xhtml = FALSE; /* Scripts and styles */ private $headCode = array(); private $trackingcode = ''; // Tracking code private $ga_conversions_code = ''; // Conversion tracking code private $pagetitle = ''; // Title of page private $scripts = array(); // Scripts to include on page private $meta; /* the current school. See get_school(). */ private $school; private $semester; /* * Whether or not the user should be presented with the option to * change the school profile or semester. */ private $school_semester_constant; /** * \brief * Construct a new page. * * Only to be called by page::page_construct(). Use that function * instead of the new keyword. * * \see page::page_construct() * * \param $ntitle * Must be a valid HTML string (i.e., escaped with htmlentities()). * \param $nscripts * An array of strings identifying the scripts to include for this page. * \param $options * An array containing any of the following keys: * - 'school': The school to use instead of the autodetected one. * - 'semester': The semester to use instead of the autodetected one. */ protected function __construct($ntitle, $nscripts = array(), $immediate = TRUE, array $options = array()) { /* Begin tracking generation time */ $this->pageGenTime = round(microtime(),4); global $ga_trackers; require_once('school.inc'); /* Scripts and styles available for inclusion */ $this->headCode['jQuery'] = ''; $this->headCode['jQueryUI'] = ''; $this->headCode['jValidate'] = ''; $this->headCode['jAddress'] = ''; $this->headCode['jQuery.cuteTime'] = ''; $this->headCode['qTip'] = ''; $this->headCode['qTip2'] = ''; $this->headCode['schedInput'] = ''; $this->headCode['outputPrintStyle'] = ''; $this->headCode['outputStyle'] = ''; $this->headCode['gliderHeadcode'] = ''; $this->headCode['uiTabsKeyboard'] = ''; $this->headCode['displayTables'] = ''; $this->pagetitle = $ntitle; $this->scripts = $nscripts; $this->meta = array( 'msapplication-starturl' => self::uri_resolve(''), 'msapplication-task' => 'name=Create Schedule; action-uri=' . self::uri_resolve('input.php') . '; icon-uri=' . self::uri_resolve('images/favicon_96.png'), 'msapplication-tooltip' => 'Find the semester schedule which works for you!', ); /* Compliant browsers which care, such as gecko, explicitly request xhtml: */ if(empty($_SERVER['HTTP_ACCEPT']) /* then the browser doesn't care :-) */ || strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') !== FALSE) $this->xhtml = TRUE; if (count($ga_trackers)) { $ga_www = 'http://www.'; if ($_SERVER['SERVER_PORT'] != 80) $ga_www = 'https://ssl.'; $this->trackingcode = '' . "\n" . $this->trackingcode . ' \n"; } self::session_start(); /* everything that needs sessions started to work: */ if (empty($options['school'])) $options['school'] = school_load_guess(); $this->school = $options['school']; if ($this->school['id'] != 'default') /* If we have a non-generic school, put it into base_title */ array_unshift($this->base_title, $this->school['name']); if (empty($options['semester'])) $options['semester'] = school_semester_guess($this->school); $this->semester = $options['semester']; if (!isset($options['school_semester_constant'])) $options['school_semester_constant'] = TRUE; $this->school_semester_constant = (bool)$options['school_semester_constant']; if($immediate && $ntitle != "NOHEAD") $this->head(); } /** * \brief * Instantiate a new page for the caller. * * The caller must explicitly call the page::head() function upon * the value that is returned. No implicit actions are supported * anymore. * * \param $title * The title of the page. Must be completely UTF-8 (will be * escaped for you with htmlentitites()). * \param $scripts * A list of scripts which the page desires to be included in the *
'. PHP_EOL . ' of the page. Should this param just be moved to the
   *   page::head() function?
   * \param $options
   *   An array containing any of the following keys:
   *     - 'school': The school to use instead of the autodetected one.
   *     - 'semester': The semester to use instead of the autodetected one.
   *     - 'school_semester_constant': Whether the options to change
   *        the current school and semester should be hidden. TRUE by
   *        default.
   */
  public static function page_create($title, array $scripts = array(), array $options = array())
  {
    return new page(htmlentities($title, ENT_QUOTES, 'UTF-8'), $scripts, FALSE, $options);
  }
  /**
   * \brief
   *   Adds some headcode to this page.
   *
   * \param $key
   *   The key to register this headcode under.
   * \param $code
   *   The actual code, such as a .
   * \param $enable
   *   Whether or not to enable this code while adding it.
   */
  public function headcode_add($key, $code, $enable = FALSE)
  {
    $this->headCode[$key] = $code;
    if ($enable) {
      $this->scripts[] = $key;
    }
  }
  /**
   * \brief
   *   Declare that this page is a conversion point.
   *
   * Making a page a conversion point informs any ad services or
   * whatnot that the user made it this far in slate_permutate. If the
   * user was referred to slate_permutate via an advertisement, this
   * can be used to see whether a click actually resulted in the user
   * actually _using_ slate_permutate instead of just navigating away
   * upon reading the first page.
   */
  public function conversion()
  {
    global $ga_conversions;
    if (!empty($ga_conversions))
      {
	if (!empty($this->ga_conversions_code))
	  /* Function already called once. */
	  return;
	$conversion_base_href = 'http' . ($_SERVER['SERVER_PORT'] == 80 ? '' : 's') . '://www.googleadservices/pagead/conversion/';
	$conversion_hrefs = array();
	$conversion_referrer = empty($_SERVER['HTTP_REFERER']) ? '' : '&ref=' . rawurlencode(substr($_SERVER['HTTP_REFERER'], 0, 255));
	$js_Date_getTime = (1000 * time()) . sprintf("%03d", rand(0, 999));
	$i = 1;
	foreach ($ga_conversions as $conversion_id => $conversion_label)
	  /*
	   * For random, supplement time() with three numerals to look
	   * like milliseconds like JavaScript's Date.getTime()
	   * function. For some reason, `random' and `fst' (first
	   * conversion time?) are both set to the current time. I'm
	   * guessing that random is supposed to be a cachebreaker.
	   *
	   * `cv' is the `current version' of the Google conversion.js
	   * which is 7. This could be scraped from the .js by looking
	   * for `google_conversion_js_version="7"'.
	   *
	   * `fmt=3' must mean that we don't want the user-notification
	   * to appear, but we already don't show that.  `value=0'
	   * seems to have no meaning at all, maybe it is supposed to
	   * be the `priority' of this conversion point.
	   *
	   * Google's `hl' and `gl' language values should probably be
	   * appended.
	   */
	  $this->ga_conversions_code .= 'xhtml ? '/' : '') . '>';
      }
  }
  /**
   * \brief
   *   Set a meta element value.
   * \param $name
   *   The name of the meta attribute.
   * \param $value
   *   The value.
   */
  public function meta($name, $value = '')
  {
    $this->meta[$name] = $value;
  }
  /**
   * \brief
   *   Set the information necessary to create a canonical URI
   *   description.
   *
   * For declaring a page's canonical URI, we use both  and soft redirects.
   *
   * \param $uri
   *   The base URI for the current page.
   * \param $query
   *   The querystring to canonicalize on.
   */
  public function canonize($uri, array $query = array())
  {
    $query_string = '';
    $uri_full = $uri;
    if (!empty($query))
      {
	ksort($query);
	$uri_full .= self::query_string($query);
      }
    /* Detect if we are at the canonical location or not... */
    list($base_request_uri) = explode('?', $_SERVER['REQUEST_URI'], 2);
    $base_request_uri = substr($_SERVER['REQUEST_URI'], strrpos($base_request_uri, '/') + 1);
    if ($base_request_uri != $uri_full)
      /* We are not canonical, redirect. */
      $this->redirect($uri_full);
    /* Mention that this is a canonical URI with  */
    $this->headcode_add('link_rel_canonical', 'xhtml ? '/>' : '>'),
			TRUE);
  }
  /**
   * \brief
   *   Output the HTML header for a page, including , 
, and opening structure */ public function head() { if ($this->xhtml) { header('Content-Type: application/xhtml+xml; charset=utf-8'); echo '' . PHP_EOL; } else header('Content-Type: text/html; charset=utf-8'); echo 'doctype . '>'. PHP_EOL . 'htmlargs . '>'. PHP_EOL . '
'. PHP_EOL . '
'. PHP_EOL . ' '. PHP_EOL . ' '. PHP_EOL . ' '. PHP_EOL . ' '. PHP_EOL . ' ' . PHP_EOL; foreach ($this->meta as $key => $value) echo ' xhtml ? '/' : '') . '>' . PHP_EOL; // Write out all passed scripts foreach ($this->scripts as $i) echo ' ' . $this->headCode["$i"] . "\n"; /* * Perhaps we should have a separate array for javascript library * initialization snippets. */ $javascript_init = ''; if (in_array('jQuery.cuteTime', $this->scripts)) $javascript_init .= 'jQuery.extend(jQuery.fn.cuteTime.settings, {refresh: 10000, use_html_attribute: false});' . PHP_EOL . 'jQuery.fn.cuteTime.settings.time_ranges[0].cuteness = \'in the future\';' . PHP_EOL; echo $this->script_wrap('' . 'var slate_permutate_school = ' . json_encode($this->school['id']) . ';' . PHP_EOL . 'var slate_permutate_semester = ' . json_encode($this->semester['id']) . ';' . PHP_EOL . $javascript_init) . PHP_EOL; $selectschool_query = '&school=' . $this->school['id']; /* kludge */ if (!empty($_REQUEST['s'])) $selectschool_query .= '&s=' . (int)$_REQUEST['s']; echo ' ' . PHP_EOL . '