4 use Shaarli\Api\Exceptions\ApiAuthorizationException
;
5 use Shaarli\Http\Base64Url
;
13 * Validates a JWT token authenticity.
15 * @param string $token JWT token extracted from the headers.
16 * @param string $secret API secret set in the settings.
18 * @return bool true on success
20 * @throws ApiAuthorizationException the token is not valid.
22 public static function validateJwtToken($token, $secret)
24 $parts = explode('.', $token);
25 if (count($parts) != 3 || strlen($parts[0]) == 0 || strlen($parts[1]) == 0) {
26 throw new ApiAuthorizationException('Malformed JWT token');
29 $genSign = Base64Url
::encode(hash_hmac('sha512', $parts[0] .'.'. $parts[1], $secret, true));
30 if ($parts[2] != $genSign) {
31 throw new ApiAuthorizationException('Invalid JWT signature');
34 $header = json_decode(Base64Url
::decode($parts[0]));
35 if ($header === null) {
36 throw new ApiAuthorizationException('Invalid JWT header');
39 $payload = json_decode(Base64Url
::decode($parts[1]));
40 if ($payload === null) {
41 throw new ApiAuthorizationException('Invalid JWT payload');
44 if (empty($payload->iat
)
45 || $payload->iat
> time()
46 || time() - $payload->iat
> ApiMiddleware
::$TOKEN_DURATION
48 throw new ApiAuthorizationException('Invalid JWT issued time');
55 * Format a Link for the REST API.
57 * @param array $link Link data read from the datastore.
58 * @param string $indexUrl Shaarli's index URL (used for relative URL).
60 * @return array Link data formatted for the REST API.
62 public static function formatLink($link, $indexUrl)
64 $out['id'] = $link['id'];
65 // Not an internal link
66 if (! is_note($link['url'])) {
67 $out['url'] = $link['url'];
69 $out['url'] = $indexUrl . $link['url'];
71 $out['shorturl'] = $link['shorturl'];
72 $out['title'] = $link['title'];
73 $out['description'] = $link['description'];
74 $out['tags'] = preg_split('/\s+/', $link['tags'], -1, PREG_SPLIT_NO_EMPTY
);
75 $out['private'] = $link['private'] == true;
76 $out['created'] = $link['created']->format(\DateTime
::ATOM
);
77 if (! empty($link['updated'])) {
78 $out['updated'] = $link['updated']->format(\DateTime
::ATOM
);
86 * Convert a link given through a request, to a valid link for LinkDB.
88 * If no URL is provided, it will generate a local note URL.
89 * If no title is provided, it will use the URL as title.
91 * @param array $input Request Link.
92 * @param bool $defaultPrivate Request Link.
94 * @return array Formatted link.
96 public static function buildLinkFromRequest($input, $defaultPrivate)
98 $input['url'] = ! empty($input['url']) ? cleanup_url($input['url']) : '';
99 if (isset($input['private'])) {
100 $private = filter_var($input['private'], FILTER_VALIDATE_BOOLEAN
);
102 $private = $defaultPrivate;
106 'title' => ! empty($input['title']) ? $input['title'] : $input['url'],
107 'url' => $input['url'],
108 'description' => ! empty($input['description']) ? $input['description'] : '',
109 'tags' => ! empty($input['tags']) ? implode(' ', $input['tags']) : '',
110 'private' => $private,
111 'created' => new \
DateTime(),
117 * Update link fields using an updated link object.
119 * @param array $oldLink data
120 * @param array $newLink data
122 * @return array $oldLink updated with $newLink values
124 public static function updateLink($oldLink, $newLink)
126 foreach (['title', 'url', 'description', 'tags', 'private'] as $field) {
127 $oldLink[$field] = $newLink[$field];
129 $oldLink['updated'] = new \
DateTime();
131 if (empty($oldLink['url'])) {
132 $oldLink['url'] = '?' . $oldLink['shorturl'];
135 if (empty($oldLink['title'])) {
136 $oldLink['title'] = $oldLink['url'];
143 * Format a Tag for the REST API.
145 * @param string $tag Tag name
146 * @param int $occurrences Number of links using this tag
148 * @return array Link data formatted for the REST API.
150 public static function formatTag($tag, $occurences)
154 'occurrences' => $occurences,