Ejemplo n.º 1
0
 /**
  * Method used to end with
  * a Rss value from
  * an endpoint.
  */
 public static function endWithRSS($_payload, $feed_title = '', $code = 200)
 {
     global $app;
     $plugins = self::getPayload($_payload);
     // retrieve app config
     $app_config = self::getConfig();
     $url = $app_config['client_url'];
     // create a feed
     $feed = new \Suin\RSSWriter\Feed();
     // create a channel
     $channel = new \Suin\RSSWriter\Channel();
     $channel->title($feed_title)->url($url)->language('en-US')->pubDate(time())->lastBuildDate(time())->ttl(60)->appendTo($feed);
     foreach ($plugins->toArray() as $current_plugin) {
         $plugin = Plugin::with('descriptions', 'authors', 'versions', 'screenshots', 'tags', 'langs')->short()->where('key', '=', $current_plugin['key'])->where('active', '=', 1)->first();
         if ($plugin) {
             $plugin = $plugin->toArray();
             // compute date
             $date = $plugin['date_updated'] != "" ? $plugin['date_updated'] : ($plugin['date_added'] != "" ? $plugin['date_added'] : date("Y-m-d"));
             // compute description
             $description = "";
             foreach ($plugin['descriptions'] as $current_desc) {
                 if ($current_desc['lang'] == 'en') {
                     $description = $current_desc['long_description'];
                     break;
                 }
             }
             if (empty($description)) {
                 $description = $plugin['descriptions'][0]['long_description'];
             }
             // find last version (the first in list)
             $version_num = $version_compat = "";
             $last_version = array_shift($plugin['versions']);
             if ($last_version != NULL) {
                 $version_num = $last_version['num'];
                 $version_compat = $last_version['compatibility'];
                 $description .= "<br />\n                                <br /> Version: {$version_num}\n                                <br /> Compatibility: {$version_compat}";
             }
             // add plugin to feed
             $item = new \Suin\RSSWriter\Item();
             $item->title($plugin['name'] . " " . $version_num)->description($description)->contentEncoded($description)->url($url . '/#/plugin/' . $plugin['key'])->pubDate(strtotime($date))->guid($plugin['name'] . "_" . $date . "_" . $version_num, true)->appendTo($channel);
         }
     }
     // render feed
     $app->halt($code, $feed->render());
 }
Ejemplo n.º 2
0
 public function verifyAndUpdatePlugins()
 {
     $plugins = Plugin::where('active', '=', 1)->get();
     // Going to compare checksums
     // for each of these plugins
     $n = 0;
     foreach ($plugins as $num => $plugin) {
         $n++;
         // Defaults not to update
         $update = false;
         // fetching via http
         $xml = @file_get_contents($plugin->xml_url);
         if (!$xml) {
             echo 'Plugin (' . $n . '/' . sizeof($plugins) . "): \"" . $plugin->name . "\" Cannot get XML file via HTTP, Skipping.\n";
             continue;
         }
         $crc = md5($xml);
         // compute crc
         if ($plugin->xml_crc != $crc || $plugin->name == NULL) {
             $update = true;
             // if we got
             // missing name or changing
             // crc, then we're going to
             // update that one
         } else {
             echo 'Plugin (' . $n . '/' . sizeof($plugins) . "): \"" . $plugin->name . "\" Already updated, Skipping.\n";
             continue;
         }
         // loading XML OO-style with simplemxl
         $xml = new ValidableXMLPluginDescription($xml);
         if (!$xml->isValid()) {
             echo 'Plugin (' . $n . '/' . sizeof($plugins) . "): \"" . $plugin->name . "\" Unreadable/Non validable XML, Skipping.\n";
             echo "Errors: \n";
             foreach ($xml->errors as $error) {
                 echo " - " . $error . "\n";
             }
             continue;
         }
         $xml = $xml->contents;
         echo 'Plugin (' . $n . '/' . sizeof($plugins) . '): Updating ... ';
         $this->updatePlugin($plugin, $xml, $crc);
     }
 }
Ejemplo n.º 3
0
<?php

