Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F11707870
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/finger/ThimblDocument.php b/finger/ThimblDocument.php
index 0c11c7c..de068b7 100644
--- a/finger/ThimblDocument.php
+++ b/finger/ThimblDocument.php
@@ -1,210 +1,212 @@
<?php
/**
* Thimbl document
*/
class ThimblDocument {
/**
* The Thimbl raw deserialized .plan data
* @var Object
*/
private $data;
/**
* Initializes a new instance of the ThimblDocument object
*
* @param Object $data An object matching a deserialized json Thimbl plan file
*/
public function __construct ($data) {
$this->data = $data;
}
/**
* Cleans a string, for JSON decode error
*
* @param string &$string The string to clean
*/
private static function ApplyCleanKludge (&$string) {
$string = clean_string($string);
//Issue for nknouf@zeitkunst.org
$wrongText = <<<'END'
âM-^Y» @zeminlu: UNIX' Russian Roulette: sudo [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo âM-^@M-^\You liveâM-^@M-^]
END;
$rightText = "@zeminlu: UNIX' Russian Roulette: sudo [ \$[ \$RANDOM % 6 ] == 0 ] && rm -rf / || echo";
//$rightText = "x";
$string = str_replace(trim($wrongText), $rightText, $string);
}
/**
* Gets a new instance of the ThimblDocument object from a JSON string
+ *
+ * @return ThimblDocument|null
*/
public static function FromJSON ($string) {
self::ApplyCleanKludge($string);
$data = json_decode($string);
return is_object($data) ? new ThimblDocument($data) : null;
}
/**
* Gets the finger address
*
* @return string The finger address
*/
public function GetAddress () {
return $this->data->address;
}
/**
* Gets the name
*
* @return string The name
*/
public function GetName () {
return $this->data->name;
}
/**
* Gets the properties
*
* @return Array An array with the properties
*/
public function GetProperties () {
return (array)$this->data->properties;
}
/**
* Gets the specified property
*
* @param string $property The property
* @return string The property value
*/
public function GetProperty ($property) {
$properties = $this->GetProperties();
if (array_key_exists($property, $properties)) {
return $properties[$property];
}
return null;
}
/**
* Gets the messages
*
* @return Array An array with the messages
*/
public function GetMessages () {
$messages = array();
foreach ($this->data->messages as $message) {
$messages[] = (array)$message;
}
return array_reverse($messages);
}
/**
* Gets the people the current user follows
*
* @param int $avatarSize The avatar width
* @param string $avatarFallbackStyle The avatar fallback Gravatar style ('mm', 'blank', '404', 'identicon', 'wavatar', 'retro')
* @return Array An array with the followed people
*/
public function GetFollowing ($avatarSize = 80, $avatarFallbackStyle = 'mm') {
$following = array();
foreach ($this->data->following as $contact) {
$following[] = [
'nick' => $contact->nick,
'address' => $contact->address,
'avatar' => self::GetGravatar($contact->address, $avatarSize, $avatarFallbackStyle)
];
}
return $following;
}
/**
* Gets the gravatar
*
* @param string $email The e-mail address
* @param int $size The avatar width
* @param string $fallbackStyle The avatar fallback Gravatar style ('mm', 'blank', '404', 'identicon', 'wavatar', 'retro')
* @return string The Gravatar URL, or if not available a fallback representation
*/
private static function GetGravatar ($email, $size = 200, $fallbackStyle = 'mm') {
$hash = md5(strtolower(trim($email)));
return "//www.gravatar.com/avatar/$hash?s=$size&d=$fallbackStyle";
}
/**
* Gets the avatar
*
* @param int $size The avatar width
* @param string $fallbackStyle The avatar fallback Gravatar style ('mm', 'blank', '404', 'identicon', 'wavatar', 'retro')
* @return string The Gravatar URL, or if not available a fallback representation
*/
public function GetAvatar ($size = 200, $fallbackStyle = 'mm') {
return self::GetGravatar($this->data->properties->email, $size, $fallbackStyle);
}
/**
* Gets the unixtime from a Thimbl time
*
* @param long $time The date, in a Thimbl time representation
* @return int The date, in a unixtime representation
*/
public static function ThimblTimeToUnixtime ($time) {
return strtotime($time);
}
/**
* Formats a message
*
* @param string $message The message to format
* @return string The formatted message
*/
public function FormatMessage ($message) {
$message = preg_replace(
"/(?<!a href=\")(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/i",
"<a href=\"\\0\">\\0</a>",
$message
);
return $message;
}
}
/*
Here a minimal representation of a deserialized Thimbl .plan file:
stdClass Object
(
[messages] => Array
(
[0] => stdClass Object
(
[text] => A message
[time] => 20130917204527
)
)
[replies] => stdClass Object
(
)
[address] => user@domain.tld
[following] => Array
(
[0] => stdClass Object
(
[nick] => dk
[address] => dk@telekommunisten.org
)
)
[name] => user
[properties] => stdClass Object
(
[website] => http://www.domain.tld
[email] => user@domain.tld
[mobile] => Mobile withheld
)
)
*/
diff --git a/finger/thimbl.php b/finger/thimbl.php
index 4088c34..56b05b2 100644
--- a/finger/thimbl.php
+++ b/finger/thimbl.php
@@ -1,47 +1,145 @@
<?php
-if (array_key_exists('user', $_REQUEST)) {
- require_once('FingerClient.php');
- $client = FingerClient::fromAddress($_REQUEST['user']);
- $blackListFile = 'finger/blacklist.txt';
- if (file_exists($blackListFile)) {
- $client->AddToBlacklist(explode("\n", file_get_contents($blackListFile)));
+/**
+ * Represents a controller to process the Thimbl client request
+ */
+class ThimblController {
+ ///
+ /// Constants
+ ///
+
+ /**
+ * The path to the server to not finger
+ *
+ * @const
+ */
+ const BLACKLIST_FILE = 'finger/blacklist.txt';
+
+ ///
+ /// Private properties
+ ///
+
+ /**
+ * Thimbl document from a plan file
+ *
+ * @var ThimblDocument|null
+ */
+ private $thimblDocument = null;
+
+ /**
+ * A finger client instance used to fetch the plan file containing the Thimbl feed
+ *
+ * @var FingerClient
+ */
+ private $client;
+
+ /**
+ * Errors occured during request processing
+ *
+ * @var array
+ */
+ private $errors = [];
+
+ /**
+ * Runs the controller logic
+ */
+ public function run () {
+ if (array_key_exists('user', $_REQUEST)) {
+ $this->processThimblClientRequest();
+ }
+
+ if (count($this->errors)) {
+ $this->printErrors();
+ }
+
+ $this->printInputForm();
+
+ if ($this->thimblDocument !== null) {
+ $this->printThimblFeed();
+ }
}
- if ($client == null) {
- echo '<div class="alert-box alert">Invalid Finger address format.</div>';
- } elseif (!$client->Run()) {
- echo '<div class="alert-box alert">', $client->lastError, '</div>';
- } else {
- $client->Parse();
- if (!$planField = $client->Get('Plan')) {
- echo '<div class="alert-box alert">Finger connection successful, but there is no plan file.</div>';
- } else {
- require_once('ThimblDocument.php');
- if (!$plan = ThimblDocument::FromJSON($planField)) {
- echo '<div class="alert-box alert">Finger connection successful, but the plan file format is not a Thimbl one.<br />';
- echo 'JSON error returned by the parser: ', json_last_error_msg();
- echo '</div>';
- echo "<h2>Plan file for $_REQUEST[user]</h2>";
- echo '<pre>', clean_string($planField), '</pre>';
- }
+
+ /**
+ * Processes Thimbl client request
+ */
+ public function processThimblClientRequest() {
+ require_once('FingerClient.php');
+
+ $this->client = FingerClient::fromAddress($_REQUEST['user']);
+ if ($this->client === null) {
+ $this->errors[] = 'Invalid Finger address format.';
+ return;
+ }
+
+ $this->handleBlackList();
+
+ if (!$this->client->Run()) {
+ $this->errors[] = $this->client->lastError;
+ return;
+ }
+
+ $this->client->Parse();
+ if (!$planField = $this->client->Get('Plan')) {
+ $this->errors[] = 'Finger connection successful, but there is no plan file.';
+ return;
+ }
+
+ require_once('ThimblDocument.php');
+ if (!$this->thimblDocument = ThimblDocument::FromJSON($planField)) {
+ $this->printDebugPlanMessage($planField);
}
}
+
+ /**
+ * Prints debug .plan message
+ *
+ * @param string $planField
+ */
+ private function printDebugPlanMessage ($planField) {
+ echo '<div class="alert-box alert">Finger connection successful, but the plan file format is not a Thimbl one.<br />';
+ echo 'JSON error returned by the parser: ', json_last_error_msg();
+ echo '</div>';
+ echo "<h2>Plan file for $_REQUEST[user]</h2>";
+ echo '<pre>', clean_string($planField), '</pre>';
+ }
+
+ /**
+ * Handles blacklist
+ */
+ private function handleBlackList () {
+ if (file_exists(self::BLACKLIST_FILE)) {
+ $blackListedServers = explode(
+ "\n",
+ trim(
+ file_get_contents(self::BLACKLIST_FILE)
+ )
+ );
+ $this->client->AddToBlacklist($blackListedServers);
+ }
+ }
+
+ /**
+ * Prints errors
+ */
+ public function printErrors () {
+ foreach ($this->errors as $error) {
+ echo '<div class="alert-box alert">', $error, '</div>';
+ }
+ }
+
+ /**
+ * Prints input form
+ */
+ public function printInputForm () {
+ include('thimbl_inputForm.html');
+ }
+
+ public function printThimblFeed () {
+ $plan = $this->thimblDocument;
+
+ echo "<h2>Thimbl feed for $_REQUEST[user]</h2>";
+ require_once('thimbl_feed.php');
+ }
}
-?>
-<h2>Who?</h2>
-<form>
-<div class="row collapse">
- <div class="ten mobile-three columns">
- <input type="text" name="user" id="user" value="<?= $_REQUEST['user'] ?>" placeholder="username@server" />
- </div>
- <div class="two mobile-one columns">
- <input type="submit" class="button expand postfix" value="Finger" />
- </div>
-</div>
-</form>
-<?php
-if ($plan) {
- echo "<h2>Thimbl feed for $_REQUEST[user]</h2>";
- require_once('thimbl_feed.php');
-}
-?>
+
+(new ThimblController())->run();
diff --git a/finger/thimbl_inputForm.html b/finger/thimbl_inputForm.html
new file mode 100644
index 0000000..fecd169
--- /dev/null
+++ b/finger/thimbl_inputForm.html
@@ -0,0 +1,11 @@
+<h2>Who?</h2>
+<form>
+<div class="row collapse">
+ <div class="ten mobile-three columns">
+ <input type="text" name="user" id="user" value="<?= $_REQUEST['user'] ?>" placeholder="username@server" />
+ </div>
+ <div class="two mobile-one columns">
+ <input type="submit" class="button expand postfix" value="Finger" />
+ </div>
+</div>
+</form>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Sep 15, 03:56 (1 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2978092
Default Alt Text
(12 KB)
Attached To
Mode
rTOOLS Nasqueron Tools
Attached
Detach File
Event Timeline
Log In to Comment