public function configFileIsAvailable() {
if (! self::$configFileAvailable) {
- $this->notInstalledMessage[] = 'You have to rename inc/poche/config.inc.php.new to inc/poche/config.inc.php.';
+ $this->notInstalledMessage[] = 'You have to copy (don\'t just rename!) inc/poche/config.inc.default.php to inc/poche/config.inc.php.';
return false;
}
$filter = new Twig_SimpleFilter('getReadingTime', 'Tools::getReadingTime');
$this->tpl->addFilter($filter);
}
+
+ public function createNewUser() {
+ if (isset($_GET['newuser'])){
+ if ($_POST['newusername'] != "" && $_POST['password4newuser'] != ""){
+ $newusername = filter_var($_POST['newusername'], FILTER_SANITIZE_STRING);
+ if (!$this->store->userExists($newusername)){
+ if ($this->store->install($newusername, Tools::encodeString($_POST['password4newuser'] . $newusername))) {
+ Tools::logm('The new user '.$newusername.' has been installed');
+ $this->messages->add('s', sprintf(_('The new user %s has been installed. Do you want to <a href="?logout">logout ?</a>'),$newusername));
+ Tools::redirect();
+ }
+ else {
+ Tools::logm('error during adding new user');
+ Tools::redirect();
+ }
+ }
+ else {
+ $this->messages->add('e', sprintf(_('Error : An user with the name %s already exists !'),$newusername));
+ Tools::logm('An user with the name '.$newusername.' already exists !');
+ Tools::redirect();
+ }
+ }
+ }
+ }
+
+ public function deleteUser(){
+ if (isset($_GET['deluser'])){
+ if ($this->store->listUsers() > 1) {
+ if (Tools::encodeString($_POST['password4deletinguser'].$this->user->getUsername()) == $this->store->getUserPassword($this->user->getId())) {
+ $username = $this->user->getUsername();
+ $this->store->deleteUserConfig($this->user->getId());
+ Tools::logm('The configuration for user '. $username .' has been deleted !');
+ $this->store->deleteTagsEntriesAndEntries($this->user->getId());
+ Tools::logm('The entries for user '. $username .' has been deleted !');
+ $this->store->deleteUser($this->user->getId());
+ Tools::logm('User '. $username .' has been completely deleted !');
+ Session::logout();
+ Tools::logm('logout');
+ Tools::redirect();
+ $this->messages->add('s', sprintf(_('User %s has been successfully deleted !'),$newusername));
+ }
+ else {
+ Tools::logm('Bad password !');
+ $this->messages->add('e', _('Error : The password is wrong !'));
+ }
+ }
+ else {
+ Tools::logm('Only user !');
+ $this->messages->add('e', _('Error : You are the only user, you cannot delete your account !'));
+ }
+ }
+ }
private function install()
{
switch ($action)
{
case 'add':
- if (!$import) {
- $content = Tools::getPageContent($url);
- $title = ($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled');
- $body = $content['rss']['channel']['item']['description'];
-
- // clean content from prevent xss attack
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.SerializerPath', CACHE);
- $purifier = new HTMLPurifier($config);
- $title = $purifier->purify($title);
- $body = $purifier->purify($body);
- }
- else {
- $title = '';
- $body = '';
- }
+ $content = Tools::getPageContent($url);
+ $title = ($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled');
+ $body = $content['rss']['channel']['item']['description'];
+
+ // clean content from prevent xss attack
+ $purifier = $this->getPurifier();
+ $title = $purifier->purify($title);
+ $body = $purifier->purify($body);
//search for possible duplicate
$duplicate = NULL;
- if (!$import) {
- $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId());
- }
+ $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId());
$last_id = $this->store->add($url->getUrl(), $title, $body, $this->user->getId());
- if ( $last_id && !$import ) {
+ if ( $last_id ) {
Tools::logm('add link ' . $url->getUrl());
if (DOWNLOAD_PICTURES) {
$content = filtre_picture($body, $url->getUrl(), $last_id);
$this->messages->add('s', _('the link has been added successfully'));
}
else {
- if (!$import) {
- $this->messages->add('e', _('error during insertion : the link wasn\'t added'));
- Tools::logm('error during insertion : the link wasn\'t added ' . $url->getUrl());
- }
+ $this->messages->add('e', _('error during insertion : the link wasn\'t added'));
+ Tools::logm('error during insertion : the link wasn\'t added ' . $url->getUrl());
}
- if (!$import) {
- if ($autoclose == TRUE) {
- Tools::redirect('?view=home');
- } else {
- Tools::redirect('?view=home&closewin=true');
- }
+ if ($autoclose == TRUE) {
+ Tools::redirect('?view=home');
+ } else {
+ Tools::redirect('?view=home&closewin=true');
}
break;
case 'delete':
case 'toggle_fav' :
$this->store->favoriteById($id, $this->user->getId());
Tools::logm('mark as favorite link #' . $id);
- if (!$import) {
- Tools::redirect();
+ if ( Tools::isAjaxRequest() ) {
+ echo 1;
+ exit;
+ }
+ else {
+ Tools::redirect();
}
break;
case 'toggle_archive' :
$this->store->archiveById($id, $this->user->getId());
Tools::logm('archive link #' . $id);
- if (!$import) {
- Tools::redirect();
+ if ( Tools::isAjaxRequest() ) {
+ echo 1;
+ exit;
+ }
+ else {
+ Tools::redirect();
}
break;
case 'archive_all' :
$this->store->archiveAll($this->user->getId());
Tools::logm('archive all links');
- if (!$import) {
- Tools::redirect();
- }
+ Tools::redirect();
break;
case 'add_tag' :
- if($import){
- $entry_id = $id;
- $tags = explode(',', $tags);
- }
- else{
- $tags = explode(',', $_POST['value']);
- $entry_id = $_POST['entry_id'];
- }
+ $tags = explode(',', $_POST['value']);
+ $entry_id = $_POST['entry_id'];
$entry = $this->store->retrieveOneById($entry_id, $this->user->getId());
if (!$entry) {
$this->messages->add('e', _('Article not found!'));
$this->store->setTagToEntry($tag_id, $entry_id);
}
}
- if(!$import) {
- Tools::redirect();
- }
+ Tools::redirect();
break;
case 'remove_tag' :
$tag_id = $_GET['tag_id'];
$languages = $this->getInstalledLanguages();
$token = $this->user->getConfigValue('token');
$http_auth = (isset($_SERVER['PHP_AUTH_USER']) || isset($_SERVER['REMOTE_USER'])) ? true : false;
+ $only_user = ($this->store->listUsers() > 1) ? false : true;
$tpl_vars = array(
'themes' => $themes,
'languages' => $languages,
'token' => $token,
'user_id' => $this->user->getId(),
'http_auth' => $http_auth,
+ 'only_user' => $only_user
);
Tools::logm('config view');
break;
Tools::redirect();
}
- /**
- * import from Instapaper. poche needs a ./instapaper-export.html file
- * @todo add the return value
- * @param string $targetFile the file used for importing
- * @return boolean
- */
- private function importFromInstapaper($targetFile)
- {
- # TODO gestion des articles favs
- $html = new simple_html_dom();
- $html->load_file($targetFile);
- Tools::logm('starting import from instapaper');
-
- $read = 0;
- $errors = array();
- foreach($html->find('ol') as $ul)
- {
- foreach($ul->find('li') as $li)
- {
- $a = $li->find('a');
- $url = new Url(base64_encode($a[0]->href));
- $this->action('add', $url, 0, TRUE);
- if ($read == '1') {
- $sequence = '';
- if (STORAGE == 'postgres') {
- $sequence = 'entries_id_seq';
- }
- $last_id = $this->store->getLastId($sequence);
- $this->action('toggle_archive', $url, $last_id, TRUE);
- }
- }
-
- # the second <ol> is for read links
- $read = 1;
- }
-
- $unlink = unlink($targetFile);
- $this->messages->add('s', _('import from instapaper completed. You have to execute the cron to fetch content.'));
- Tools::logm('import from instapaper completed');
- Tools::redirect();
- }
-
- /**
- * import from Pocket. poche needs a ./ril_export.html file
- * @todo add the return value
- * @param string $targetFile the file used for importing
- * @return boolean
- */
- private function importFromPocket($targetFile)
- {
- # TODO gestion des articles favs
- $html = new simple_html_dom();
- $html->load_file($targetFile);
- Tools::logm('starting import from pocket');
-
- $read = 0;
- $errors = array();
- foreach($html->find('ul') as $ul)
- {
- foreach($ul->find('li') as $li)
- {
- $a = $li->find('a');
- $url = new Url(base64_encode($a[0]->href));
- $this->action('add', $url, 0, TRUE);
- $sequence = '';
- if (STORAGE == 'postgres') {
- $sequence = 'entries_id_seq';
- }
- $last_id = $this->store->getLastId($sequence);
- if ($read == '1') {
- $this->action('toggle_archive', $url, $last_id, TRUE);
- }
- $tags = $a[0]->tags;
- if(!empty($tags)) {
- $this->action('add_tag',$url,$last_id,true,false,$tags);
- }
- }
-
- # the second <ul> is for read links
- $read = 1;
- }
-
- $unlink = unlink($targetFile);
- $this->messages->add('s', _('import from pocket completed. You have to execute the cron to fetch content.'));
- Tools::logm('import from pocket completed');
- Tools::redirect();
- }
-
- /**
- * import from Readability. poche needs a ./readability file
- * @todo add the return value
- * @param string $targetFile the file used for importing
- * @return boolean
- */
- private function importFromReadability($targetFile)
- {
- # TODO gestion des articles lus / favs
- $str_data = file_get_contents($targetFile);
- $data = json_decode($str_data,true);
- Tools::logm('starting import from Readability');
- $count = 0;
- foreach ($data as $key => $value) {
- $url = NULL;
- $favorite = FALSE;
- $archive = FALSE;
- foreach ($value as $item) {
- foreach ($item as $attr => $value) {
- if ($attr == 'article__url') {
- $url = new Url(base64_encode($value));
- }
- $sequence = '';
- if (STORAGE == 'postgres') {
- $sequence = 'entries_id_seq';
- }
- if ($value == 'true') {
- if ($attr == 'favorite') {
- $favorite = TRUE;
- }
- if ($attr == 'archive') {
- $archive = TRUE;
- }
- }
- }
-
- # we can add the url
- if (!is_null($url) && $url->isCorrect()) {
- $this->action('add', $url, 0, TRUE);
- $count++;
- if ($favorite) {
- $last_id = $this->store->getLastId($sequence);
- $this->action('toggle_fav', $url, $last_id, TRUE);
- }
- if ($archive) {
- $last_id = $this->store->getLastId($sequence);
- $this->action('toggle_archive', $url, $last_id, TRUE);
- }
- }
- }
- }
-
- unlink($targetFile);
- $this->messages->add('s', _('import from Readability completed. You have to execute the cron to fetch content.'));
- Tools::logm('import from Readability completed');
- Tools::redirect();
- }
-
- /**
- * import from Poche exported file
- * @param string $targetFile the file used for importing
- * @return boolean
- */
- private function importFromPoche($targetFile)
- {
- $str_data = file_get_contents($targetFile);
- $data = json_decode($str_data,true);
- Tools::logm('starting import from Poche');
-
-
- $sequence = '';
- if (STORAGE == 'postgres') {
- $sequence = 'entries_id_seq';
- }
-
- $count = 0;
- foreach ($data as $value) {
-
- $url = new Url(base64_encode($value['url']));
- $favorite = ($value['is_fav'] == -1);
- $archive = ($value['is_read'] == -1);
-
- # we can add the url
- if (!is_null($url) && $url->isCorrect()) {
-
- $this->action('add', $url, 0, TRUE);
-
- $count++;
- if ($favorite) {
- $last_id = $this->store->getLastId($sequence);
- $this->action('toggle_fav', $url, $last_id, TRUE);
- }
- if ($archive) {
- $last_id = $this->store->getLastId($sequence);
- $this->action('toggle_archive', $url, $last_id, TRUE);
- }
- }
-
- }
-
- unlink($targetFile);
- $this->messages->add('s', _('import from Poche completed. You have to execute the cron to fetch content.'));
- Tools::logm('import from Poche completed');
- Tools::redirect();
- }
-
/**
* import datas into your poche
* @return boolean
public function import() {
if ( isset($_FILES['file']) ) {
+ Tools::logm('Import stated: parsing file');
+
// assume, that file is in json format
$str_data = file_get_contents($_FILES['file']['tmp_name']);
$data = json_decode($str_data, true);
$read = 0;
foreach (array('ol','ul') as $list) {
foreach ($html->find($list) as $ul) {
- foreach ($ul->find('li') as $li) {
- $tmpEntry = array();
- $a = $li->find('a');
- $tmpEntry['url'] = $a[0]->href;
- $tmpEntry['tags'] = $a[0]->tags;
- $tmpEntry['is_read'] = $read;
- if ($tmpEntry['url']) {
- $data[] = $tmpEntry;
- }
- }
- # the second <ol/ul> is for read links
- $read = ((sizeof($data) && $read)?0:1);
+ foreach ($ul->find('li') as $li) {
+ $tmpEntry = array();
+ $a = $li->find('a');
+ $tmpEntry['url'] = $a[0]->href;
+ $tmpEntry['tags'] = $a[0]->tags;
+ $tmpEntry['is_read'] = $read;
+ if ($tmpEntry['url']) {
+ $data[] = $tmpEntry;
+ }
+ }
+ # the second <ol/ul> is for read links
+ $read = ((sizeof($data) && $read)?0:1);
+ }
+ }
+ }
+
+ //for readability structure
+ foreach ($data as $record) {
+ if (is_array($record)) {
+ $data[] = $record;
+ foreach ($record as $record2) {
+ if (is_array($record2)) {
+ $data[] = $record2;
+ }
}
}
}
- $i = 0; //counter for articles inserted
+ $urlsInserted = array(); //urls of articles inserted
foreach ($data as $record) {
- //echo '<pre>';
- //var_dump($record);
- // foreach ($record as $key=>$val) {
- // echo "\n=================\n$i: $key: $val\n";
- // }
- // exit;
-
- $url = trim($record['url']);
- if ( $url ) {
+ $url = trim( isset($record['article__url']) ? $record['article__url'] : (isset($record['url']) ? $record['url'] : '') );
+ if ( $url and !in_array($url, $urlsInserted) ) {
$title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>');
$body = (isset($record['content']) ? $record['content'] : '');
- $isRead = (isset($record['is_read']) ? intval($record['is_read']) : 0);
- $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : 0);
+ $isRead = (isset($record['is_read']) ? intval($record['is_read']) : (isset($record['archive'])?intval($record['archive']):0));
+ $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : (isset($record['favorite'])?intval($record['favorite']):0) );
//insert new record
$id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead);
if ( $id ) {
- //increment no of records inserted
- $i++;
+ $urlsInserted[] = $url; //add
+
if ( isset($record['tags']) && trim($record['tags']) ) {
- //@TODO: set tags
+ //@TODO: set tags
}
}
}
}
+ $i = sizeof($urlsInserted);
if ( $i > 0 ) {
$this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".'));
}
+ Tools::logm('Import of articles finished: '.$i.' articles added (w/o content if not provided).');
}
//file parsing finished here
if ( $recordsDownloadRequired == 0 ) {
//nothing to download
$this->messages->add('s', _('Import finished.'));
+ Tools::logm('Import finished completely');
Tools::redirect();
}
else {
//if just inserted - don't download anything, download will start in next reload
if ( !isset($_FILES['file']) ) {
//download next batch
+ Tools::logm('Fetching next batch of articles...');
$items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.SerializerPath', CACHE);
- $purifier = new HTMLPurifier($config);
+ $purifier = $this->getPurifier();
foreach ($items as $item) {
- $url = new Url(base64_encode($item['url']));
- $content = Tools::getPageContent($url);
+ $url = new Url(base64_encode($item['url']));
+ Tools::logm('Fetching article '.$item['id']);
+ $content = Tools::getPageContent($url);
- $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
- $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
+ $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
+ $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
- //clean content to prevent xss attack
- $title = $purifier->purify($title);
- $body = $purifier->purify($body);
+ //clean content to prevent xss attack
+ $title = $purifier->purify($title);
+ $body = $purifier->purify($body);
- $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
+ $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
+ Tools::logm('Article '.$item['id'].' updated.');
}
}
return array('includeImport'=>true, 'import'=>array('recordsDownloadRequired'=>$recordsDownloadRequired, 'recordsUnderDownload'=> IMPORT_LIMIT, 'delay'=> IMPORT_DELAY * 1000) );
}
- public function uploadFile() {
- if (isset($_FILES['file']))
- {
- $dir = CACHE . '/';
- $file = basename($_FILES['file']['name']);
- if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) {
- $this->messages->add('s', _('File uploaded. You can now execute import.'));
- }
- else {
- $this->messages->add('e', _('Error while importing file. Do you have access to upload it?'));
- }
- }
-
- Tools::redirect('?view=config');
- }
-
/**
* export poche entries in json
* @return json all poche entries
*/
- public function export()
- {
- $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
- header('Content-Disposition: attachment; filename='.$filename);
-
- $entries = $this->store->retrieveAll($this->user->getId());
- echo $this->tpl->render('export.twig', array(
- 'export' => Tools::renderJson($entries),
- ));
- Tools::logm('export view');
+ public function export() {
+ $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
+ header('Content-Disposition: attachment; filename='.$filename);
+
+ $entries = $this->store->retrieveAll($this->user->getId());
+ echo $this->tpl->render('export.twig', array(
+ 'export' => Tools::renderJson($entries),
+ ));
+ Tools::logm('export view');
}
/**
* @param string $which 'prod' or 'dev'
* @return string latest $which version
*/
- private function getPocheVersion($which = 'prod')
- {
- $cache_file = CACHE . '/' . $which;
- $check_time = time();
-
- # checks if the cached version file exists
- if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 86400 ))) {
- $version = file_get_contents($cache_file);
- $check_time = filemtime($cache_file);
- } else {
- $version = file_get_contents('http://static.wallabag.org/versions/' . $which);
- file_put_contents($cache_file, $version, LOCK_EX);
- }
- return array($version, $check_time);
+ private function getPocheVersion($which = 'prod') {
+ $cache_file = CACHE . '/' . $which;
+ $check_time = time();
+
+ # checks if the cached version file exists
+ if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 86400 ))) {
+ $version = file_get_contents($cache_file);
+ $check_time = filemtime($cache_file);
+ } else {
+ $version = file_get_contents('http://static.wallabag.org/versions/' . $which);
+ file_put_contents($cache_file, $version, LOCK_EX);
+ }
+ return array($version, $check_time);
}
public function generateToken()
{
- if (ini_get('open_basedir') === '') {
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- echo 'This is a server using Windows!';
- // alternative to /dev/urandom for Windows
- $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
- } else {
- $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
- }
- }
- else {
- $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ if (ini_get('open_basedir') === '') {
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ echo 'This is a server using Windows!';
+ // alternative to /dev/urandom for Windows
+ $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ } else {
+ $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
}
+ }
+ else {
+ $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ }
- $token = str_replace('+', '', $token);
- $this->store->updateUserConfig($this->user->getId(), 'token', $token);
- $currentConfig = $_SESSION['poche_user']->config;
- $currentConfig['token'] = $token;
- $_SESSION['poche_user']->setConfig($currentConfig);
- Tools::redirect();
+ $token = str_replace('+', '', $token);
+ $this->store->updateUserConfig($this->user->getId(), 'token', $token);
+ $currentConfig = $_SESSION['poche_user']->config;
+ $currentConfig['token'] = $token;
+ $_SESSION['poche_user']->setConfig($currentConfig);
+ Tools::redirect();
}
public function generateFeeds($token, $user_id, $tag_id, $type = 'home')
foreach ($entries as $entry) {
$newItem = $feed->createNewItem();
$newItem->setTitle($entry['title']);
+ $newItem->setSource(Tools::getPocheUrl() . '?view=view&id=' . $entry['id']);
$newItem->setLink($entry['url']);
$newItem->setDate(time());
$newItem->setDescription($entry['content']);
$this->messages->add('s', _('Cache deleted.'));
Tools::redirect();
}
+
+ /**
+ * return new purifier object with actual config
+ */
+ protected function getPurifier() {
+ $config = HTMLPurifier_Config::createDefault();\r
+ $config->set('Cache.SerializerPath', CACHE);\r
+ $config->set('HTML.SafeIframe', true);\r
+ $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%'); //allow YouTube and Vimeo$purifier = new HTMLPurifier($config);
+\r
+ return new HTMLPurifier($config);
+ }
}