use Illuminate\Database\Capsule\Manager as DB;
use API\Core\Tool;
use API\Model\Plugin;
use API\OAuthServer\OAuthHelper;
$version_plugins = Tool::makeEndpoint(function ($version) {
    OAuthHelper::needsScopes(['version', 'plugins']);
    $plugins = Tool::paginateCollection(Plugin::short()->with('authors', 'versions', 'descriptions')->withAverageNote()->descWithLang(Tool::getRequestLang())->withGlpiVersion($version));
    Tool::endWithJson($plugins);
});
$app->get('/version/:version/plugin', $version_plugins);
$app->options('/version/:version/plugin', function () {
});
Ejemplo n.º 4
0
});
$tag_single = Tool::makeEndpoint(function ($key) use($app) {
    OAuthHelper::needsScopes(['tag']);
    $tag = Tag::where('key', '=', $key)->first();
    if ($tag == NULL) {
        throw new \API\Exception\ResourceNotFound('Tag', $key);
    }
    Tool::endWithJson($tag);
});
$tag_plugins = Tool::makeEndpoint(function ($key) use($app) {
    OAuthHelper::needsScopes(['tag', 'plugins']);
    $tag = Tag::where('key', '=', $key)->first();
    if ($tag == NULL) {
        throw new \API\Exception\ResourceNotFound('Tag', $key);
    }
    $plugins = Tool::paginateCollection(Plugin::with('versions', 'authors')->short()->withAverageNote()->descWithLang(Tool::getRequestLang())->withTag($tag));
    Tool::endWithJson($plugins);
});
// HTTP rest map
$app->get('/tags', $tags_all);
$app->get('/tags/top', $tags_top);
$app->get('/tags/:id/plugin', $tag_plugins);
$app->get('/tags/:id', $tag_single);
$app->options('/tags', function () {
});
$app->options('/tags/top', function () {
});
$app->options('/tags/:id/plugin', function ($id) {
});
$app->options('/tags/:id', function ($id) {
});
Ejemplo n.º 5
0
/**
 * Download
 *
 * This REST module hooks on
 * following URLs
 *
 * /download/:plugin_id
 */
