Completed
Pull Request — master (#219)
by
unknown
04:51
created

BookmarkController   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 1 Features 1
Metric Value
wmc 36
c 4
b 1
f 1
lcom 1
cbo 2
dl 0
loc 260
ccs 0
cts 156
cp 0
rs 8.8

11 Methods

Rating   Name   Duplication   Size   Complexity  
A legacyGetBookmarks() 0 3 1
A __construct() 0 6 1
B getBookmarks() 0 27 4
C newBookmark() 0 40 8
A legacyEditBookmark() 0 7 2
B editBookmark() 0 20 5
A legacyDeleteBookmark() 0 3 1
A deleteBookmark() 0 11 3
A clickBookmark() 0 19 2
B importBookmark() 0 25 4
B exportBookmark() 0 28 5
1
<?php
2
3
/**
4
 * ownCloud - bookmarks
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Stefan Klemm <[email protected]>
10
 * @copyright Stefan Klemm 2014
11
 */
12
13
namespace OCA\Bookmarks\Controller\Rest;
14
15
use \OCP\IRequest;
16
use \OCP\AppFramework\ApiController;
17
use \OCP\AppFramework\Http\JSONResponse;
18
use \OCP\AppFramework\Http;
19
use \OCP\IDb;
20
use \OCA\Bookmarks\Controller\Lib\Bookmarks;
21
use \OCA\Bookmarks\Controller\Lib\ExportResponse;
22
23
class BookmarkController extends ApiController {
24
25
	private $userId;
26
	private $db;
27
28
	public function __construct($appName, IRequest $request, $userId, IDb $db) {
29
		parent::__construct($appName, $request);
30
		$this->userId = $userId;
31
		$this->db = $db;
32
		$this->request = $request;
33
	}
34
35
	/**
36
	 * @NoAdminRequired
37
	 */
38
	public function legacyGetBookmarks($type = "bookmark", $tag = '', $page = 0, $sort = "bookmarks_sorting_recent") {
39
		return $this->getBookmarks($type, $tag, $page, $sort);
40
	}
41
42
	/**
43
	 * @NoAdminRequired
44
	 */
45
	public function getBookmarks($type = "bookmark", $tag = '', $page = 0, $sort = "bookmarks_sorting_recent", $search = '') {
46
47
		if ($type == 'rel_tags') {
48
			$tags = Bookmarks::analyzeTagRequest($tag);
49
			$qtags = Bookmarks::findTags($this->userId, $this->db, $tags);
50
			return new JSONResponse(array('data' => $qtags, 'status' => 'success'));
51
		} else { // type == bookmark
52
			$filterTag = Bookmarks::analyzeTagRequest($tag);
53
54
			$offset = $page * 10;
55
56
			if ($sort == 'bookmarks_sorting_clicks') {
57
				$sqlSortColumn = 'clickcount';
58
			} else {
59
				$sqlSortColumn = 'lastmodified';
60
			}
61
62
            if($search == '') {
63
                $bookmarks = Bookmarks::findBookmarks(
0 ignored issues
show
Bug introduced by
The call to findBookmarks() misses a required argument $filterTagOnly.

This check looks for function calls that miss required arguments.

Loading history...
64
                        $this->userId, $this->db, $offset, $sqlSortColumn, $filterTag);
65
            } else {
66
                $bookmarks = Bookmarks::findBookmarks(
67
                        $this->userId, $this->db, $offset, $sqlSortColumn, $search, false);
68
            }
69
			return new JSONResponse(array('data' => $bookmarks, 'status' => 'success'));
70
		}
71
	}
72
73
	/**
74
	 * @NoAdminRequired
75
	 */
76
	public function newBookmark($url = "", $item = array(), $from_own = 0, $title = "", $is_public = false, $description = "") {
77
78
		if ($from_own == 0) {
79
			// allow only http(s) and (s)ftp
80
			$protocols = '/^(https?|s?ftp)\:\/\//i';
81
			if (preg_match($protocols, $url)) {
82
				$datas = Bookmarks::getURLMetadata($url);
83
			// if not (allowed) protocol is given, assume http and https (and fetch both)
84
			} else { 
85
				// append https to url and fetch it
86
				$url_https = 'https://' . $url;
87
				$datas_https = Bookmarks::getURLMetadata($url_https);
88
				// append http to url and fetch it
89
				$url_http = 'http://' . $url;
90
				$datas_http = Bookmarks::getURLMetadata($url_http);
91
			}
92
			
93
			if (isset($datas['title'])) { // prefer original url if working
94
				$title = $datas['title'];
95
				//url remains unchanged
96
			} elseif (isset($datas_https['title'])) { // test if https works
97
				$title = $datas_https['title'];
98
				$url = $url_https;
0 ignored issues
show
Bug introduced by
The variable $url_https does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
99
			} elseif (isset($datas_http['title'])) { // otherwise test http for results
100
				$title = $datas_http['title'];
101
				$url = $url_http;
0 ignored issues
show
Bug introduced by
The variable $url_http does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
102
			}
103
		}
104
105
		// Check if it is a valid URL (after adding http(s) prefix)
106
		if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
107
			return new JSONResponse(array('status' => 'error'), Http::STATUS_BAD_REQUEST);
108
		}
109
110
		$tags = isset($item['tags']) ? $item['tags'] : array();
111
112
		$id = Bookmarks::addBookmark($this->userId, $this->db, $url, $title, $tags, $description, $is_public);
113
		$bm = Bookmarks::findUniqueBookmark($id, $this->userId, $this->db);
114
		return new JSONResponse(array('item' => $bm, 'status' => 'success'));
115
	}
116
117
	/**
118
	  @NoAdminRequired
119
	 * 
120
	 * @param int $id
121
	 * @param bool $is_public Description
122
	 * @return \OCP\AppFramework\Http\TemplateResponse
123
	 */
124
	//TODO id vs record_id?
125
	public function legacyEditBookmark($id = null, $url = "", $item = array(), $title = "", $is_public = false, $record_id = null, $description = "") {
126
		if ($id == null) {
127
			return $this->newBookmark($url, $item, false, $title, $is_public, $description);
128
		} else {
129
			return $this->editBookmark($id, $url, $item, $title, $is_public, $record_id, $description);
130
		}
131
	}
132
133
	/**
134
	  @NoAdminRequired
135
	 * 
136
	 * @param int $id
137
	 * @param bool $is_public Description
138
	 * @return \OCP\AppFramework\Http\TemplateResponse
139
	 */
140
	public function editBookmark($id = null, $url = "", $item = array(), $title = "", $is_public = false, $record_id = null, $description = "") {
141
142
		// Check if it is a valid URL
143
		if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
144
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
145
		}
146
147
		if ($record_id == null) {
148
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
149
		}
150
151
		$tags = isset($item['tags']) ? $item['tags'] : array();
152
153
		if (is_numeric($record_id)) {
154
			$id = Bookmarks::editBookmark($this->userId, $this->db, $record_id, $url, $title, $tags, $description, $is_public = false);
155
		}
156
157
		$bm = Bookmarks::findUniqueBookmark($id, $this->userId, $this->db);
158
		return new JSONResponse(array('item' => $bm, 'status' => 'success'));
159
	}
