예제 #1
0
 static function init(\Db\Connection $db)
 {
     // set up the event handlers
     /**
      * Set up metrics-capturing events.
      */
     if (Config::get('metrics_enabled', true)) {
         self::$instance = new MetricsHandler($db);
         if (Config::get('metrics_db_enabled', true)) {
             Events::on('db_prepare_start', array(self::$instance, 'db_prepare_start'));
             Events::on('db_prepare_end', array(self::$instance, 'db_prepare_end'));
             Events::on('db_prepare_master', array(self::$instance, 'db_prepare_master'));
             Events::on('db_prepare_slave', array(self::$instance, 'db_prepare_slave'));
             Events::on('db_execute_start', array(self::$instance, 'db_execute_start'));
             Events::on('db_execute_end', array(self::$instance, 'db_execute_end'));
             Events::on('db_fetch_start', array(self::$instance, 'db_fetch_start'));
             Events::on('db_fetch_end', array(self::$instance, 'db_fetch_end'));
             Events::on('db_fetch_all_start', array(self::$instance, 'db_fetch_all_start'));
             Events::on('db_fetch_all_end', array(self::$instance, 'db_fetch_all_end'));
         }
         if (Config::get('metrics_page_enabled', true)) {
             Events::on('page_start', array(self::$instance, 'page_start'));
             Events::on('page_end', array(self::$instance, 'page_end'));
         }
         if (Config::get('metrics_templates_enabled', true)) {
             Events::on('pages_template_start', array(self::$instance, 'template_start'));
             Events::on('pages_template_end', array(self::$instance, 'template_end'));
         }
         if (Config::get('metrics_curl_enabled', true)) {
             Events::on('curl_start', array(self::$instance, 'curl_start'));
             Events::on('curl_end', array(self::$instance, 'curl_end'));
         }
     }
 }
예제 #2
0
파일: Query.php 프로젝트: openclerk/db
 function fetchAll()
 {
     if ($this->cursor === null) {
         throw new DbException("Query must be executed first");
     }
     Events::trigger('db_fetch_all_start', $this->query);
     $result = $this->cursor->fetchAll();
     Events::trigger('db_fetch_all_end', $this->query);
     return $result;
 }
예제 #3
0
 /**
  * We can bind and then unbind.
  */
 function testBindThenUnbind()
 {
     $bind = Events::on('test_simple', array($this, 'onTestSimple'));
     try {
         Events::trigger('test_simple', "cat");
         $this->assertEquals(array("cat"), $this->last_simple_data);
     } finally {
         Events::unbind($bind);
     }
     Events::trigger('test_simple', "dog");
     $this->assertEquals(array("cat"), $this->last_simple_data);
     // hasn't changed
 }
예제 #4
0
파일: Email.php 프로젝트: openclerk/emails
 /**
  * Send an email with the given template to the given user or address.
  * The subject of the e-mail is obtained from the first line of the text e-mail template, or the
  * <title> of the HTML template.
  *
  * TODO support mock mailing
  * TODO support i18n
  * TODO service wrapper to allow emails to be queued
  *
  * @param $to_or_user either an email address, or something with getEmail() and optionally getName()
  * @throws MailerException if the mail could not be immediately sent (e.g. technical error, invalid e-mail address...)
  * @return the email result object, which is also sent to the `email_sent` event trigger
  */
 static function send($to_or_user, $template_id, $arguments = array())
 {
     // add any global arguments
     foreach (static::$global_arguments as $name => $callback) {
         if (!isset($arguments[$name])) {
             $arguments[$name] = call_user_func($callback, $arguments);
         }
     }
     $to_name = false;
     $to_id = null;
     if (is_object($to_or_user)) {
         $to_email = $to_or_user->getEmail();
         if (method_exists($to_or_user, 'getName')) {
             $to_name = $to_or_user->getName();
         }
         if (method_exists($to_or_user, 'getId')) {
             $to_id = $to_or_user->getId();
         }
     } else {
         if (is_string($to_or_user)) {
             $to_email = $to_or_user;
         } else {
             throw new MailerException("Unknown 'to' type " . gettype($to_or_user));
         }
     }
     if (!$to_name) {
         $to_name = $to_email;
     }
     // default arguments
     if (!isset($arguments['email'])) {
         $arguments['email'] = $to_email;
     }
     if (!isset($arguments['name'])) {
         $arguments['name'] = $to_name;
     }
     $compiled = self::compile($template_id, $arguments);
     $template = $compiled['text'];
     $html_template = $compiled['html'];
     $subject = $compiled['subject'];
     // now send the email
     // may throw MailerException
     if (self::$mock_mailer) {
         $message_id = call_user_func(self::$mock_mailer, $to_email, $to_name, $subject, $template, $html_template);
     } else {
         $message_id = Email::phpmailer($to_email, $to_name, $subject, $template, $html_template);
     }
     // allow others to capture this event
     $result = array("user_id" => $to_id, "to_name" => $to_name, "to_email" => $to_email, "subject" => $subject, "template_id" => $template_id, "arguments" => $arguments, "message_id" => $message_id);
     \Openclerk\Events::trigger('email_sent', $result);
     return $result;
 }