use API\Core\Tool;
use API\Model\Plugin;
use API\Model\PluginDownload;
use Illuminate\Database\Capsule\Manager as DB;
use API\OAuthServer\OAuthHelper;
$download = Tool::makeEndpoint(function ($key) use($app) {
    $plugin = Plugin::where('key', '=', $key)->first();
    $plugin->download_count = DB::raw('download_count + 1');
    $plugin->save();
    $plugin_download = new PluginDownload();
    $plugin_download->downloaded_at = DB::raw('NOW()');
    $plugin_download->plugin_id = $plugin->id;
    $plugin_download->save();
    /**
     * @MonkeyPatch
     * @todo remove this as soon as possible once
     * all our famous, star, since-day-one
     * contributors took the time
     * to update their XML file.
     */
    $indepnetFixSearchPattern = '/https:\\/\\/forge\\.indepnet\\.net/';
    if (preg_match($indepnetFixSearchPattern, $plugin->download_url)) {
Ejemplo n.º 6
0
 /**
  * Task : updatePlugin()
  *
  * Note: This function does direct output,
  * in fact it builds the log string
  * that concerns the update of a
  * plugin.
  */
 private function updatePlugin($plugin, $index = null, $length = null, $subtasks)
 {
     // Displaying index / length
     $this->outputStr('Plugin (' . $index . '/' . $length . ') (id #' . $plugin->id . '): ');
     $update = false;
     // This can be used to detect the state
     // in some way (think about it)
     $this->currentXml = null;
     $this->currentPluginState = null;
     // fetching via http
     $unableToFetch = false;
     $httpClient = new GuzzleHttpClient();
     try {
         $pluginXmlRequest = $httpClient->get($plugin->xml_url, ["headers" => ["User-Agent" => Tool::getConfig()['glpi_plugin_directory_user_agent']]]);
     } catch (\GuzzleHttp\Exception\ConnectException $e) {
         $unableToFetch = true;
     } finally {
         if ($unableToFetch || !$unableToFetch && $pluginXmlRequest->getStatusCode() != 200) {
             if ($this->pluginMaxConsecutiveXmlFetchFails) {
                 $fetchFailCount = $plugin->incrementXmlFetchFailCount();
                 if ($fetchFailCount == $this->pluginMaxConsecutiveXmlFetchFails) {
                     $this->triggerPluginXmlStateChange($plugin, 'bad_xml_url', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks));
                     $plugin->resetXmlFetchFailCount();
                 }
             } else {
                 $this->triggerPluginXmlStateChange($plugin, 'bad_xml_url', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks));
             }
             $this->outputStr($plugin->xml_url . "\" Cannot get XML file via HTTP, Skipping.\n");
             if ($this->throwsExceptions) {
                 throw new InvalidXML('url', $plugin->xml_url);
             }
             return false;
         } else {
             $plugin->resetXmlFetchFailCount();
         }
     }
     $xml = $pluginXmlRequest->getBody();
     $this->currentXml = (string) $xml;
     $crc = md5($xml);
     // compute crc
     if ($plugin->xml_crc != $crc || $plugin->name == NULL) {
         $update = true;
         // if we got
         // missing name or changing
         // crc, then we're going to
         // update that one.
         // missing name means it's
         // the first time the plugin
         // is updated
     } else {
         $this->outputStr("\"" . $plugin->name . "\" Already up-to-date, Skipping.\n");
         $this->triggerPluginXmlStateChange($plugin, 'passing', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks));
         return false;
     }
     try {
         $xml = new ValidableXMLPluginDescription($xml);
         $xml->validate();
     } catch (\API\Exception\InvalidXML $e) {
         $_unreadable = '';
         if (isset($xml->contents) && $xml->contents->name && sizeof($xml->contents->name->children()) < 1 && strlen((string) $xml->contents->name) < 80) {
             $_unreadable .= '"' . (string) $xml->contents->key . '" ';
         } elseif ($plugin->name) {
             $_unreadable .= '"' . $plugin->name . '" ';
         }
         $this->triggerPluginXmlStateChange($plugin, 'xml_error', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks));
         $_unreadable .= "Unreadable/Non validable XML, error: " . $e->getRepresentation() . " Skipping.\n";
         $this->outputStr($_unreadable);
         if ($this->throwsExceptions) {
             throw $e;
         }
         return false;
     }
     $xml = $xml->contents;
     if (!$plugin->name) {
         $this->outputStr("first time update, found name \"" . $xml->name . "\"...");
         if (Plugin::where('name', '=', $xml->name)->first()) {
             $this->outputStr(" already exists. skipping.");
             // this would be amazing to alert the administrators
             // of that. new Mailer; ?
             return false;
         }
         $firstTimeUpdate = true;
     } else {
         if ($plugin->name != $xml->name) {
             $this->outputStr(" requested name change to \"" . $xml->name . "\" ...");
             if (Plugin::where('name', '=', $xml->name)->first()) {
                 $this->outputStr(" but name already exists. skipping.");
                 // this would be amazing to alert the administrators
                 // of that. new Mailer; ?
                 return false;
             }
         }
         $firstTimeUpdate = false;
         $this->outputStr("\"" . $plugin->name . "\"");
     }
     $this->outputStr(" going to be synced with xml ...");
     $this->triggerPluginXmlStateChange($plugin, 'passing', true, in_array('alert_plugin_team_on_xml_state_change', $subtasks));
     // Updating basic infos
     $plugin->logo_url = $xml->logo;
     $plugin->name = $xml->name;
     $plugin->key = $xml->key;
     $plugin->homepage_url = $xml->homepage;
     $plugin->download_url = $xml->download;
     $plugin->issues_url = $xml->issues;
     $plugin->readme_url = $xml->readme;
     $plugin->license = $xml->license;
     // reading descriptions,
     // mapping type=>lang relation to lang=>type
     $descriptions = [];
     foreach ($xml->description->children() as $type => $descs) {
         if (in_array($type, ['short', 'long'])) {
             foreach ($descs->children() as $_lang => $content) {
                 $descriptions[$_lang][$type] = (string) $content;
             }
         }
     }
     // Delete current descriptions
     $plugin->descriptions()->delete();
     // Refreshing descriptions
     foreach ($descriptions as $lang => $_type) {
         $description = new PluginDescription();
         $description->lang = $lang;
         foreach ($_type as $type => $html) {
             $description[$type . '_description'] = $html;
         }
         $description->plugin_id = $plugin->id;
         $description->save();
     }
     // Refreshing authors
     $plugin->authors()->detach();
     $clean_authors = [];
     foreach ($xml->authors->children() as $author) {
         $_clean_authors = Author::fixKnownDuplicates((string) $author);
         foreach ($_clean_authors as $author) {
             $clean_authors[] = $author;
         }
     }
     foreach ($clean_authors as $_author) {
         $found = Author::where('name', '=', $_author)->first();
         if (sizeof($found) < 1) {
             $author = new Author();
             $author->name = $_author;
             $author->save();
         } else {
             $author = $found;
         }
         if (!$plugin->authors->find($author->id)) {
             $plugin->authors()->attach($author);
         }
     }
     // Refreshing versions
     $plugin->versions()->delete();
     foreach ($xml->versions->children() as $_version) {
         foreach ($_version->compatibility as $compat) {
             $version = new PluginVersion();
             $version->num = trim((string) $_version->num);
             $version->compatibility = trim((string) $compat);
             $version->plugin_id = $plugin->id;
             $version->save();
         }
     }
     // Refreshing screenshots
     if (isset($xml->screenshots)) {
         $plugin->screenshots()->delete();
         foreach ($xml->screenshots->children() as $url) {
             $screenshot = new PluginScreenshot();
             $screenshot->url = (string) $url;
             $screenshot->plugin_id = $plugin->id;
             $screenshot->save();
         }
     }
     // Reassociating plugin to tags
     $plugin->tags()->detach();
     foreach ($xml->tags->children() as $lang => $tags) {
         foreach ($tags->children() as $_tag) {
             $found = Tag::where('tag', '=', (string) $_tag)->where('lang', '=', $lang)->first();
             if (sizeof($found) < 1) {
                 $tag = new Tag();
                 $tag->tag = (string) $_tag;
                 $tag->lang = $lang;
                 $tag->key = Tool::getUrlSlug((string) $_tag);
                 $tag->save();
             } else {
                 $tag = $found;
             }
             $tag->plugins()->attach($plugin);
         }
     }
     // Reassociating plugin to langs
     $plugin->langs()->detach();
     foreach ($xml->langs->children() as $lang) {
         $lang = (string) $lang;
         $_lang = PluginLang::where('lang', '=', $lang)->first();
         if (!$_lang) {
             $_lang = new PluginLang();
             $_lang->lang = $lang;
             $_lang->save();
         }
         $_lang->plugins()->attach($plugin);
     }
     // new crc
     $plugin->xml_crc = $crc;
     // new updated timestamp
     $plugin->date_updated = \Illuminate\Database\Capsule\Manager::raw('NOW()');
     $plugin->save();
     $this->outputStr(" OK.");
     if (in_array('alert_watchers', $subtasks)) {
         $this->alertWatchers($plugin);
         $this->outputStr("\n");
     } else {
         $this->outputStr("\n");
     }
 }