160
161
	/**
162
	  @NoAdminRequired
163
	 * 
164
	 * @param int $id
165
	 * @param bool $is_public Description
0 ignored issues
show
Bug introduced by
There is no parameter named $is_public. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
166
	 * @return \OCP\AppFramework\Http\JSONResponse
167
	 */
168
	public function legacyDeleteBookmark($id = -1) {
169
		return $this->deleteBookmark($id);
170
	}
171
172
	/**
173
	  @NoAdminRequired
174
	 * 
175
	 * @param int $id
176
	 * @param bool $is_public Description
0 ignored issues
show
Bug introduced by
There is no parameter named $is_public. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
177
	 * @return \OCP\AppFramework\Http\JSONResponse
178
	 */
179
	public function deleteBookmark($id = -1) {
180
		if ($id == -1) {
181
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
182
		}
183
184
		if (!Bookmarks::deleteUrl($this->userId, $this->db, $id)) {
185
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
186
		} else {
187
			return new JSONResponse(array('status' => 'success'), Http::STATUS_OK);
188
		}
189
	}
190
191
	/**
192
	  @NoAdminRequired
193
	 * 
194
	 * @param string $url
195
	 * @return \OCP\AppFramework\Http\JSONResponse
196
	 */
197
	public function clickBookmark($url = "") {
198
199
		// Check if it is a valid URL
200
		if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
201
			return new JSONResponse(array(), Http::STATUS_BAD_REQUEST);
202
		}
