]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - lib/util.php
Set initialize_fave_tallys.php executable
[quix0rs-gnu-social.git] / lib / util.php
index c120fa3767de8daaadb1e71080432a46c865d8eb..dc853f657b1e53f76b00d162cb22a7dd49fc7ab2 100644 (file)
 
 /* XXX: break up into separate modules (HTTP, user, files) */
 
-// Show a server error
-
+/**
+ * Show a server error.
+ */
 function common_server_error($msg, $code=500)
 {
     $err = new ServerErrorAction($msg, $code);
     $err->showPage();
 }
 
-// Show a user error
+/**
+ * Show a user error.
+ */
 function common_user_error($msg, $code=400)
 {
     $err = new ClientErrorAction($msg, $code);
     $err->showPage();
 }
 
+/**
+ * This should only be used at setup; processes switching languages
+ * to send text to other users should use common_switch_locale().
+ *
+ * @param string $language Locale language code (optional; empty uses
+ *                         current user's preference or site default)
+ * @return mixed success
+ */
 function common_init_locale($language=null)
 {
     if(!$language) {
@@ -41,13 +52,24 @@ function common_init_locale($language=null)
     }
     putenv('LANGUAGE='.$language);
     putenv('LANG='.$language);
-    return setlocale(LC_ALL, $language . ".utf8",
+    $ok =  setlocale(LC_ALL, $language . ".utf8",
                      $language . ".UTF8",
                      $language . ".utf-8",
                      $language . ".UTF-8",
                      $language);
+
+    return $ok;
 }
 
+/**
+ * Initialize locale and charset settings and gettext with our message catalog,
+ * using the current user's language preference or the site default.
+ *
+ * This should generally only be run at framework initialization; code switching
+ * languages at runtime should call common_switch_language().
+ *
+ * @access private
+ */
 function common_init_language()
 {
     mb_internal_encoding('UTF-8');
@@ -69,8 +91,8 @@ function common_init_language()
         // don't do the job. en_US.UTF-8 should be there most of the
         // time, but not guaranteed.
         $ok = common_init_locale("en_US");
-        if (!$ok) {
-            // Try to find a complete, working locale...
+        if (!$ok && strtolower(substr(PHP_OS, 0, 3)) != 'win') {
+            // Try to find a complete, working locale on Unix/Linux...
             // @fixme shelling out feels awfully inefficient
             // but I don't think there's a more standard way.
             $all = `locale -a`;
@@ -82,13 +104,39 @@ function common_init_language()
                     }
                 }
             }
-            if (!$ok) {
-                common_log(LOG_ERR, "Unable to find a UTF-8 locale on this system; UI translations may not work.");
-            }
+        }
+        if (!$ok) {
+            common_log(LOG_ERR, "Unable to find a UTF-8 locale on this system; UI translations may not work.");
         }
         $locale_set = common_init_locale($language);
     }
 
+    common_init_gettext();
+}
+
+/**
+ * @access private
+ */
+function common_init_gettext()
+{
+    setlocale(LC_CTYPE, 'C');
+    // So we do not have to make people install the gettext locales
+    $path = common_config('site','locale_path');
+    bindtextdomain("statusnet", $path);
+    bind_textdomain_codeset("statusnet", "UTF-8");
+    textdomain("statusnet");
+}
+
+/**
+ * Switch locale during runtime, and poke gettext until it cries uncle.
+ * Otherwise, sometimes it doesn't actually switch away from the old language.
+ *
+ * @param string $language code for locale ('en', 'fr', 'pt_BR' etc)
+ */
+function common_switch_locale($language=null)
+{
+    common_init_locale($language);
+
     setlocale(LC_CTYPE, 'C');
     // So we do not have to make people install the gettext locales
     $path = common_config('site','locale_path');
@@ -97,6 +145,7 @@ function common_init_language()
     textdomain("statusnet");
 }
 