Ejemplo n.º 7
0
    $all = Tool::paginateCollection(\API\Model\Author::mostActive()->contributorsOnly());
    Tool::endWithJson($all);
};
$top = function () use($app) {
    $top = \API\Model\Author::mostActive(10)->get();
    Tool::endWithJson($top);
};
$single = function ($id) use($app) {
    $single = \API\Model\Author::withPluginCount()->find($id);
    Tool::endWithJson($single);
};
$author_plugins = function ($id) use($app) {
    $author_plugins = \API\Model\Author::find($id);
    if (!$author_plugins) {
        return Tool::endWithJson(["error" => "Cannot find author"]);
    }
    Tool::endWithJson(Tool::paginateCollection(\API\Model\Plugin::with('versions', 'authors')->short()->withDownloads()->withAverageNote()->descWithLang(Tool::getRequestLang())->whereAuthor($author_plugins->id)));
};
// HTTP REST Map
$app->get('/author', $all);
$app->get('/author/top', $top);
$app->get('/author/:id', $single);
$app->get('/author/:id/plugin', $author_plugins);
$app->options('/author', function () {
});
$app->options('/author/top', function () {
});
$app->options('/author/:id', function ($id) {
});
$app->options('/author/:id/plugin', function ($id) {
});
Ejemplo n.º 8
0
<?php

/**
 * Search
 *
 * This REST module hooks on
 * following URLs
 *
 * /search
 */
