+function pl_redirect($path, $query = null, $fragment = null)
+{
+ global $globals;
+ http_redirect($globals->baseurl . '/' . pl_url($path, $query, $fragment));
+}
+
+function pl_entities($text, $mode = ENT_COMPAT)
+{
+ return htmlentities($text, $mode, 'UTF-8');
+}
+
+function pl_entity_decode($text, $mode = ENT_COMPAT)
+{
+ return html_entity_decode($text, $mode, 'UTF-8');
+}
+
+function pl_flatten_aux(array &$dest, array $src)
+{
+ foreach ($src as $val) {
+ if (is_array($val)) {
+ pl_flatten_aux($dest, $val);
+ } else {
+ $dest[] = $val;
+ }
+ }
+}
+
+function pl_flatten(array $array)
+{
+ $res = array();
+ pl_flatten_aux($res, $array);
+ return $res;
+}
+
+/**
+ * Returns the path of a static content, including, when appropriate, the
+ * version number. This is used to avoid cross-version cache issues, by ensuiring
+ * that all static resources are served on a unique path.
+ */
+function pl_static_content_path($path, $filename)
+{
+ global $globals;
+ if (isset($globals) && isset($globals->version)) {
+ return $path . $globals->version . '/' . $filename;
+ } else {
+ return $path . $filename;
+ }
+}
+
+/**
+ * Adds content type headers; by default the encoding used is utf-8.
+ */
+function pl_content_headers($content_type, $encoding = 'utf-8')
+{
+ if (is_null($encoding)) {
+ header("Content-Type: $content_type");
+ } else {
+ header("Content-Type: $content_type; charset=$encoding");
+ }
+}
+
+/**
+ * Adds content type and caching headers for content generated by plat/al. The
+ * cache duration defaults to the global static_cache_duration. No encoding is
+ * applied by default.
+ */
+function pl_cached_content_headers($content_type, $encoding = null, $cache_duration = -1)
+{
+ global $globals;
+ $cache_duration = ($cache_duration < 0 ? $globals->static_cache_duration : $cache_duration);
+
+ header("Cache-Control: max-age=$cache_duration");
+ header("Expires: " . gmdate('D, d M Y H:i:s', time() + $cache_duration) . " GMT");
+ header("Pragma: ");
+ pl_content_headers($content_type, $encoding);
+}
+
+/**
+ * Same as above, but applying an expiration time suitable for cacheable dynamic
+ * content (eg. photos, logos, ...).
+ */
+function pl_cached_dynamic_content_headers($content_type, $encoding = null)
+{
+ global $globals;
+ pl_cached_content_headers($content_type, $encoding, $globals->dynamic_cache_duration);
+}