]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/Utils.php
Markdown: don't escape content + sanitize sensible tags
[github/shaarli/Shaarli.git] / application / Utils.php
index 658b97bc2f03fff6d2f5580fa912165d1a422cdb..868946df756d98c1a726350cd524556e48b4a667 100644 (file)
@@ -3,6 +3,24 @@
  * Shaarli utilities
  */
 
+/**
+ * Logs a message to a text file
+ *
+ * The log format is compatible with fail2ban.
+ *
+ * @param string $logFile  where to write the logs
+ * @param string $clientIp the client's remote IPv4/IPv6 address
+ * @param string $message  the message to log
+ */
+function logm($logFile, $clientIp, $message)
+{
+    file_put_contents(
+        $logFile,
+        date('Y/m/d H:i:s').' - '.$clientIp.' - '.strval($message).PHP_EOL,
+        FILE_APPEND
+    );
+}
+
 /**
  *  Returns the small hash of a string, using RFC 4648 base64url format
  *
@@ -44,19 +62,27 @@ function endsWith($haystack, $needle, $case=true)
 }
 
 /**
- * Same as nl2br(), but escapes < and >
+ * Htmlspecialchars wrapper
+ *
+ * @param string $str the string to escape.
+ *
+ * @return string escaped.
  */
-function nl2br_escaped($html)
+function escape($str)
 {
-    return str_replace('>','&gt;',str_replace('<','&lt;',nl2br($html)));
+    return htmlspecialchars($str, ENT_COMPAT, 'UTF-8', false);
 }
 
 /**
- * htmlspecialchars wrapper
+ * Reverse the escape function.
+ *
+ * @param string $str the string to unescape.
+ *
+ * @return string unescaped string.
  */
-function escape($str)
+function unescape($str)
 {
-    return htmlspecialchars($str, ENT_COMPAT, 'UTF-8', false);
+    return htmlspecialchars_decode($str);
 }
 
 /**
@@ -72,12 +98,14 @@ function sanitizeLink(&$link)
 
 /**
  * Checks if a string represents a valid date
+
+ * @param string $format The expected DateTime format of the string
+ * @param string $string A string-formatted date
  *
- * @param string        a string-formatted date
- * @param format        the expected DateTime format of the string
- * @return              whether the string is a valid date
- * @see                 http://php.net/manual/en/class.datetime.php
- * @see                 http://php.net/manual/en/datetime.createfromformat.php
+ * @return bool whether the string is a valid date
+ *
+ * @see http://php.net/manual/en/class.datetime.php
+ * @see http://php.net/manual/en/datetime.createfromformat.php
  */
 function checkDateFormat($format, $string)
 {
@@ -97,12 +125,12 @@ function checkDateFormat($format, $string)
  */
 function generateLocation($referer, $host, $loopTerms = array())
 {
-    $final_referer = '?';
+    $finalReferer = '?';
 
     // No referer if it contains any value in $loopCriteria.
     foreach ($loopTerms as $value) {
         if (strpos($referer, $value) !== false) {
-            return $final_referer;
+            return $finalReferer;
         }
     }
 
@@ -111,9 +139,93 @@ function generateLocation($referer, $host, $loopTerms = array())
         $host = substr($host, 0, $pos);
     }
 
-    if (!empty($referer) && strpos(parse_url($referer, PHP_URL_HOST), $host) !== false) {
-        $final_referer = $referer;
+    $refererHost = parse_url($referer, PHP_URL_HOST);
+    if (!empty($referer) && (strpos($refererHost, $host) !== false || startsWith('?', $refererHost))) {
+        $finalReferer = $referer;
+    }
+
+    return $finalReferer;
+}
+
+/**
+ * Validate session ID to prevent Full Path Disclosure.
+ *
+ * See #298.
+ * The session ID's format depends on the hash algorithm set in PHP settings
+ *
+ * @param string $sessionId Session ID
+ *
+ * @return true if valid, false otherwise.
+ *
+ * @see http://php.net/manual/en/function.hash-algos.php
+ * @see http://php.net/manual/en/session.configuration.php
+ */
+function is_session_id_valid($sessionId)
+{
+    if (empty($sessionId)) {
+        return false;
     }
 
-    return $final_referer;
+    if (!$sessionId) {
+        return false;
+    }
+
+    if (!preg_match('/^[a-zA-Z0-9,-]{2,128}$/', $sessionId)) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * In a string, converts URLs to clickable links.
+ *
+ * @param string $text       input string.
+ * @param string $redirector if a redirector is set, use it to gerenate links.
+ *
+ * @return string returns $text with all links converted to HTML links.
+ *
+ * @see Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722
+ */
+function text2clickable($text, $redirector)
+{
+    $regex = '!(((?:https?|ftp|file)://|apt:|magnet:)\S+[[:alnum:]]/?)!si';
+
+    if (empty($redirector)) {
+        return preg_replace($regex, '<a href="$1">$1</a>', $text);
+    }
+    // Redirector is set, urlencode the final URL.
+    return preg_replace_callback(
+        $regex,
+        function ($matches) use ($redirector) {
+            return '<a href="' . $redirector . urlencode($matches[1]) .'">'. $matches[1] .'</a>';
+        },
+        $text
+    );
+}
+
+/**
+ * This function inserts &nbsp; where relevant so that multiple spaces are properly displayed in HTML
+ * even in the absence of <pre>  (This is used in description to keep text formatting).
+ *
+ * @param string $text input text.
+ *
+ * @return string formatted text.
+ */
+function space2nbsp($text)
+{
+    return preg_replace('/(^| ) /m', '$1&nbsp;', $text);
+}
+
+/**
+ * Format Shaarli's description
+ * TODO: Move me to ApplicationUtils when it's ready.
+ *
+ * @param string $description shaare's description.
+ * @param string $redirector  if a redirector is set, use it to gerenate links.
+ *
+ * @return string formatted description.
+ */
+function format_description($description, $redirector) {
+    return nl2br(space2nbsp(text2clickable($description, $redirector)));
 }