예제 #5
0
 /**
  * Execute OAuth2 authentication and return the user.
  */
 static function auth(ProviderInterface $provider)
 {
     if (!require_get("code", false)) {
         redirect($provider->getAuthorizationUrl());
         return false;
     } else {
         // optionally check for abuse etc
         if (!\Openclerk\Events::trigger('oauth2_auth', $provider)) {
             throw new UserAuthenticationException("Login was cancelled by the system.");
         }
         $token = $provider->getAccessToken('authorization_code', array('code' => require_get("code")));
         // now find the relevant user
         return $provider->getUserDetails($token);
     }
 }
예제 #6
0
 function prepare($query)
 {
     if ($this->shouldUseMaster($query)) {
         if ($this->isWriteQuery($query)) {
             // update the session, but only for write queries
             $_SESSION['master_slave_data'][$this->getTable($query)] = time();
         }
         $this->lastConnection = $this->master;
         Events::trigger('db_prepare_master', $query);
         return new ReplicatedQuery($this->master, $query, true);
     } else {
         $this->lastConnection = $this->slave;
         Events::trigger('db_prepare_slave', $query);
         return new ReplicatedQuery($this->slave, $query, false);
     }
 }
예제 #7
0
/**
 * Log an Exception into the {@code uncaught_exceptions} table.
 * If the exception is a {@link TypedException}, or the {@code argument_id} and
 * {@code argument_type} parameters are provided, this argument ID/type will be inserted as well.
 *
 * @param $argument_id optional argument type
 * @param $argmuent_type optional argument id
 */
function log_uncaught_exception($e, $argument_type = null, $argument_id = null)
{
    // check db() is defined
    $db = openclerk_exceptions_check_db($e);
    // events
    Events::trigger('exception_uncaught', $e);
    $extra_args = array();
    $extra_query = "";
    // logging
    if ($argument_id !== null && $argument_type !== null) {
        // unwrap it
        $extra_args[] = $argument_id;
        $extra_args[] = $argument_type;
        $extra_query .= ", argument_id=?, argument_type=?";
    } else {
        if ($e instanceof \Openclerk\TypedException) {
            // unwrap it
            $extra_args[] = $e->getArgumentId();
            $extra_args[] = $e->getArgumentType();
            $extra_query .= ", argument_id=?, argument_type=?";
        }
    }
    if (get_class($e) !== false) {
        $extra_args[] = get_class($e);
        $extra_query .= ", class_name=?";
    }
    $q = $db->prepare("INSERT INTO uncaught_exceptions SET\n    message=?,\n    previous_message=?,\n    filename=?,\n    line_number=?,\n    raw=?,\n    created_at=NOW() {$extra_query}");
    try {
        $serialized = serialize($e);
    } catch (\Exception $e2) {
        if (preg_match("#Serialization of .+ is not allowed#im", $e2->getMessage())) {
            $serialized = serialize($e2->getMessage());
        } else {
            $serialized = serialize($e->getMessage());
        }
    }
    $args = array_merge(array(mb_substr($e->getMessage(), 0, 255), mb_substr($e->getPrevious() ? $e->getPrevious()->getMessage() : "", 0, 255), mb_substr($e->getFile(), 0, 255), $e->getLine(), mb_substr($serialized, 0, 65535)), $extra_args);
    return $q->execute($args);
}
예제 #8
0
    }
    foreach (get_blockchain_currencies() as $explorer => $currencies) {
        foreach ($currencies as $cur) {
            if ($cur == $currency) {
                return "<span class=\"address " . $currency . "_address\"><code>" . htmlspecialchars($address) . "</code>\n          <a class=\"inspect\" href=\"" . htmlspecialchars(sprintf(get_site_config($currency . "_address_url"), $address)) . "\" title=\"Inspect with " . htmlspecialchars($explorer) . "\">?</a>\n        </span>";
            }
        }
    }
    return htmlspecialchars($address);
}
/**
 * Set up page load events
 */