use API\Core\Tool;
use Illuminate\Database\Capsule\Manager as DB;
// Minimal length of search string
$search_min_length = 2;
$search = function () use($app) {
    global $search_min_length, $allowed_languages;
    $body = Tool::getBody();
    if ($body == NULL || !isset($body->query_string) || strlen($body->query_string) < $search_min_length) {
        return Tool::endWithJson(["error" => "Your search string needs to " . "have at least " . $search_min_length . " chars"], 400);
    }
    $query_string = $body->query_string;
    $_search = Tool::paginateCollection(\API\Model\Plugin::short()->with('authors', 'versions', 'descriptions')->withDownloads()->withAverageNote()->descWithLang(Tool::getRequestLang())->where('name', 'LIKE', "%{$query_string}%")->orWhere('plugin_description.short_description', 'LIKE', "%{$query_string}%")->orWhere('plugin_description.long_description', 'LIKE', "%{$query_string}%"));
    Tool::endWithJson($_search);
};
$app->post('/search', $search);
$app->options('/search', function () {
});
Ejemplo n.º 9
0
 if (Plugin::where('xml_url', '=', $body->plugin_url)->count() > 0) {
     return Tool::endWithJson(["error" => "That plugin XML URL has already been submitted."]);
 }
 $xml = @file_get_contents($body->plugin_url);
 if (!$xml) {
     return Tool::endWithJson(["error" => "We cannot fetch that URL."]);
 }
 $xml = new ValidableXMLPluginDescription($xml);
 if (!$xml->isValid()) {
     return Tool::endWithJson(["error" => "Unreadable/Non validable XML.", "details" => $xml->errors]);
 }
 $xml = $xml->contents;
 if (Plugin::where('key', '=', $xml->key)->count() > 0) {
     return Tool::endWithJson(["error" => "Your XML describe a plugin whose key already exists in our database."]);
 }
 $plugin = new Plugin();
 $plugin->xml_url = $body->plugin_url;
 $plugin->date_added = DB::raw('NOW()');
 $plugin->active = false;
 $plugin->save();
 $msg_alerts_settings = Tool::getConfig()['msg_alerts'];
 $recipients = '';
 $i = 0;
 foreach ($msg_alerts_settings['recipients'] as $recipient) {
     if ($i > 0) {
         $recipients .= ', ';
     }
     $recipients .= $recipient;
     $i++;
 }
 mail($recipients, $msg_alerts_settings['subject_prefix'] . '[PLUGIN SUBMISSION] ' . $xml->name . ' (' . $xml->key . ')', 'A new plugin "' . $xml->name . '" with key "' . $xml->key . '" has been submitted and is awaiting to be verified. It has db id #' . $plugin->id, "From: GLPI Plugins <*****@*****.**>");
Ejemplo n.º 10
0
<?php

/**
 * Search
 *
 * This REST module hooks on
 * following URLs
 *
 * /search
 */
use API\Core\Tool;
use Illuminate\Database\Capsule\Manager as DB;
use API\OAuthServer\OAuthHelper;
// Minimal length of search string
$search_min_length = 2;
$search = Tool::makeEndpoint(function () use($app) {
    OAuthHelper::needsScopes(['plugins:search']);
    global $search_min_length, $allowed_languages;
    $body = Tool::getBody();
    if ($body == NULL || !isset($body->query_string) || strlen($body->query_string) < $search_min_length) {
        Tool::endWithJson(["error" => "Your search string needs to " . "have at least " . $search_min_length . " chars"], 400);
    }
    $query_string = $body->query_string;
    $_search = Tool::paginateCollection(\API\Model\Plugin::short()->with('authors', 'versions', 'descriptions')->withAverageNote()->descWithLang(Tool::getRequestLang())->where('active', '=', true)->where(function ($q) use($query_string) {
        return $q->where('name', 'LIKE', "%{$query_string}%")->orWhere('key', 'LIKE', "%{$query_string}%")->orWhere('plugin_description.short_description', 'LIKE', "%{$query_string}%")->orWhere('plugin_description.long_description', 'LIKE', "%{$query_string}%");
    })->orderBy('download_count', 'DESC')->orderBy('note', 'DESC')->orderBy('name', 'ASC'));
    Tool::endWithJson($_search);
});
$app->post('/search', $search);
$app->options('/search', function () {
});
Ejemplo n.º 11
0
    }
    // Quickly validating
    if (Plugin::where('xml_url', '=', $body->plugin_url)->count() > 0) {
        throw new UnavailableName('XML_URL', $body->plugin_url);
    }
    $xml = @file_get_contents($body->plugin_url);
    if (!$xml) {
        throw new InvalidXML('url', $body->plugin_url);
    }
    $xml = new ValidableXMLPluginDescription($xml);
    $xml->validate();
    $xml = $xml->contents;
    if (Plugin::where('key', '=', $xml->key)->count() > 0) {
        throw new UnavailableName('Plugin', $xml->key);
    }
    $plugin = new Plugin();
    $plugin->xml_url = $body->plugin_url;
    $plugin->date_added = DB::raw('NOW()');
    $plugin->active = false;
    $plugin->download_count = 0;
    $plugin->save();
    $plugin->permissions()->attach($user);
    $user = $plugin->permissions()->where('user_id', '=', $user->id)->first();
    $user->pivot['admin'] = true;
    $user->pivot->save();
    $mailer = new Mailer();
    $mailer->sendMail('plugin_submission.html', Tool::getConfig()['msg_alerts']['local_admins'], '[PLUGIN SUBMISSION] ' . $xml->name . ' (' . $xml->key . ')', ['plugin_xml' => (array) $xml]);
    Tool::endWithJson(["success" => true]);
});
// HTTP REST Map
$app->get('/plugin', $all);