Commit 7e96aee5 authored by Adrien Dorsaz's avatar Adrien Dorsaz

Merge branch 'master' of adorsaz.ch:leed-market

parents 46453cbd 547e9813
leed-API
========
Plugin permettant de faire une API pour l'agrégateur [leed](https://github.com/ldleman/Leed).
Le but de cette API est de pouvoir suivre ses flux Leed via une application externe comme [LeedReader](http://www.barbogogo.fr/?page_id=4) pour Android.
Installation
============
Mettre le répertoire api dans le répertoire /plugins/ de l'agrégateur Leed.
Utilisation
===========
Pour plus de détails quant à l'utilisation de l'API, veuillez vous rendre sur la page du projet : [Leed-API](http://www.barbogogo.fr/?page_id=6).
<?php
/*
@name api
@author Barbogogo <barbogogo@barbogogo.fr>
@link http://www.barbogogo.fr/projets/applications-leed/leed-api/
@licence CC by nc sa <a href="http://creativecommons.org/licenses/by-nc-sa/2.0/fr/">http://creativecommons.org/licenses/by-nc-sa/2.0/fr/</a>
// @version 0.11
@description Le plugin API permet de gérer ses flux Leed via une application externe
*/
require_once('constantAPI.php');
function api_plugin_setting_link(&$myUser){
echo '<li><a class="toggle" href="#leedAPIBloc">'._t('P_LEEDAPI_TITLE').'</a></li>';
}
function api_plugin_setting_bloc(&$myUser)
{
echo '
<section id="leedAPIBloc" class="leedAPIBloc" style="display:none;">
<h2>'._t('P_LEEDAPI_TITLE').'</h2>
<section class="preferenceBloc">
<h3>'._t('P_LEEDAPI_SUBTITLE').'</h3>';
// La clé n'est affichée que si le plugin est activé
if(PLUGIN_ENABLED == 1)
{
echo '<p>'._t('P_LEEDAPI_DESCRIPTION_KEY').'</p>';
echo '<p>'._t('P_LEEDAPI_TEXT_KEY').' <b>'.KEY.'</b>.</p>';
}
echo '
</section>
</section>
';
}
$myUser = (isset($_SESSION['currentUser'])?unserialize($_SESSION['currentUser']):false);
if($myUser!=false)
{
Plugin::addHook('setting_post_link', 'api_plugin_setting_link');
Plugin::addHook('setting_post_section', 'api_plugin_setting_bloc');
}
?>
<?php
function auth_check($realm) {
$_SESSION = array();
session_unset();
session_destroy();
session_start();
if(isset($_REQUEST['login']) && $_REQUEST['login'] != "" ||
isset($_REQUEST['password']) && $_REQUEST['password'] != "")
{
$userMngr = new User();
$user = $userMngr->load(array('login'=>$_REQUEST['login']));
if(!$user) {
$GLOBALS["authError"] = "Utilisateur inconnu";
return false;
}
if(sha1(KEY) == $_REQUEST['password']) {
return $user;
}
else {
$GLOBALS["authError"] = "Echec de l'authentification";
return false;
}
}
else
{
if(isset($_SERVER['PHP_AUTH_DIGEST'])) {
$digest = $_SERVER['PHP_AUTH_DIGEST'];
} else if(isset($_SERVER['HTTP_AUTHENTICATION']) &&
strpos(strtolower($_SERVER['HTTP_AUTHENTICATION']), "digest") == 0) {
$digest = substr($_SERVER['HTTP_AUTHORIZATION'], 7);
}
if(!isset($digest)) {
$GLOBALS["authError"] = "Digest vide";
return false;
}
// check digest string
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1,'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('@('.$keys.')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $digest, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
// digest string is not valid
if(count($needed_parts) > 0) {
$GLOBALS["authError"] = "Digest invalide";
return false;
}
// user found ?
$userMngr = new User();
$user = $userMngr->load(array('login'=>$data['username']));
if(!$user) {
$GLOBALS["authError"] = "Utilisateur inconnu";
return false;
}
// check credentials
$A1 = md5($data['username'] . ':' . $realm . ':' . sha1(KEY));
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$resp = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if($data['response'] != $resp) {
$GLOBALS["authError"] = "Echec de l'authentification";
return false;
}
}
return $user;
}
function auth_request($realm) {
header("WWW-Authenticate: Digest realm=\"$realm\",qop=\"auth\",nonce=\"".uniqid()."\",opaque=\"".session_id()."\"");
header("HTTP/1.0 401 Unauthorized");
echo "{\"error\":{\"id\":\"2\",\"message\":\"<h1>login failed</h1><p>".$GLOBALS["authError"]."</p>\"}}\n";
$_SESSION = array();
session_unset();
session_destroy();
die();
}
?>
<?php
$rep = "../../";
session_start();
require_once($rep.'RainTPL.php');
require_once($rep.'i18n.php');
class_exists('Plugin') or require_once($rep.'Plugin.class.php');
class_exists('MysqlEntity') or require_once($rep.'MysqlEntity.class.php');
class_exists('Update') or require_once($rep.'Update.class.php');
$resultUpdate = Update::ExecutePatch();
class_exists('Feed') or require_once($rep.'Feed.class.php');
class_exists('Event') or require_once($rep.'Event.class.php');
class_exists('Functions') or require_once($rep.'Functions.class.php');
class_exists('User') or require_once($rep.'User.class.php');
class_exists('Folder') or require_once($rep.'Folder.class.php');
class_exists('Configuration') or require_once($rep.'Configuration.class.php');
$feedManager = new Feed();
$eventManager = new Event();
$folderManager = new Folder();
$configurationManager = new Configuration();
$conf = $configurationManager->getAll();
$userManager = new User();
$myUser = (isset($_SESSION['currentUser'])?unserialize($_SESSION['currentUser']):false);
?>
<?php
define('PLUGIN_ENABLED','0');
?>
\ No newline at end of file
<?php
$key = genererKeyAPI();
$constant = "<?php
define('PLUGIN_ENABLED','1');
define('KEY','".$key."');
?>";
file_put_contents(Plugin::path().'constantAPI.php', $constant);
function genererKeyAPI()
{
$j = 0;
$passwd = "";
while($j!=8)
{
$i=rand(48,122);
if($i>47 && $i<58 || $i>96 && $i<123 || $i>65 && $i<90)
{
$i = chr($i);
$passwd .= $i;
$j++;
}
}
return $passwd;
}
?>
\ No newline at end of file
<?php
/*
@nom: API
@auteur: Barbogogo
@description: Page de gestion des flux en json en vue d'une utilisation externe
*/
require_once('./commonAPI.php');
require_once('./constantAPI.php');
require_once('./phpError.php');
define('API_VERSION','0.9');
//Rcuperation des dossiers de flux par ordre de nom
$folders = $folderManager->populate('name');
//recuperation de tous les flux
$allFeeds = $feedManager->getFeedsPerFolder();
header('Cache-Control: no-cache, must-revalidate');
header('Expires:'.gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));
header('Content-type: application/json');
$jsonOutput = "";
if(PLUGIN_ENABLED == 1)
{
if($myUser != false)
{
if(isset($_REQUEST['option']) && $_REQUEST['option'] != "")
$option = $_REQUEST['option'];
else
$option = "";
$unreadOnly = FALSE;
switch($option)
{
case "article":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('id' => $_REQUEST['idArticle']));
$content = str_replace("%", "%25", $event[0]->getContent());
$jsonOutput = "{\"content\":".json_encode($content, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)."}\n";
// On met comme lu le event
$event[0]->change(array('unread'=>'0'),array('id'=>$event[0]->getId()));
break;
case "flux":
$target = "*";
$idFeed = $_REQUEST['feedId'];
$nbMaxArticle = $_REQUEST['nbMaxArticle'];
$connectionType = $_REQUEST['connectionType'];
if(isset($_REQUEST['offset']) && $_REQUEST['offset'] != "")
$limitSql = $_REQUEST['offset'].", ".$nbMaxArticle;
else
$limitSql = $nbMaxArticle;
$cOnLine = 0;
$cGetData = 1;
$cOffLine = 2;
$events = $eventManager->loadAllOnlyColumn($target,array('unread'=>1, 'feed'=>$idFeed),'pubDate DESC', $limitSql);
$tab = array();
$iTab = 0;
$feed = $feedManager->loadAllOnlyColumn($target,array('id'=>$idFeed),'', '');
foreach($events as $event)
{
$tab[$iTab] = array("id" => $event->getId(),
"title" => html_entity_decode($event->getTitle(), ENT_NOQUOTES, 'UTF-8'),
"date" => $event->getPubdate("d/m/Y h:i"),
"urlArticle" => $event->getLink(),
"author" => $event->getCreator(),
"favorite" => $event->getFavorite(),
"idFeed" => $event->getFeed());
$tab[$iTab]['nameFeed'] = $feed[0]->getName();
$tab[$iTab]['urlFeed'] = $feed[0]->getUrl();
if($connectionType == $cGetData)
$tab[$iTab]['content'] = $event->getContent();
else
$tab[$iTab]['content'] = "null";
$iTab ++;
}
if($iTab == 0)
{
$tab[$iTab] = array("id" => "0", "title" => "Pas d'article pour ce flux");
}
$jsonOutput = "{\"articles\":".json_encode($tab, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)."}\n";
break;
case "getUnread":
$target = "*";
$nbMaxArticle = $_REQUEST['nbMaxArticle'];
if(isset($_REQUEST['offset']) && $_REQUEST['offset'] != "")
$limitSql = $_REQUEST['offset'].", ".$nbMaxArticle;
else
$limitSql = $nbMaxArticle;
$events = $eventManager->loadAllOnlyColumn($target,array('unread'=>1),'pubDate DESC', $limitSql);
$tab = array();
$iTab = 0;
foreach($events as $event)
{
$feed = $feedManager->loadAllOnlyColumn($target,array('id'=>$event->getFeed()),'', '');
$tab[$iTab] = array("id" => $event->getId(),
"title" => html_entity_decode($event->getTitle(), ENT_NOQUOTES, 'UTF-8'),
"date" => $event->getPubdate("d/m/Y h:i"),
"urlArticle" => $event->getLink(),
"author" => $event->getCreator(),
"favorite" => $event->getFavorite(),
"idFeed" => $event->getFeed());
$tab[$iTab]['nameFeed'] = $feed[0]->getName();
$tab[$iTab]['urlFeed'] = $feed[0]->getUrl();
$tab[$iTab]['content'] = $event->getContent();
$iTab ++;
}
if($iTab == 0)
{
$tab[$iTab] = array("id" => "0", "title" => "Pas d'article non lus");
}
$jsonOutput = "{\"articles\":".json_encode($tab, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP)."}\n";
break;
case "setRead":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('id' => $_REQUEST['idArticle']));
// On met comme lu le event
$event[0]->change(array('unread'=>'0'),array('id'=>$event[0]->getId()));
break;
case "setUnRead":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('id' => $_REQUEST['idArticle']));
// On met comme non lu le event
$event[0]->change(array('unread'=>'1'),array('id'=>$event[0]->getId()));
break;
case "setFavorite":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('id' => $_REQUEST['idArticle']));
// On met comme favori
$event[0]->change(array('favorite'=>'1'),array('id'=>$event[0]->getId()));
break;
case "unsetFavorite":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('id' => $_REQUEST['idArticle']));
// On met comme non favori
$event[0]->change(array('favorite'=>'0'),array('id'=>$event[0]->getId()));
break;
case "getVersions":
$versions['API'] = API_VERSION;
$versions['Leed'] = VERSION_NUMBER." (".VERSION_NAME.")";
$jsonOutput = "{\"versions\":".json_encode($versions)."}\n";
break;
case "getUnreadFolders":
$unreadOnly = TRUE;
case "getFolders":
$tab = array();
$iTab = 0;
if (isset($_REQUEST['unreadOnly'])) $unreadOnly = $_REQUEST['unreadOnly'];
$nbNoRead = $feedManager->countUnreadEvents();
foreach($folders as $folder)
{
if(isset($allFeeds['folderMap'][$folder->getId()]))
{
$feeds = $allFeeds['folderMap'][$folder->getId()];
foreach($feeds as $title => $value)
{
$allFeeds['folderMap'][$folder->getId()][$title]['nbNoRead'] = 0;
if (isset($nbNoRead[$title]))
{
$allFeeds['folderMap'][$folder->getId()][$title]['nbNoRead'] = $nbNoRead[$title]*1;
}
else
{
if ($unreadOnly) unset($allFeeds['folderMap'][$folder->getId()][$title]);
}
}
$feeds2 = $allFeeds['folderMap'][$folder->getId()];
$tab[$iTab] = array("id" => $folder->getId(), "titre" => $folder->getName(), "flux" => $feeds2);
$iTab ++;
}
}
$jsonOutput = "{\"folders\":".json_encode($tab)."}\n";
break;
case "setFeedRead":
$target = "*";
$event = $eventManager->loadAllOnlyColumn($target,array('feed' => $_REQUEST['idFeed']));
for($i = 0 ; $i < sizeof($event) ; $i++)
{
$event[$i]->change(array('unread'=>'0'),array('id'=>$event[$i]->getId()));
}
break;
case "setAllRead":
$target = "*";
$event = $eventManager->loadAll(null);
for($i = 0 ; $i < sizeof($event) ; $i++)
{
$event[$i]->change(array('unread'=>'0'),array('id'=>$event[$i]->getId()));
}
break;
default:
// Error#0: no eror
$jsonOutput = "{\"error\":{\"id\":\"0\",\"message\":\"no error\"}}\n";
break;
}
}
else
{
// Error#2: login failed
$jsonOutput = "{\"error\":{\"id\":\"2\",\"message\":\"login failed\"}}\n";
}
}
else
{
// Error#1: plugin disable
$jsonOutput = "{\"error\":{\"id\":\"1\",\"message\":\"API disabled\"}}\n";
}
if($isErrorPHP == true)
{
echo $msgErrorPHP;
}
else
{
echo $jsonOutput;
}
?>
{
"P_LEEDAPI_TITLE":"Leed API Plugin",
"P_LEEDAPI_SUBTITLE":"Informations",
"P_LEEDAPI_DESCRIPTION_KEY":"In order to connect to the API, the following key shall be used in the application (LeedReader) as a password. The Leed password used to connect to the Leed account is not needed for the API. This key is generated automatically when you activate the API plugin. However, you can change it manually in the file leed/plugings/api/constantAPI.php (KEY field).",
"P_LEEDAPI_TEXT_KEY":"The key to connect to Leed through the API is:"
}
{
"P_LEEDAPI_TITLE":"Plugin Leed API",
"P_LEEDAPI_SUBTITLE":"Informations",
"P_LEEDAPI_DESCRIPTION_KEY":"Afin de vous connecter à l'API, la clé ci-dessous doit être renseignée dans l'application (LeedReader) en tant que mot de passe. Le mot de passe utiliser pour vous connecter à Leed ne fonctionne pas pour utiliser l'API. Cette clé est générée de façon aléatoire à chaque fois que vous activez le plugin API. Vous pouvez toutefois la modifier manuellement dans leed/plugings/api/constantAPI.php (variable KEY).",
"P_LEEDAPI_TEXT_KEY":"La clé vous permettant de vous connecter via l'API est :"
}
<?php
require_once('./commonAPI.php');
require_once('./constantAPI.php');
require_once('./auth.php');
require_once('./phpError.php');
$realm = $_SERVER['SERVER_NAME'];
$authError = "";
if(!$myUser && !($myUser = auth_check($realm)))
{
auth_request($realm);
}
else
{
header('Cache-Control: no-cache, must-revalidate');
header('Expires:'.gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));
header('Content-type: application/json');
$jsonOutput = "{\"error\":{\"id\":\"0\",\"message\":\"no error\"}}\n";
}
$_SESSION['currentUser'] = serialize($myUser);
if($isErrorPHP == true)
{
echo $msgErrorPHP;
$_SESSION = array();
session_unset();
session_destroy();
}
else
{
echo $jsonOutput;
}
?>
<?php
require_once('../../common.php');
require_once('./auth.php');
$_SESSION = array();
session_unset();
session_destroy();
// force to "unregister" on client side
auth_request($_SERVER['SERVER_NAME']);
?>
<?php
$isErrorPHP = false;
$msgErrorPHP = "";
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
$errortype = array(1=>"Erreur",
2=>"Alerte",
4=>"Erreur d'analyse",
8=>"Note",
16=>"Code Error",
32=>"Code Warning",
64=>"Zend Scripting Engine Error",
128=>"Zend Scripting Engine Warning",
256=>"Erreur spcifique",
512=>"Alerte spcifique",
1024=>"Note spcifique",
2048=>"Note inconnue"
);
$phpVersion = phpversion();
$jsonVersion = phpversion('json');
$mysqlVersion = phpversion('mysql');
$erreur = "<h1>PHP Error</h1>";
$erreur .= "<p>".$errortype[$errno]."[".$errno."]".$errmsg. "- ".$filename."(l.".$linenum.")</p>";
$erreur .= "<p>Your server configuration:</p>";
$erreur .= "<ul>";
$erreur .= "<li>PHP Version: ".$phpVersion."</li>";
$erreur .= "<li>JSON Version: ".$jsonVersion."</li>";
$erreur .= "<li>MySQL Version: ".$mysqlVersion."</li>";
$erreur .= "</ul>";
$GLOBALS["msgErrorPHP"] = "{\"error\":{\"id\":\"3\",\"message\":\"".$erreur."\"}}\n";
$GLOBALS["isErrorPHP"] = true;
}
unset($old_error_handler);
$old_error_handler = set_error_handler("userErrorHandler");
?>
\ No newline at end of file
<?php
$constant = "<?php
define('PLUGIN_ENABLED','0');
?>";