\Openclerk\Events::on('pages_header_start', function ($data) {
    define('PAGE_RENDER_START', microtime(true));
});
/**
 * Set up page load events
 */
\Openclerk\Events::on('pages_footer_end', function ($data) {
    if (defined('PAGE_RENDER_START')) {
        $end_time = microtime(true);
        $time_diff = ($end_time - PAGE_RENDER_START) * 1000;
        echo "<!-- rendered in " . number_format($time_diff, 2) . " ms -->";
    }
    performance_metrics_page_end();
    echo "\n<!--\n" . print_r(Openclerk\MetricsHandler::getInstance()->printResults(), true) . "\n-->";
    if (is_admin()) {
        echo "\n<!-- " . print_r($_SESSION, true) . "\n-->";
    }
});
예제 #9
0
        // only supports GET relogins; TODO support POST relogins
        redirect(url_for('login', array('need_admin' => 1, 'destination' => $_SERVER['REQUEST_URI'])));
    }
}
function has_required_admin()
{
    global $has_required_admin;
    return $has_required_admin;
}
class SecurityException extends Exception
{
}
function require_user($user)
{
    global $errors;
    if (!$user) {
        if (!$errors) {
            $errors = array();
        }
        $errors[] = t("Could not find your profile on the system. You will need to login or signup again.");
        set_temporary_errors($errors);
        redirect(url_for('login'));
    }
}
// set up heavy request checks
\Openclerk\Events::on('openid_validate', function ($lightopenid) {
    check_heavy_request();
});
\Openclerk\Events::on('oauth2_auth', function ($oauth2) {
    check_heavy_request();
});
예제 #10
0
    {
        return $this->title;
    }
    function load()
    {
        require __DIR__ . "/../locale/" . $this->key . ".php";
        return $result;
    }
}
$locales = array('de' => 'German', 'fr' => 'French', 'jp' => 'Japanese', 'ru' => 'Russian', 'zh' => 'Chinese');
foreach ($locales as $locale => $title) {
    I18n::addAvailableLocale(new GenericLocale($locale, $title));
}
I18n::addDefaultKeys(array(':site_name' => get_site_config('site_name')));
// set locale as necessary
if (isset($_COOKIE["locale"]) && in_array($_COOKIE["locale"], array_keys(I18n::getAvailableLocales()))) {
    I18n::setLocale($_COOKIE["locale"]);
}
\Openclerk\Events::on('i18n_missing_string', function ($data) {
    $locale = $data['locale'];
    $key = $data['key'];
    log_uncaught_exception(new LocaleException("Locale '{$locale}': Missing key '{$key}'"));
});
/**
 * Helper function to mark strings that need to be translated on the client-side.
 */