+
 function common_timezone()
 {
     if (common_logged_in()) {
@@ -111,7 +160,6 @@ function common_timezone()
 
 function common_language()
 {
-
     // If there is a user logged in and they've set a language preference
     // then return that one...
     if (_have_config() && common_logged_in()) {
@@ -143,8 +191,10 @@ function common_language()
     // Finally, if none of the above worked, use the site's default...
     return common_config('site', 'language');
 }
-// salted, hashed passwords are stored in the DB
 
+/**
+ * Salted, hashed passwords are stored in the DB.
+ */
 function common_munge_password($password, $id)
 {
     if (is_object($id) || is_object($password)) {
@@ -155,8 +205,9 @@ function common_munge_password($password, $id)
     return md5($password . $id);
 }
 
-// check if a username exists and has matching password
-
+/**
+ * Check if a username exists and has matching password.
+ */
 function common_check_user($nickname, $password)
 {
     // empty nickname always unacceptable
@@ -183,7 +234,9 @@ function common_check_user($nickname, $password)
     return $authenticatedUser;
 }
 
-// is the current user logged in?
+/**
+ * Is the current user logged in?
+ */
 function common_logged_in()
 {
     return (!is_null(common_current_user()));
@@ -229,12 +282,10 @@ function common_ensure_session()
 // 3) null to clear
 
 // Initialize to false; set to null if none found
-
 $_cur = false;
 
 function common_set_user($user)
 {
-
     global $_cur;
 
     if (is_null($user) && common_have_session()) {
@@ -320,7 +371,6 @@ function common_rememberme($user=null)
 
 function common_remembered_user()
 {
-
     $user = null;
 
     $packed = isset($_COOKIE[REMEMBERME]) ? $_COOKIE[REMEMBERME] : null;
@@ -382,14 +432,17 @@ function common_remembered_user()
     return $user;
 }
 
-// must be called with a valid user!
-
+/**
+ * must be called with a valid user!
+ */
 function common_forgetme()
 {
     common_set_cookie(REMEMBERME, '', 0);
 }
 
-// who is the current user?
+/**
+ * Who is the current user?
+ */
 function common_current_user()
 {
     global $_cur;
@@ -425,10 +478,11 @@ function common_current_user()
     return $_cur;
 }
 
-// Logins that are 'remembered' aren't 'real' -- they're subject to
-// cookie-stealing. So, we don't let them do certain things. New reg,
-// OpenID, and password logins _are_ real.
-
+/**
+ * Logins that are 'remembered' aren't 'real' -- they're subject to
+ * cookie-stealing. So, we don't let them do certain things. New reg,
+ * OpenID, and password logins _are_ real.
+ */
 function common_real_login($real=true)
 {
     common_ensure_session();
@@ -440,6 +494,29 @@ function common_is_real_login()
     return common_logged_in() && $_SESSION['real_login'];
 }
 
+/**
+ * Get a hash portion for HTTP caching Etags and such including
+ * info on the current user's session. If login/logout state changes,
+ * or we've changed accounts, or we've renamed the current user,
+ * we'll get a new hash value.
+ *
+ * This should not be considered secure information.
+ *
+ * @param User $user (optional; uses common_current_user() if left out)
+ * @return string
+ */
+function common_user_cache_hash($user=false)
+{
+    if ($user === false) {
+        $user = common_current_user();
+    }
+    if ($user) {
+        return crc32($user->id . ':' . $user->nickname);
+    } else {
+        return '0';
+    }
+}
+
 // get canonical version of nickname for comparison
 function common_canonical_nickname($nickname)
 {
@@ -531,9 +608,7 @@ function common_find_mentions($text, $notice)
     }
 
     if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) {
-
         // Get the context of the original notice, if any
-
         $originalAuthor   = null;
         $originalNotice   = null;
         $originalMentions = array();
@@ -569,7 +644,6 @@ function common_find_mentions($text, $notice)
         $matches = array_merge($tmatches[1], $atmatches[1]);
 
         foreach ($matches as $match) {
-
             $nickname = common_canonical_nickname($match[0]);
 
             // Try to get a profile for this nickname.
@@ -577,19 +651,15 @@ function common_find_mentions($text, $notice)
             // sender context.
 
             if (!empty($originalAuthor) && $originalAuthor->nickname == $nickname) {
-
                 $mentioned = $originalAuthor;
-
             } else if (!empty($originalMentions) &&
                        array_key_exists($nickname, $originalMentions)) {
-
                 $mentioned = $originalMentions[$nickname];
             } else {
                 $mentioned = common_relative_profile($sender, $nickname);
             }
 
             if (!empty($mentioned)) {
-
                 $user = User::staticGet('id', $mentioned->id);
 
                 if ($user) {
@@ -784,7 +854,10 @@ function common_linkify($url) {
         } elseif (is_string($longurl_data)) {
             $longurl = $longurl_data;
         } else {
-            throw new ServerException("Can't linkify url '$url'");
+            // Unable to reach the server to verify contents, etc
+            // Just pass the link on through for now.
+            common_log(LOG_ERR, "Can't linkify url '$url'");
+            $longurl = $url;
         }
     }
     $attrs = array('href' => $canon, 'title' => $longurl, 'rel' => 'external');
@@ -826,10 +899,10 @@ function common_linkify($url) {
     return XMLStringer::estring('a', $attrs, $url);
 }
 
-function common_shorten_links($text)
+function common_shorten_links($text, $always = false)
 {
     $maxLength = Notice::maxContent();
-    if ($maxLength == 0 || mb_strlen($text) <= $maxLength) return $text;
+    if (!$always && ($maxLength == 0 || mb_strlen($text) <= $maxLength)) return $text;
     return common_replace_urls_callback($text, array('File_redirection', 'makeShort'));
 }
 
@@ -969,8 +1042,7 @@ function common_local_url($action, $args=null, $params=null, $fragment=null, $ad
 
 function common_is_sensitive($action)
 {
-    static $sensitive = array('login', 'register', 'passwordsettings',
-                              'twittersettings', 'api');
+    static $sensitive = array('login', 'register', 'passwordsettings', 'api');
     $ssl = null;
 
     if (Event::handle('SensitiveAction', array($action, &$ssl))) {
@@ -1050,24 +1122,38 @@ function common_date_string($dt)
     if ($now < $t) { // that shouldn't happen!
         return common_exact_date($dt);
     } else if ($diff < 60) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('a few seconds ago');
     } else if ($diff < 92) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('about a minute ago');
     } else if ($diff < 3300) {
-        return sprintf(_('about %d minutes ago'), round($diff/60));
+        $minutes = round($diff/60);
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
+        return sprintf( ngettext('about one minute ago', 'about %d minutes ago', $minutes), $minutes);
     } else if ($diff < 5400) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('about an hour ago');
     } else if ($diff < 22 * 3600) {
-        return sprintf(_('about %d hours ago'), round($diff/3600));
+        $hours = round($diff/3600);
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
+        return sprintf( ngettext('about one hour ago', 'about %d hours ago', $hours), $hours);
     } else if ($diff < 37 * 3600) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('about a day ago');
     } else if ($diff < 24 * 24 * 3600) {
-        return sprintf(_('about %d days ago'), round($diff/(24*3600)));
+        $days = round($diff/(24*3600));
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
+        return sprintf( ngettext('about one day ago', 'about %d days ago', $days), $days);
     } else if ($diff < 46 * 24 * 3600) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('about a month ago');
     } else if ($diff < 330 * 24 * 3600) {
-        return sprintf(_('about %d months ago'), round($diff/(30*24*3600)));
+        $months = round($diff/(30*24*3600));
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
+        return sprintf( ngettext('about one month ago', 'about %d months ago',$months), $months);
     } else if ($diff < 480 * 24 * 3600) {
+        // TRANS: Used in notices to indicate when the notice was made compared to now.
         return _('about a year ago');
     } else {
         return common_exact_date($dt);
@@ -1168,8 +1254,9 @@ function common_broadcast_notice($notice, $remote=false)
     // DO NOTHING!
 }
 
-// Stick the notice on the queue
-
+/**
+ * Stick the notice on the queue.
+ */
 function common_enqueue_notice($notice)
 {
     static $localTransports = array('omb',
@@ -1189,9 +1276,8 @@ function common_enqueue_notice($notice)
         $transports[] = 'jabber';
     }
 
-    // @fixme move these checks into QueueManager and/or individual handlers
-    if ($notice->is_local == Notice::LOCAL_PUBLIC ||
-        $notice->is_local == Notice::LOCAL_NONPUBLIC) {
+    // We can skip these for gatewayed notices.
+    if ($notice->isLocal()) {
         $transports = array_merge($transports, $localTransports);
         if ($xmpp) {
             $transports[] = 'public';
@@ -1232,8 +1318,9 @@ function common_profile_url($nickname)
                             null, null, false);
 }
 
-// Should make up a reasonable root URL
-
+/**
+ * Should make up a reasonable root URL
+ */
 function common_root_url($ssl=false)
 {
     $url = common_path('', $ssl, false);
@@ -1244,9 +1331,10 @@ function common_root_url($ssl=false)
     return $url;
 }
 
-// returns $bytes bytes of random data as a hexadecimal string
-// "good" here is a goal and not a guarantee
-
+/**
+ * returns $bytes bytes of random data as a hexadecimal string
+ * "good" here is a goal and not a guarantee
+ */
 function common_good_rand($bytes)
 {
     // XXX: use random.org...?
@@ -1282,13 +1370,13 @@ function common_mtrand($bytes)
 /**
  * Record the given URL as the return destination for a future
  * form submission, to be read by common_get_returnto().
- * 
+ *
  * @param string $url
- * 
+ *
  * @fixme as a session-global setting, this can allow multiple forms
  * to conflict and overwrite each others' returnto destinations if
  * the user has multiple tabs or windows open.
- * 
+ *
  * Should refactor to index with a token or otherwise only pass the
  * data along its intended path.
  */
@@ -1301,13 +1389,13 @@ function common_set_returnto($url)
 /**
  * Fetch a return-destination URL previously recorded by
  * common_set_returnto().
- * 
+ *
  * @return mixed URL string or null
- * 
+ *
  * @fixme as a session-global setting, this can allow multiple forms
  * to conflict and overwrite each others' returnto destinations if
  * the user has multiple tabs or windows open.
- * 
+ *
  * Should refactor to index with a token or otherwise only pass the
  * data along its intended path.
  */
@@ -1336,7 +1424,7 @@ function common_log_line($priority, $msg)
 {
     static $syslog_priorities = array('LOG_EMERG', 'LOG_ALERT', 'LOG_CRIT', 'LOG_ERR',
                                       'LOG_WARNING', 'LOG_NOTICE', 'LOG_INFO', 'LOG_DEBUG');
-    return date('Y-m-d H:i:s') . ' ' . $syslog_priorities[$priority] . ': ' . $msg . "\n";
+    return date('Y-m-d H:i:s') . ' ' . $syslog_priorities[$priority] . ': ' . $msg . PHP_EOL;
 }
 
 function common_request_id()
@@ -1392,7 +1480,12 @@ function common_log_db_error(&$object, $verb, $filename=null)
 {
     $objstr = common_log_objstring($object);
     $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
-    common_log(LOG_ERR, $last_error->message . '(' . $verb . ' on ' . $objstr . ')', $filename);
+    if (is_object($last_error)) {
+        $msg = $last_error->message;
+    } else {
+        $msg = 'Unknown error (' . var_export($last_error, true) . ')';
+    }
+    common_log(LOG_ERR, $msg . '(' . $verb . ' on ' . $objstr . ')', $filename);
 }
 
 function common_log_objstring(&$object)
@@ -1434,7 +1527,7 @@ function common_valid_tag($tag)
  * Determine if given domain or address literal is valid
  * eg for use in JIDs and URLs. Does not check if the domain
  * exists!
- * 
+ *
  * @param string $domain
  * @return boolean valid or not
  */
@@ -1765,7 +1858,6 @@ function common_compatible_license($from, $to)
  */
 function common_database_tablename($tablename)
 {
-
   if(common_config('db','quote_identifiers')) {
       $tablename = '"'. $tablename .'"';
   }
@@ -1879,6 +1971,15 @@ function common_url_to_nickname($url)
             $path = preg_replace('@/$@', '', $parts['path']);
             $path = preg_replace('@^/@', '', $path);
             $path = basename($path);
+
+            // Hack for MediaWiki user pages, in the form:
+            // http://example.com/wiki/User:Myname
+            // ('User' may be localized.)
+            if (strpos($path, ':')) {
+                $parts = array_filter(explode(':', $path));
+                $path = $parts[count($parts) - 1];
+            }
+
             if ($path) {
                 return common_nicknamize($path);
             }