203
204
		$query = $this->db->prepareQuery('
205
	UPDATE `*PREFIX*bookmarks`
206
	SET `clickcount` = `clickcount` + 1
207
	WHERE `user_id` = ?
208
		AND `url` LIKE ?
209
	');
210
211
		$params = array($this->userId, htmlspecialchars_decode($url));
212
		$query->execute($params);
213
214
		return new JSONResponse(array('status' => 'success'), Http::STATUS_OK);
215
	}
216
217
	/**
218
	  @NoAdminRequired
219
	 * 
220
	 * @return \OCP\AppFramework\Http\JSONResponse
221
	 */
222
	public function importBookmark() {
223
224
		$l = new \OC_l10n('bookmarks');
225
226
		$full_input = $this->request->getUploadedFile("bm_import");
227
228
		if (empty($full_input)) {
229
			\OCP\Util::writeLog('bookmarks', "No file provided for import", \OCP\Util::WARN);
230
			$error = array();
231
			$error[] = $l->t('No file provided for import');
232
		} else {
233
			$error = array();
234
			$file = $full_input['tmp_name'];
235
			if ($full_input['type'] == 'text/html') {
236
				$error = Bookmarks::importFile($this->userId, $this->db, $file);
237
				if (empty($error)) {
238
					return new JSONResponse(array('status' => 'success'));
239
				}
240
			} else {
241
				$error[] = $l->t('Unsupported file type for import');
242
			}
243
		}
244
245
		return new JSONResponse(array('status' => 'error', 'data' => $error));
246
	}
247
248
	/**
249
	  @NoAdminRequired
250
	 * 
251
	 * @return \OCP\AppFramework\Http\JSONResponse
252
	 */
253
	public function exportBookmark() {
254
255
		$file = <<<EOT
256
<!DOCTYPE NETSCAPE-Bookmark-file-1>
257
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
258
<!-- This is an automatically generated file.
259
It will be read and overwritten.
260
Do Not Edit! -->
261
<TITLE>Bookmarks</TITLE>
262
<H1>Bookmarks</H1>
263
<DL><p>
264
EOT;
265
		$bookmarks = Bookmarks::findBookmarks($this->userId, $this->db, 0, 'id', array(), true, -1);
266
		foreach ($bookmarks as $bm) {
267
			$title = $bm['title'];
268
			if (trim($title) === '') {
269
				$url_parts = parse_url($bm['url']);
270
				$title = isset($url_parts['host']) ? OCA\Bookmarks\Controller\Lib\Helper::getDomainWithoutExt($url_parts['host']) : $bm['url'];
271
			}
272
			$file .= '<DT><A HREF="' . \OC_Util::sanitizeHTML($bm['url']) . '" TAGS="' . implode(',', \OC_Util::sanitizeHTML($bm['tags'])) . '">';
273
			$file .= htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</A>';
274
			if ($bm['description'])
275
				$file .= '<DD>' . htmlspecialchars($bm['description'], ENT_QUOTES, 'UTF-8');
276
			$file .= "\n";
277
		}
278
279
		return new ExportResponse($file);
280
	}
281
282
}
283