function ct($s)
{
    // do not do any translation here - we have to do it on the client side!
    return $s;
}
예제 #11
0
파일: User.php 프로젝트: openclerk/users
 /**
  * Delete the given user. Triggers a 'user_deleted' event with the
  * current user as an argument.
  */
 function delete(\Db\Connection $db)
 {
     // delete all possible identities
     $q = $db->prepare("DELETE FROM user_passwords WHERE user_id=?");
     $q->execute(array($this->getId()));
     $q = $db->prepare("DELETE FROM user_openid_identities WHERE user_id=?");
     $q->execute(array($this->getId()));
     $q = $db->prepare("DELETE FROM user_oauth2_identities WHERE user_id=?");
     $q->execute(array($this->getId()));
     $q = $db->prepare("DELETE FROM user_valid_keys WHERE user_id=?");
     $q->execute(array($this->getId()));
     $q = $db->prepare("DELETE FROM users WHERE id=?");
     $q->execute(array($this->getId()));
     \Openclerk\Events::trigger('user_deleted', $this);
 }
예제 #12
0
파일: I18n.php 프로젝트: openclerk/i18n
 static function tWithoutCategory($key = false, $args = array())
 {
     $locale = self::getCurrentLocale();
     // remove any unnecessary whitespace in the key that won't be displayed
     $key = self::stripKey($key);
     if ($locale != 'en' && !isset(self::$global_loaded_locales[$locale])) {
         if (!isset(self::$locales[$locale])) {
             throw new LocaleException("No known locale '{$locale}'");
         }
         $localeInstance = self::$locales[$locale];
         $loaded = $localeInstance->load();
         self::$global_loaded_locales[$locale] = $loaded;
     }
     if (!is_array($args)) {
         throw new LocaleException("Expected array argument");
     }
     foreach ($args as $k => $value) {
         if (is_numeric($k)) {
             throw new LocaleException("Did not expect numeric key '{$k}'");
         }
         if (substr($k, 0, 1) !== ":") {
             throw new LocaleException("Did not expect non-parameterised key '{$k}'");
         }
     }
     // add default arguments (but keep any existing keys used)
     $args += self::$default_keys;
     if (!isset(self::$global_loaded_locales[$locale][$key])) {
         if ($locale != 'en') {
             \Openclerk\Events::trigger('i18n_missing_string', array("locale" => $locale, "key" => $key));
         }
         // if (is_admin() && get_site_config('show_i18n')) {
         //   return "[" . strtr($key, $args) . "]";
         // } else {
         return strtr($key, $args);
         // }
     }
     // if (is_admin() && get_site_config('show_i18n')) {
     //   return "[" . strtr(self::$global_loaded_locales[$locale][$key], $args) . "]";
     // } else {
     return strtr(self::$global_loaded_locales[$locale][$key], $args);
     // }
 }
예제 #13
0
/**
 * Wraps {@link #file_get_contents()} with timeout information etc.
 * May throw a {@link ExternalAPIException} if something unexpected occured.
 */
function crypto_get_contents($url, $options = array())
{
    \Openclerk\Events::trigger('curl_start', $url);
    // normally file_get_contents is OK, but if URLs are down etc, the timeout has no value and we can just stall here forever
    // this also means we don't have to enable OpenSSL on windows for file_get_contents('https://...'), which is just a bit of a mess
    $ch = crypto_curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Openclerk PHP client; ' . php_uname('s') . '; PHP/' . phpversion() . ')');
    curl_setopt($ch, CURLOPT_URL, $url);
    // curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    // curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_ENCODING, "gzip,deflate");
    // enable gzip decompression if necessary
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    foreach ($options as $key => $value) {
        curl_setopt($ch, $key, $value);
    }
    // run the query
    $res = curl_exec($ch);
    \Openclerk\Events::trigger('curl_end', $url);
    if ($res === false) {
        throw new ExternalAPIException('Could not get reply: ' . curl_error($ch));
    }
    crypto_check_response($res);
    return $res;
}
예제 #14
0
 /**
  * Try do OpenID validation (with the given redirect).
  * @return the validated LightOpenID object on success
  * @throws UserSignupException if anything bad happened
  */
 static function validateOpenID($openid, $redirect)
 {
     if (!is_valid_url($openid)) {
         throw new UserSignupException("That is not a valid OpenID identity.");
     }
     if (!$redirect) {
         throw new \InvalidArgumentException("No redirect provided.");
     }
     $light = new \LightOpenID(\Openclerk\Config::get("openid_host"));
     if (!$light->mode) {
         // we still need to authenticate
         $light->identity = $openid;
         $light->returnUrl = $redirect;
         redirect($light->authUrl());
         return false;
     } else {
         if ($light->mode == 'cancel') {
             // user has cancelled
             throw new UserSignupException("User has cancelled authentication.");
         } else {
             // otherwise login as necessary
             // optionally check for abuse etc
             if (!\Openclerk\Events::trigger('openid_validate', $light)) {
                 throw new UserSignupException("Login was cancelled by the system.");
             }
             if ($light->validate()) {
                 return $light;
             } else {
                 $error = $light->validate_error ? $light->validate_error : "Please try again.";
                 throw new UserSignupException("OpenID validation was not successful: " . $error);
             }
         }
     }
 }
예제 #15
0
 /**
  * However we can capture missing strings using the event framework.
  */
 function testEventIsThrown()
 {
     global $_test_event_is_thrown;
     $_test_event_is_thrown = false;
     $handler = \Openclerk\Events::on('i18n_missing_string', function ($string) {
         global $_test_event_is_thrown;
         $_test_event_is_thrown = $string;
     });
     t("a missing string");
     $this->assertEquals(array("locale" => "fr", "key" => "a missing string"), $_test_event_is_thrown);
     // and be a good events citizen
     \Openclerk\Events::unbind($handler);
 }
예제 #16
0
 /**
  * Render the given template.
  *
  * Searches for templates within each template directory, with the following
  * search order: {@code .php}, {@code .haml.php}, {@code .haml}.
  */
 static function requireTemplate($template, $arguments = array())
 {
     if (!is_array($arguments)) {
         throw new \InvalidArgumentException("Arguments '{$arguments}' need to be an array, not " . gettype($arguments));
     }
     Events::trigger('pages_template_start', $arguments + array('template' => $template));
     // so sub-templates can access all parent arguments
     if (self::$argument_stack) {
         $arguments += self::$argument_stack[count(self::$argument_stack) - 1];
     }
     // add to argument stack
     array_push(self::$argument_stack, $arguments);
     foreach (self::$templates as $dir) {
         // either include templates as direct PHP files...
         $file = $dir . "/" . $template . ".php";
         if (file_exists($file)) {
             // create locally scoped variables for all arguments
             foreach ($arguments as $key => $value) {
                 ${$key} = $value;
             }
             require $file;
             Events::trigger('pages_template_end', $arguments + array('template' => $template, 'filetype' => 'php'));
             // and then remove from argument stack
             array_pop(self::$argument_stack);
             return;
         }
         // ... or as HAML templates
         foreach (array($dir . "/" . $template . ".php.haml", $dir . "/" . $template . ".haml") as $file) {
             if (file_exists($file)) {
                 if (self::$executor === null) {
                     $haml = new \MtHaml\Environment('php', self::$haml_options);
                     self::$executor = new \MtHaml\Support\Php\Executor($haml, array('cache' => sys_get_temp_dir() . '/haml'));
                 }
                 // Compiles and executes the HAML template, with variables given as second argument
                 self::$executor->display($file, $arguments);
                 Events::trigger('pages_template_end', $arguments + array('template' => $template, 'filetype' => 'haml'));
                 // and then remove from argument stack
                 array_pop(self::$argument_stack);
                 return;
             }
         }
     }
     throw new TemplateNotFoundException("Could not find template '{$template}'", new TemplateNotFoundException("No template '{$template}' found in [" . implode(", ", self::$templates) . "]"));
 }