Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1854 lines
56 KiB

6 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. <?php
  2. require_once('include/Photo.php');
  3. require_once('include/items.php');
  4. require_once('include/acl_selectors.php');
  5. require_once('include/bbcode.php');
  6. require_once('include/security.php');
  7. require_once('include/redir.php');
  8. require_once('include/tags.php');
  9. require_once('include/threads.php');
  10. function photos_init(&$a) {
  11. if($a->argc > 1)
  12. auto_redir($a, $a->argv[1]);
  13. if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
  14. return;
  15. }
  16. $o = '';
  17. if($a->argc > 1) {
  18. $nick = $a->argv[1];
  19. $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `blocked` = 0 LIMIT 1",
  20. dbesc($nick)
  21. );
  22. if(! count($r))
  23. return;
  24. $a->data['user'] = $r[0];
  25. $a->profile_uid = $r[0]['uid'];
  26. $is_owner = (local_user() && (local_user() == $a->profile_uid));
  27. $profilephoto = $a->get_cached_avatar_image($a->get_baseurl() . '/photo/profile/' . $a->data['user']['uid'] . '.jpg');
  28. $tpl = get_markup_template("vcard-widget.tpl");
  29. $vcard_widget .= replace_macros($tpl, array(
  30. '$name' => $a->data['user']['username'],
  31. '$photo' => $profilephoto
  32. ));
  33. $sql_extra = permissions_sql($a->data['user']['uid']);
  34. $albums = q("SELECT count(distinct `resource-id`) AS `total`, `album` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s'
  35. $sql_extra group by album order by created desc",
  36. intval($a->data['user']['uid']),
  37. dbesc('Contact Photos'),
  38. dbesc( t('Contact Photos'))
  39. );
  40. $albums_visible = ((intval($a->data['user']['hidewall']) && (! local_user()) && (! remote_user())) ? false : true);
  41. // add various encodings to the array so we can just loop through and pick them out in a template
  42. $ret = array('success' => false);
  43. if($albums) {
  44. $a->data['albums'] = $albums;
  45. if ($albums_visible)
  46. $ret['success'] = true;
  47. $ret['albums'] = array();
  48. foreach($albums as $k => $album) {
  49. //hide profile photos to others
  50. if((! $is_owner) && (! remote_user()) && ($album['album'] == t('Profile Photos')))
  51. continue;
  52. $entry = array(
  53. 'text' => $album['album'],
  54. 'total' => $album['total'],
  55. 'url' => z_root() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album['album']),
  56. 'urlencode' => urlencode($album['album']),
  57. 'bin2hex' => bin2hex($album['album'])
  58. );
  59. $ret['albums'][] = $entry;
  60. }
  61. }
  62. $albums = $ret;
  63. if(local_user() && $a->data['user']['uid'] == local_user())
  64. $can_post = true;
  65. if($albums['success']) {
  66. $photo_albums_widget = replace_macros(get_markup_template('photo_albums.tpl'),array(
  67. '$nick' => $a->data['user']['nickname'],
  68. '$title' => t('Photo Albums'),
  69. 'recent' => t('Recent Photos'),
  70. '$albums' => $albums['albums'],
  71. '$baseurl' => z_root(),
  72. '$upload' => array( t('Upload New Photos'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/upload'),
  73. '$can_post' => $can_post
  74. ));
  75. }
  76. if(! x($a->page,'aside'))
  77. $a->page['aside'] = '';
  78. $a->page['aside'] .= $vcard_widget;
  79. $a->page['aside'] .= $photo_albums_widget;
  80. $tpl = get_markup_template("photos_head.tpl");
  81. $a->page['htmlhead'] .= replace_macros($tpl,array(
  82. '$ispublic' => t('everybody')
  83. ));
  84. }
  85. return;
  86. }
  87. function photos_post(&$a) {
  88. logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
  89. logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA);
  90. logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA);
  91. $phototypes = Photo::supportedTypes();
  92. $can_post = false;
  93. $visitor = 0;
  94. $page_owner_uid = $a->data['user']['uid'];
  95. $community_page = (($a->data['user']['page-flags'] == PAGE_COMMUNITY) ? true : false);
  96. if((local_user()) && (local_user() == $page_owner_uid))
  97. $can_post = true;
  98. else {
  99. if($community_page && remote_user()) {
  100. $cid = 0;
  101. if(is_array($_SESSION['remote'])) {
  102. foreach($_SESSION['remote'] as $v) {
  103. if($v['uid'] == $page_owner_uid) {
  104. $cid = $v['cid'];
  105. break;
  106. }
  107. }
  108. }
  109. if($cid) {
  110. $r = q("SELECT `uid` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
  111. intval($cid),
  112. intval($page_owner_uid)
  113. );
  114. if(count($r)) {
  115. $can_post = true;
  116. $visitor = $cid;
  117. }
  118. }
  119. }
  120. }
  121. if(! $can_post) {
  122. notice( t('Permission denied.') . EOL );
  123. killme();
  124. }
  125. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  126. WHERE `user`.`uid` = %d AND `self` = 1 LIMIT 1",
  127. intval($page_owner_uid)
  128. );
  129. if(! count($r)) {
  130. notice( t('Contact information unavailable') . EOL);
  131. logger('photos_post: unable to locate contact record for page owner. uid=' . $page_owner_uid);
  132. killme();
  133. }
  134. $owner_record = $r[0];
  135. if(($a->argc > 3) && ($a->argv[2] === 'album')) {
  136. $album = hex2bin($a->argv[3]);
  137. if($album === t('Profile Photos') || $album === 'Contact Photos' || $album === t('Contact Photos')) {
  138. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  139. return; // NOTREACHED
  140. }
  141. $r = q("SELECT count(*) FROM `photo` WHERE `album` = '%s' AND `uid` = %d",
  142. dbesc($album),
  143. intval($page_owner_uid)
  144. );
  145. if(! count($r)) {
  146. notice( t('Album not found.') . EOL);
  147. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  148. return; // NOTREACHED
  149. }
  150. // Check if the user has responded to a delete confirmation query
  151. if($_REQUEST['canceled']) {
  152. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  153. }
  154. $newalbum = notags(trim($_POST['albumname']));
  155. if($newalbum != $album) {
  156. q("UPDATE `photo` SET `album` = '%s' WHERE `album` = '%s' AND `uid` = %d",
  157. dbesc($newalbum),
  158. dbesc($album),
  159. intval($page_owner_uid)
  160. );
  161. $newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
  162. goaway($a->get_baseurl() . '/' . $newurl);
  163. return; // NOTREACHED
  164. }
  165. if($_POST['dropalbum'] == t('Delete Album')) {
  166. // Check if we should do HTML-based delete confirmation
  167. if($_REQUEST['confirm']) {
  168. $drop_url = $a->query_string;
  169. $extra_inputs = array(
  170. array('name' => 'albumname', 'value' => $_POST['albumname']),
  171. );
  172. $a->page['content'] = replace_macros(get_markup_template('confirm.tpl'), array(
  173. '$method' => 'post',
  174. '$message' => t('Do you really want to delete this photo album and all its photos?'),
  175. '$extra_inputs' => $extra_inputs,
  176. '$confirm' => t('Delete Album'),
  177. '$confirm_url' => $drop_url,
  178. '$confirm_name' => 'dropalbum', // Needed so that confirmation will bring us back into this if statement
  179. '$cancel' => t('Cancel'),
  180. ));
  181. $a->error = 1; // Set $a->error so the other module functions don't execute
  182. return;
  183. }
  184. $res = array();
  185. // get the list of photos we are about to delete
  186. if($visitor) {
  187. $r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d AND `album` = '%s'",
  188. intval($visitor),
  189. intval($page_owner_uid),
  190. dbesc($album)
  191. );
  192. }
  193. else {
  194. $r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
  195. intval(local_user()),
  196. dbesc($album)
  197. );
  198. }
  199. if(count($r)) {
  200. foreach($r as $rr) {
  201. $res[] = "'" . dbesc($rr['rid']) . "'" ;
  202. }
  203. }
  204. else {
  205. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  206. return; // NOTREACHED
  207. }
  208. $str_res = implode(',', $res);
  209. // remove the associated photos
  210. q("DELETE FROM `photo` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d",
  211. intval($page_owner_uid)
  212. );
  213. // find and delete the corresponding item with all the comments and likes/dislikes
  214. $r = q("SELECT `parent-uri` FROM `item` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d",
  215. intval($page_owner_uid)
  216. );
  217. if(count($r)) {
  218. foreach($r as $rr) {
  219. q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
  220. dbesc(datetime_convert()),
  221. dbesc($rr['parent-uri']),
  222. intval($page_owner_uid)
  223. );
  224. create_tags_from_itemuri($rr['parent-uri'], $page_owner_uid);
  225. delete_thread_uri($rr['parent-uri'], $page_owner_uid);
  226. $drop_id = intval($rr['id']);
  227. // send the notification upstream/downstream as the case may be
  228. if($rr['visible'])
  229. proc_run('php',"include/notifier.php","drop","$drop_id");
  230. }
  231. }
  232. }
  233. goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']);
  234. return; // NOTREACHED
  235. }
  236. // Check if the user has responded to a delete confirmation query for a single photo
  237. if(($a->argc > 2) && $_REQUEST['canceled']) {
  238. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  239. }
  240. if(($a->argc > 2) && (x($_POST,'delete')) && ($_POST['delete'] == t('Delete Photo'))) {
  241. // same as above but remove single photo
  242. // Check if we should do HTML-based delete confirmation
  243. if($_REQUEST['confirm']) {
  244. $drop_url = $a->query_string;
  245. $a->page['content'] = replace_macros(get_markup_template('confirm.tpl'), array(
  246. '$method' => 'post',
  247. '$message' => t('Do you really want to delete this photo?'),
  248. '$extra_inputs' => array(),
  249. '$confirm' => t('Delete Photo'),
  250. '$confirm_url' => $drop_url,
  251. '$confirm_name' => 'delete', // Needed so that confirmation will bring us back into this if statement
  252. '$cancel' => t('Cancel'),
  253. ));
  254. $a->error = 1; // Set $a->error so the other module functions don't execute
  255. return;
  256. }
  257. if($visitor) {
  258. $r = q("SELECT `id`, `resource-id` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d AND `resource-id` = '%s' LIMIT 1",
  259. intval($visitor),
  260. intval($page_owner_uid),
  261. dbesc($a->argv[2])
  262. );
  263. }
  264. else {
  265. $r = q("SELECT `id`, `resource-id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' LIMIT 1",
  266. intval(local_user()),
  267. dbesc($a->argv[2])
  268. );
  269. }
  270. if(count($r)) {
  271. q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
  272. intval($page_owner_uid),
  273. dbesc($r[0]['resource-id'])
  274. );
  275. $i = q("SELECT * FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1",
  276. dbesc($r[0]['resource-id']),
  277. intval($page_owner_uid)
  278. );
  279. if(count($i)) {
  280. q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
  281. dbesc(datetime_convert()),
  282. dbesc(datetime_convert()),
  283. dbesc($i[0]['uri']),
  284. intval($page_owner_uid)
  285. );
  286. create_tags_from_itemuri($i[0]['uri'], $page_owner_uid);
  287. delete_thread_uri($i[0]['uri'], $page_owner_uid);
  288. $url = $a->get_baseurl();
  289. $drop_id = intval($i[0]['id']);
  290. if($i[0]['visible'])
  291. proc_run('php',"include/notifier.php","drop","$drop_id");
  292. }
  293. }
  294. goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']);
  295. return; // NOTREACHED
  296. }
  297. if(($a->argc > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false)) || (x($_POST,'albname') !== false)) {
  298. $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
  299. $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : '');
  300. $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0);
  301. $albname = ((x($_POST,'albname')) ? notags(trim($_POST['albname'])) : '');
  302. $str_group_allow = perms2str($_POST['group_allow']);
  303. $str_contact_allow = perms2str($_POST['contact_allow']);
  304. $str_group_deny = perms2str($_POST['group_deny']);
  305. $str_contact_deny = perms2str($_POST['contact_deny']);
  306. $resource_id = $a->argv[2];
  307. if(! strlen($albname))
  308. $albname = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
  309. if((x($_POST,'rotate') !== false) &&
  310. ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) {
  311. logger('rotate');
  312. $r = q("select * from photo where `resource-id` = '%s' and uid = %d and scale = 0 limit 1",
  313. dbesc($resource_id),
  314. intval($page_owner_uid)
  315. );
  316. if(count($r)) {
  317. $ph = new Photo($r[0]['data'], $r[0]['type']);
  318. if($ph->is_valid()) {
  319. $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
  320. $ph->rotate($rotate_deg);
  321. $width = $ph->getWidth();
  322. $height = $ph->getHeight();
  323. $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 0",
  324. dbesc($ph->imageString()),
  325. intval($height),
  326. intval($width),
  327. dbesc($resource_id),
  328. intval($page_owner_uid)
  329. );
  330. if($width > 640 || $height > 640) {
  331. $ph->scaleImage(640);
  332. $width = $ph->getWidth();
  333. $height = $ph->getHeight();
  334. $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 1",
  335. dbesc($ph->imageString()),
  336. intval($height),
  337. intval($width),
  338. dbesc($resource_id),
  339. intval($page_owner_uid)
  340. );
  341. }
  342. if($width > 320 || $height > 320) {
  343. $ph->scaleImage(320);
  344. $width = $ph->getWidth();
  345. $height = $ph->getHeight();
  346. $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 2",
  347. dbesc($ph->imageString()),
  348. intval($height),
  349. intval($width),
  350. dbesc($resource_id),
  351. intval($page_owner_uid)
  352. );
  353. }
  354. }
  355. }
  356. }
  357. $p = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ORDER BY `scale` DESC",
  358. dbesc($resource_id),
  359. intval($page_owner_uid)
  360. );
  361. if(count($p)) {
  362. $ext = $phototypes[$p[0]['type']];
  363. $r = q("UPDATE `photo` SET `desc` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d",
  364. dbesc($desc),
  365. dbesc($albname),
  366. dbesc($str_contact_allow),
  367. dbesc($str_group_allow),
  368. dbesc($str_contact_deny),
  369. dbesc($str_group_deny),
  370. dbesc($resource_id),
  371. intval($page_owner_uid)
  372. );
  373. }
  374. /* Don't make the item visible if the only change was the album name */
  375. $visibility = 0;
  376. if($p[0]['desc'] !== $desc || strlen($rawtags))
  377. $visibility = 1;
  378. if(! $item_id) {
  379. // Create item container
  380. $title = '';
  381. $uri = item_new_uri($a->get_hostname(),$page_owner_uid);
  382. $arr = array();
  383. $arr['uid'] = $page_owner_uid;
  384. $arr['uri'] = $uri;
  385. $arr['parent-uri'] = $uri;
  386. $arr['type'] = 'photo';
  387. $arr['wall'] = 1;
  388. $arr['resource-id'] = $p[0]['resource-id'];
  389. $arr['contact-id'] = $owner_record['id'];
  390. $arr['owner-name'] = $owner_record['name'];
  391. $arr['owner-link'] = $owner_record['url'];
  392. $arr['owner-avatar'] = $owner_record['thumb'];
  393. $arr['author-name'] = $owner_record['name'];
  394. $arr['author-link'] = $owner_record['url'];
  395. $arr['author-avatar'] = $owner_record['thumb'];
  396. $arr['title'] = $title;
  397. $arr['allow_cid'] = $p[0]['allow_cid'];
  398. $arr['allow_gid'] = $p[0]['allow_gid'];
  399. $arr['deny_cid'] = $p[0]['deny_cid'];
  400. $arr['deny_gid'] = $p[0]['deny_gid'];
  401. $arr['last-child'] = 1;
  402. $arr['visible'] = $visibility;
  403. $arr['origin'] = 1;
  404. $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $p[0]['resource-id'] . ']'
  405. . '[img]' . $a->get_baseurl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.'. $ext . '[/img]'
  406. . '[/url]';
  407. $item_id = item_store($arr);
  408. }
  409. if($item_id) {
  410. $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  411. intval($item_id),
  412. intval($page_owner_uid)
  413. );
  414. }
  415. if(count($r)) {
  416. $old_tag = $r[0]['tag'];
  417. $old_inform = $r[0]['inform'];
  418. }
  419. if(strlen($rawtags)) {
  420. $str_tags = '';
  421. $inform = '';
  422. // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a hashtag
  423. $x = substr($rawtags,0,1);
  424. if($x !== '@' && $x !== '#')
  425. $rawtags = '#' . $rawtags;
  426. $taginfo = array();
  427. $tags = get_tags($rawtags);
  428. if(count($tags)) {
  429. foreach($tags as $tag) {
  430. if(isset($profile))
  431. unset($profile);
  432. if(strpos($tag,'@') === 0) {
  433. $name = substr($tag,1);
  434. if((strpos($name,'@')) || (strpos($name,'http://'))) {
  435. $newname = $name;
  436. $links = @lrdd($name);
  437. if(count($links)) {
  438. foreach($links as $link) {
  439. if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
  440. $profile = $link['@attributes']['href'];
  441. if($link['@attributes']['rel'] === 'salmon') {
  442. $salmon = '$url:' . str_replace(',','%sc',$link['@attributes']['href']);
  443. if(strlen($inform))
  444. $inform .= ',';
  445. $inform .= $salmon;
  446. }
  447. }
  448. }
  449. $taginfo[] = array($newname,$profile,$salmon);
  450. }
  451. else {
  452. $newname = $name;
  453. $alias = '';
  454. $tagcid = 0;
  455. if(strrpos($newname,'+'))
  456. $tagcid = intval(substr($newname,strrpos($newname,'+') + 1));
  457. if($tagcid) {
  458. $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  459. intval($tagcid),
  460. intval($profile_uid)
  461. );
  462. }
  463. else {
  464. $newname = str_replace('_',' ',$name);
  465. //select someone from this user's contacts by name
  466. $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
  467. dbesc($newname),
  468. intval($page_owner_uid)
  469. );
  470. if(! $r) {
  471. //select someone by attag or nick and the name passed in
  472. $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1",
  473. dbesc($name),
  474. dbesc($name),
  475. intval($page_owner_uid)
  476. );
  477. }
  478. }
  479. /* elseif(strstr($name,'_') || strstr($name,' ')) {
  480. $newname = str_replace('_',' ',$name);
  481. $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
  482. dbesc($newname),
  483. intval($page_owner_uid)
  484. );
  485. }
  486. else {
  487. $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1",
  488. dbesc($name),
  489. dbesc($name),
  490. intval($page_owner_uid)
  491. );
  492. }*/
  493. if(count($r)) {
  494. $newname = $r[0]['name'];
  495. $profile = $r[0]['url'];
  496. $notify = 'cid:' . $r[0]['id'];
  497. if(strlen($inform))
  498. $inform .= ',';
  499. $inform .= $notify;
  500. }
  501. }
  502. if($profile) {
  503. if(substr($notify,0,4) === 'cid:')
  504. $taginfo[] = array($newname,$profile,$notify,$r[0],'@[url=' . str_replace(',','%2c',$profile) . ']' . $newname . '[/url]');
  505. else
  506. $taginfo[] = array($newname,$profile,$notify,null,$str_tags .= '@[url=' . $profile . ']' . $newname . '[/url]');
  507. if(strlen($str_tags))
  508. $str_tags .= ',';
  509. $profile = str_replace(',','%2c',$profile);
  510. $str_tags .= '@[url='.$profile.']'.$newname.'[/url]';
  511. }
  512. } elseif (strpos($tag,'#') === 0) {
  513. $tagname = substr($tag, 1);
  514. $str_tags .= '#[url='.$a->get_baseurl()."/search?tag=".$tagname.']'.$tagname.'[/url]';
  515. }
  516. }
  517. }
  518. $newtag = $old_tag;
  519. if(strlen($newtag) && strlen($str_tags))
  520. $newtag .= ',';
  521. $newtag .= $str_tags;
  522. $newinform = $old_inform;
  523. if(strlen($newinform) && strlen($inform))
  524. $newinform .= ',';
  525. $newinform .= $inform;
  526. $r = q("UPDATE `item` SET `tag` = '%s', `inform` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d",
  527. dbesc($newtag),
  528. dbesc($newinform),
  529. dbesc(datetime_convert()),
  530. dbesc(datetime_convert()),
  531. intval($item_id),
  532. intval($page_owner_uid)
  533. );
  534. create_tags_from_item($item_id);
  535. update_thread($item_id);
  536. $best = 0;
  537. foreach($p as $scales) {
  538. if(intval($scales['scale']) == 2) {
  539. $best = 2;
  540. break;
  541. }
  542. if(intval($scales['scale']) == 4) {
  543. $best = 4;
  544. break;
  545. }
  546. }
  547. if(count($taginfo)) {
  548. foreach($taginfo as $tagged) {
  549. $uri = item_new_uri($a->get_hostname(),$page_owner_uid);
  550. $arr = array();
  551. $arr['uid'] = $page_owner_uid;
  552. $arr['uri'] = $uri;
  553. $arr['parent-uri'] = $uri;
  554. $arr['type'] = 'activity';
  555. $arr['wall'] = 1;
  556. $arr['contact-id'] = $owner_record['id'];
  557. $arr['owner-name'] = $owner_record['name'];
  558. $arr['owner-link'] = $owner_record['url'];
  559. $arr['owner-avatar'] = $owner_record['thumb'];
  560. $arr['author-name'] = $owner_record['name'];
  561. $arr['author-link'] = $owner_record['url'];
  562. $arr['author-avatar'] = $owner_record['thumb'];
  563. $arr['title'] = '';
  564. $arr['allow_cid'] = $p[0]['allow_cid'];
  565. $arr['allow_gid'] = $p[0]['allow_gid'];
  566. $arr['deny_cid'] = $p[0]['deny_cid'];
  567. $arr['deny_gid'] = $p[0]['deny_gid'];
  568. $arr['last-child'] = 1;
  569. $arr['visible'] = 1;
  570. $arr['verb'] = ACTIVITY_TAG;
  571. $arr['object-type'] = ACTIVITY_OBJ_PERSON;
  572. $arr['target-type'] = ACTIVITY_OBJ_PHOTO;
  573. $arr['tag'] = $tagged[4];
  574. $arr['inform'] = $tagged[2];
  575. $arr['origin'] = 1;
  576. $arr['body'] = sprintf( t('%1$s was tagged in %2$s by %3$s'), '[url=' . $tagged[1] . ']' . $tagged[0] . '[/url]', '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . t('a photo') . '[/url]', '[url=' . $owner_record['url'] . ']' . $owner_record['name'] . '[/url]') ;
  577. $arr['body'] .= "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.' . $ext . '[/img][/url]' . "\n" ;
  578. $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $tagged[0] . '</title><id>' . $tagged[1] . '/' . $tagged[0] . '</id>';
  579. $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $tagged[1] . '" />' . "\n");
  580. if($tagged[3])
  581. $arr['object'] .= xmlify('<link rel="photo" type="'.$p[0]['type'].'" href="' . $tagged[3]['photo'] . '" />' . "\n");
  582. $arr['object'] .= '</link></object>' . "\n";
  583. $arr['target'] = '<target><type>' . ACTIVITY_OBJ_PHOTO . '</type><title>' . $p[0]['desc'] . '</title><id>'
  584. . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '</id>';
  585. $arr['target'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '" />' . "\n" . '<link rel="preview" type="'.$p[0]['type'].'" href="' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.' . $ext . '" />') . '</link></target>';
  586. $item_id = item_store($arr);
  587. if($item_id) {
  588. //q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d",
  589. // dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id),
  590. // intval($page_owner_uid),
  591. // intval($item_id)
  592. //);
  593. proc_run('php',"include/notifier.php","tag","$item_id");
  594. }
  595. }
  596. }
  597. }
  598. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  599. return; // NOTREACHED
  600. }
  601. /**
  602. * default post action - upload a photo
  603. */
  604. call_hooks('photo_post_init', $_POST);
  605. /**
  606. * Determine the album to use
  607. */
  608. $album = notags(trim($_REQUEST['album']));
  609. $newalbum = notags(trim($_REQUEST['newalbum']));
  610. logger('mod/photos.php: photos_post(): album= ' . $album . ' newalbum= ' . $newalbum , LOGGER_DEBUG);
  611. if(! strlen($album)) {
  612. if(strlen($newalbum))
  613. $album = $newalbum;
  614. else
  615. $album = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
  616. }
  617. /**
  618. *
  619. * We create a wall item for every photo, but we don't want to
  620. * overwhelm the data stream with a hundred newly uploaded photos.
  621. * So we will make the first photo uploaded to this album in the last several hours
  622. * visible by default, the rest will become visible over time when and if
  623. * they acquire comments, likes, dislikes, and/or tags
  624. *
  625. */
  626. $r = q("SELECT * FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `created` > UTC_TIMESTAMP() - INTERVAL 3 HOUR ",
  627. dbesc($album),
  628. intval($page_owner_uid)
  629. );
  630. if((! count($r)) || ($album == t('Profile Photos')))
  631. $visible = 1;
  632. else
  633. $visible = 0;
  634. if(intval($_REQUEST['not_visible']) || $_REQUEST['not_visible'] === 'true')
  635. $visible = 0;
  636. $str_group_allow = perms2str(((is_array($_REQUEST['group_allow'])) ? $_REQUEST['group_allow'] : explode(',',$_REQUEST['group_allow'])));
  637. $str_contact_allow = perms2str(((is_array($_REQUEST['contact_allow'])) ? $_REQUEST['contact_allow'] : explode(',',$_REQUEST['contact_allow'])));
  638. $str_group_deny = perms2str(((is_array($_REQUEST['group_deny'])) ? $_REQUEST['group_deny'] : explode(',',$_REQUEST['group_deny'])));
  639. $str_contact_deny = perms2str(((is_array($_REQUEST['contact_deny'])) ? $_REQUEST['contact_deny'] : explode(',',$_REQUEST['contact_deny'])));
  640. $ret = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
  641. call_hooks('photo_post_file',$ret);
  642. if(x($ret,'src') && x($ret,'filesize')) {
  643. $src = $ret['src'];
  644. $filename = $ret['filename'];
  645. $filesize = $ret['filesize'];
  646. $type = $ret['type'];
  647. }
  648. else {
  649. $src = $_FILES['userfile']['tmp_name'];
  650. $filename = basename($_FILES['userfile']['name']);
  651. $filesize = intval($_FILES['userfile']['size']);
  652. $type = $_FILES['userfile']['type'];
  653. }
  654. if ($type=="") $type=guess_image_type($filename);
  655. logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG);
  656. $maximagesize = get_config('system','maximagesize');
  657. if(($maximagesize) && ($filesize > $maximagesize)) {
  658. notice( sprintf(t('Image exceeds size limit of %s'), formatBytes($maximagesize)) . EOL);
  659. @unlink($src);
  660. $foo = 0;
  661. call_hooks('photo_post_end',$foo);
  662. return;
  663. }
  664. if(! $filesize) {
  665. notice( t('Image file is empty.') . EOL);
  666. @unlink($src);
  667. $foo = 0;
  668. call_hooks('photo_post_end',$foo);
  669. return;
  670. }
  671. logger('mod/photos.php: photos_post(): loading the contents of ' . $src , LOGGER_DEBUG);
  672. $imagedata = @file_get_contents($src);
  673. $r = q("select sum(octet_length(data)) as total from photo where uid = %d and scale = 0 and album != 'Contact Photos' ",
  674. intval($a->data['user']['uid'])
  675. );
  676. $limit = service_class_fetch($a->data['user']['uid'],'photo_upload_limit');
  677. if(($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
  678. notice( upgrade_message() . EOL );
  679. @unlink($src);
  680. $foo = 0;
  681. call_hooks('photo_post_end',$foo);
  682. killme();
  683. }
  684. $ph = new Photo($imagedata, $type);
  685. if(! $ph->is_valid()) {
  686. logger('mod/photos.php: photos_post(): unable to process image' , LOGGER_DEBUG);
  687. notice( t('Unable to process image.') . EOL );
  688. @unlink($src);
  689. $foo = 0;
  690. call_hooks('photo_post_end',$foo);
  691. killme();
  692. }
  693. $ph->orient($src);
  694. @unlink($src);
  695. $max_length = get_config('system','max_image_length');
  696. if(! $max_length)
  697. $max_length = MAX_IMAGE_LENGTH;
  698. if($max_length > 0)
  699. $ph->scaleImage($max_length);
  700. $width = $ph->getWidth();
  701. $height = $ph->getHeight();
  702. $smallest = 0;
  703. $photo_hash = photo_new_resource();
  704. $r = $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
  705. if(! $r) {
  706. logger('mod/photos.php: photos_post(): image store failed' , LOGGER_DEBUG);
  707. notice( t('Image upload failed.') . EOL );
  708. killme();
  709. }
  710. if($width > 640 || $height > 640) {
  711. $ph->scaleImage(640);
  712. $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
  713. $smallest = 1;
  714. }
  715. if($width > 320 || $height > 320) {
  716. $ph->scaleImage(320);
  717. $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
  718. $smallest = 2;
  719. }
  720. $basename = basename($filename);
  721. $uri = item_new_uri($a->get_hostname(), $page_owner_uid);
  722. // Create item container
  723. $arr = array();
  724. $arr['uid'] = $page_owner_uid;
  725. $arr['uri'] = $uri;
  726. $arr['parent-uri'] = $uri;
  727. $arr['type'] = 'photo';
  728. $arr['wall'] = 1;
  729. $arr['resource-id'] = $photo_hash;
  730. $arr['contact-id'] = $owner_record['id'];
  731. $arr['owner-name'] = $owner_record['name'];
  732. $arr['owner-link'] = $owner_record['url'];
  733. $arr['owner-avatar'] = $owner_record['thumb'];
  734. $arr['author-name'] = $owner_record['name'];
  735. $arr['author-link'] = $owner_record['url'];
  736. $arr['author-avatar'] = $owner_record['thumb'];
  737. $arr['title'] = '';
  738. $arr['allow_cid'] = $str_contact_allow;
  739. $arr['allow_gid'] = $str_group_allow;
  740. $arr['deny_cid'] = $str_contact_deny;
  741. $arr['deny_gid'] = $str_group_deny;
  742. $arr['last-child'] = 1;
  743. $arr['visible'] = $visible;
  744. $arr['origin'] = 1;
  745. $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo_hash . ']'
  746. . '[img]' . $a->get_baseurl() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/img]'
  747. . '[/url]';
  748. $item_id = item_store($arr);
  749. //if($item_id) {
  750. // q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d",
  751. // dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id),
  752. // intval($page_owner_uid),
  753. // intval($item_id)
  754. // );
  755. //}
  756. if($visible)
  757. proc_run('php', "include/notifier.php", 'wall-new', $item_id);
  758. call_hooks('photo_post_end',intval($item_id));
  759. // addon uploaders should call "killme()" [e.g. exit] within the photo_post_end hook
  760. // if they do not wish to be redirected
  761. goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
  762. // NOTREACHED
  763. }
  764. function photos_content(&$a) {
  765. // URLs:
  766. // photos/name
  767. // photos/name/upload
  768. // photos/name/upload/xxxxx (xxxxx is album name)
  769. // photos/name/album/xxxxx
  770. // photos/name/album/xxxxx/edit
  771. // photos/name/image/xxxxx
  772. // photos/name/image/xxxxx/edit
  773. if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
  774. notice( t('Public access denied.') . EOL);
  775. return;
  776. }
  777. require_once('include/bbcode.php');
  778. require_once('include/security.php');
  779. require_once('include/conversation.php');
  780. if(! x($a->data,'user')) {
  781. notice( t('No photos selected') . EOL );
  782. return;
  783. }
  784. $phototypes = Photo::supportedTypes();
  785. $_SESSION['photo_return'] = $a->cmd;
  786. //
  787. // Parse arguments
  788. //
  789. if($a->argc > 3) {
  790. $datatype = $a->argv[2];
  791. $datum = $a->argv[3];
  792. }
  793. elseif(($a->argc > 2) && ($a->argv[2] === 'upload'))
  794. $datatype = 'upload';
  795. else
  796. $datatype = 'summary';
  797. if($a->argc > 4)
  798. $cmd = $a->argv[4];
  799. else
  800. $cmd = 'view';
  801. //
  802. // Setup permissions structures
  803. //
  804. $can_post = false;
  805. $visitor = 0;
  806. $contact = null;
  807. $remote_contact = false;
  808. $contact_id = 0;
  809. $owner_uid = $a->data['user']['uid'];
  810. $community_page = (($a->data['user']['page-flags'] == PAGE_COMMUNITY) ? true : false);
  811. if((local_user()) && (local_user() == $owner_uid))
  812. $can_post = true;
  813. else {
  814. if($community_page && remote_user()) {
  815. if(is_array($_SESSION['remote'])) {
  816. foreach($_SESSION['remote'] as $v) {
  817. if($v['uid'] == $owner_uid) {
  818. $contact_id = $v['cid'];
  819. break;
  820. }
  821. }
  822. }
  823. if($contact_id) {
  824. $r = q("SELECT `uid` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
  825. intval($contact_id),
  826. intval($owner_uid)
  827. );
  828. if(count($r)) {
  829. $can_post = true;
  830. $contact = $r[0];
  831. $remote_contact = true;
  832. $visitor = $cid;
  833. }
  834. }
  835. }
  836. }
  837. // perhaps they're visiting - but not a community page, so they wouldn't have write access
  838. if(remote_user() && (! $visitor)) {
  839. $contact_id = 0;
  840. if(is_array($_SESSION['remote'])) {
  841. foreach($_SESSION['remote'] as $v) {
  842. if($v['uid'] == $owner_uid) {
  843. $contact_id = $v['cid'];
  844. break;
  845. }
  846. }
  847. }
  848. if($contact_id) {
  849. $groups = init_groups_visitor($contact_id);
  850. $r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
  851. intval($contact_id),
  852. intval($owner_uid)
  853. );
  854. if(count($r)) {
  855. $contact = $r[0];
  856. $remote_contact = true;
  857. }
  858. }
  859. }
  860. if(! $remote_contact) {
  861. if(local_user()) {
  862. $contact_id = $_SESSION['cid'];
  863. $contact = $a->contact;
  864. }
  865. }
  866. if($a->data['user']['hidewall'] && (local_user() != $owner_uid) && (! $remote_contact)) {
  867. notice( t('Access to this item is restricted.') . EOL);
  868. return;
  869. }
  870. $sql_extra = permissions_sql($owner_uid,$remote_contact,$groups);
  871. $o = "";
  872. // tabs
  873. $is_owner = (local_user() && (local_user() == $owner_uid));
  874. $o .= profile_tabs($a,$is_owner, $a->data['user']['nickname']);
  875. //
  876. // dispatch request
  877. //
  878. if($datatype === 'upload') {
  879. if(! ($can_post)) {
  880. notice( t('Permission denied.'));
  881. return;
  882. }
  883. $selname = (($datum) ? hex2bin($datum) : '');
  884. $albumselect = '';
  885. $albumselect .= '<option value="" ' . ((! $selname) ? ' selected="selected" ' : '') . '>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</option>';
  886. if(count($a->data['albums'])) {
  887. foreach($a->data['albums'] as $album) {
  888. if(($album['album'] === '') || ($album['album'] === 'Contact Photos') || ($album['album'] === t('Contact Photos')))
  889. continue;
  890. $selected = (($selname === $album['album']) ? ' selected="selected" ' : '');
  891. $albumselect .= '<option value="' . $album['album'] . '"' . $selected . '>' . $album['album'] . '</option>';
  892. }
  893. }
  894. $uploader = '';
  895. $ret = array('post_url' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'],
  896. 'addon_text' => $uploader,
  897. 'default_upload' => true);
  898. call_hooks('photo_upload_form',$ret);
  899. $default_upload_box = replace_macros(get_markup_template('photos_default_uploader_box.tpl'), array());
  900. $default_upload_submit = replace_macros(get_markup_template('photos_default_uploader_submit.tpl'), array(
  901. '$submit' => t('Submit'),
  902. ));
  903. $usage_message = '';
  904. $limit = service_class_fetch($a->data['user']['uid'],'photo_upload_limit');
  905. if($limit !== false) {
  906. $r = q("select sum(datasize) as total from photo where uid = %d and scale = 0 and album != 'Contact Photos' ",
  907. intval($a->data['user']['uid'])
  908. );
  909. $usage_message = sprintf( t("You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."), $r[0]['total'] / 1024000, $limit / 1024000 );
  910. }
  911. // Private/public post links for the non-JS ACL form
  912. $private_post = 1;
  913. if($_REQUEST['public'])
  914. $private_post = 0;
  915. $query_str = $a->query_string;
  916. if(strpos($query_str, 'public=1') !== false)
  917. $query_str = str_replace(array('?public=1', '&public=1'), array('', ''), $query_str);
  918. // I think $a->query_string may never have ? in it, but I could be wrong
  919. // It looks like it's from the index.php?q=[etc] rewrite that the web
  920. // server does, which converts any ? to &, e.g. suggest&ignore=61 for suggest?ignore=61
  921. if(strpos($query_str, '?') === false)
  922. $public_post_link = '?public=1';
  923. else
  924. $public_post_link = '&public=1';
  925. $tpl = get_markup_template('photos_upload.tpl');
  926. if($a->theme['template_engine'] === 'internal') {
  927. $albumselect_e = template_escape($albumselect);
  928. $aclselect_e = (($visitor) ? '' : template_escape(populate_acl($a->user)));
  929. }
  930. else {
  931. $albumselect_e = $albumselect;
  932. $aclselect_e = (($visitor) ? '' : populate_acl($a->user));
  933. }
  934. $o .= replace_macros($tpl,array(
  935. '$pagename' => t('Upload Photos'),
  936. '$sessid' => session_id(),
  937. '$usage' => $usage_message,
  938. '$nickname' => $a->data['user']['nickname'],
  939. '$newalbum' => t('New album name: '),
  940. '$existalbumtext' => t('or existing album name: '),
  941. '$nosharetext' => t('Do not show a status post for this upload'),
  942. '$albumselect' => $albumselect_e,
  943. '$permissions' => t('Permissions'),
  944. '$aclselect' => $aclselect_e,
  945. '$alt_uploader' => $ret['addon_text'],
  946. '$default_upload_box' => (($ret['default_upload']) ? $default_upload_box : ''),
  947. '$default_upload_submit' => (($ret['default_upload']) ? $default_upload_submit : ''),
  948. '$uploadurl' => $ret['post_url'],
  949. // ACL permissions box
  950. '$acl_data' => construct_acl_data($a, $a->user), // For non-Javascript ACL selector
  951. '$group_perms' => t('Show to Groups'),
  952. '$contact_perms' => t('Show to Contacts'),
  953. '$private' => t('Private Photo'),
  954. '$public' => t('Public Photo'),
  955. '$is_private' => $private_post,
  956. '$return_path' => $query_str,
  957. '$public_link' => $public_post_link,
  958. ));
  959. return $o;
  960. }
  961. if($datatype === 'album') {
  962. $album = hex2bin($datum);
  963. $r = q("SELECT `resource-id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
  964. AND `scale` <= 4 $sql_extra GROUP BY `resource-id`",
  965. intval($owner_uid),
  966. dbesc($album)
  967. );
  968. if(count($r)) {
  969. $a->set_pager_total(count($r));
  970. $a->set_pager_itemspage(20);
  971. }
  972. if($_GET['order'] === 'posted')
  973. $order = 'ASC';
  974. else
  975. $order = 'DESC';
  976. $r = q("SELECT `resource-id`, `id`, `filename`, type, max(`scale`) AS `scale`, `desc` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
  977. AND `scale` <= 4 $sql_extra GROUP BY `resource-id` ORDER BY `created` $order LIMIT %d , %d",
  978. intval($owner_uid),
  979. dbesc($album),
  980. intval($a->pager['start']),
  981. intval($a->pager['itemspage'])
  982. );
  983. if($cmd === 'edit') {
  984. if(($album !== t('Profile Photos')) && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
  985. if($can_post) {
  986. $edit_tpl = get_markup_template('album_edit.tpl');
  987. if($a->theme['template_engine'] === 'internal') {
  988. $album_e = template_escape($album);
  989. }
  990. else {
  991. $album_e = $album;
  992. }
  993. $o .= replace_macros($edit_tpl,array(
  994. '$nametext' => t('New album name: '),
  995. '$nickname' => $a->data['user']['nickname'],
  996. '$album' => $album_e,
  997. '$hexalbum' => bin2hex($album),
  998. '$submit' => t('Submit'),
  999. '$dropsubmit' => t('Delete Album')
  1000. ));
  1001. }
  1002. }
  1003. }
  1004. else {
  1005. if(($album !== t('Profile Photos')) && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
  1006. if($can_post) {
  1007. $edit = array(t('Edit Album'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '/edit');
  1008. }
  1009. }
  1010. }
  1011. if($_GET['order'] === 'posted')
  1012. $order = array(t('Show Newest First'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album));
  1013. else
  1014. $order = array(t('Show Oldest First'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '?f=&order=posted');
  1015. $photos = array();
  1016. if(count($r))
  1017. $twist = 'rotright';
  1018. foreach($r as $rr) {
  1019. if($twist == 'rotright')
  1020. $twist = 'rotleft';
  1021. else
  1022. $twist = 'rotright';
  1023. $ext = $phototypes[$rr['type']];
  1024. if($a->theme['template_engine'] === 'internal') {
  1025. $imgalt_e = template_escape($rr['filename']);
  1026. $desc_e = template_escape($rr['desc']);
  1027. }
  1028. else {
  1029. $imgalt_e = $rr['filename'];
  1030. $desc_e = $rr['desc'];
  1031. }
  1032. $photos[] = array(
  1033. 'id' => $rr['id'],
  1034. 'twist' => ' ' . $twist . rand(2,4),
  1035. 'link' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id']
  1036. . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''),
  1037. 'title' => t('View Photo'),
  1038. 'src' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext,
  1039. 'alt' => $imgalt_e,
  1040. 'desc'=> $desc_e,
  1041. 'ext' => $ext,
  1042. 'hash'=> $rr['resource_id'],
  1043. );
  1044. }
  1045. $tpl = get_markup_template('photo_album.tpl');
  1046. $o .= replace_macros($tpl, array(
  1047. '$photos' => $photos,
  1048. '$album' => $album,
  1049. '$can_post' => $can_post,
  1050. '$upload' => array(t('Upload New Photos'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/upload/' . bin2hex($album)),
  1051. '$order' => $order,
  1052. '$edit' => $edit
  1053. ));
  1054. $o .= paginate($a);
  1055. return $o;
  1056. }
  1057. if($datatype === 'image') {
  1058. //$o = '';
  1059. // fetch image, item containing image, then comments
  1060. $ph = q("SELECT * FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'
  1061. $sql_extra ORDER BY `scale` ASC ",
  1062. intval($owner_uid),
  1063. dbesc($datum)
  1064. );
  1065. if(! count($ph)) {
  1066. $ph = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'
  1067. LIMIT 1",
  1068. intval($owner_uid),
  1069. dbesc($datum)
  1070. );
  1071. if(count($ph))
  1072. notice( t('Permission denied. Access to this item may be restricted.'));
  1073. else
  1074. notice( t('Photo not available') . EOL );
  1075. return;
  1076. }
  1077. $prevlink = '';
  1078. $nextlink = '';
  1079. if($_GET['order'] === 'posted')
  1080. $order = 'ASC';
  1081. else
  1082. $order = 'DESC';
  1083. $prvnxt = q("SELECT `resource-id` FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `scale` = 0
  1084. $sql_extra ORDER BY `created` $order ",
  1085. dbesc($ph[0]['album']),
  1086. intval($owner_uid)
  1087. );
  1088. if(count($prvnxt)) {
  1089. for($z = 0; $z < count($prvnxt); $z++) {
  1090. if($prvnxt[$z]['resource-id'] == $ph[0]['resource-id']) {
  1091. $prv = $z - 1;
  1092. $nxt = $z + 1;
  1093. if($prv < 0)
  1094. $prv = count($prvnxt) - 1;
  1095. if($nxt >= count($prvnxt))
  1096. $nxt = 0;
  1097. break;
  1098. }
  1099. }
  1100. $edit_suffix = ((($cmd === 'edit') && ($can_post)) ? '/edit' : '');
  1101. $prevlink = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
  1102. $nextlink = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
  1103. }
  1104. if(count($ph) == 1)
  1105. $hires = $lores = $ph[0];
  1106. if(count($ph) > 1) {
  1107. if($ph[1]['scale'] == 2) {
  1108. // original is 640 or less, we can display it directly
  1109. $hires = $lores = $ph[0];
  1110. }
  1111. else {
  1112. $hires = $ph[0];
  1113. $lores = $ph[1];
  1114. }
  1115. }
  1116. $album_link = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($ph[0]['album']);
  1117. $tools = Null;
  1118. $lock = Null;
  1119. if($can_post && ($ph[0]['uid'] == $owner_uid)) {
  1120. $tools = array(
  1121. 'edit' => array($a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $datum . (($cmd === 'edit') ? '' : '/edit'), (($cmd === 'edit') ? t('View photo') : t('Edit photo'))),
  1122. 'profile'=>array($a->get_baseurl() . '/profile_photo/use/'.$ph[0]['resource-id'], t('Use as profile photo')),
  1123. );
  1124. // lock
  1125. $lock = ( ( ($ph[0]['uid'] == local_user()) && (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid'])
  1126. || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) )
  1127. ? t('Private Message')
  1128. : Null);
  1129. }
  1130. if( $cmd === 'edit') {
  1131. $tpl = get_markup_template('photo_edit_head.tpl');
  1132. $a->page['htmlhead'] .= replace_macros($tpl,array(
  1133. '$prevlink' => $prevlink,
  1134. '$nextlink' => $nextlink
  1135. ));
  1136. }
  1137. if($prevlink)
  1138. $prevlink = array($prevlink, '<div class="icon prev"></div>') ;
  1139. $photo = array(
  1140. 'href' => $a->get_baseurl() . '/photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
  1141. 'title'=> t('View Full Size'),
  1142. 'src' => $a->get_baseurl() . '/photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis'),
  1143. 'height' => $hires['height'],
  1144. 'width' => $hires['width'],
  1145. 'album' => $hires['album'],
  1146. 'filename' => $hires['filename'],
  1147. );
  1148. if($nextlink)
  1149. $nextlink = array($nextlink, '<div class="icon next"></div>');
  1150. // Do we have an item for this photo?
  1151. // FIXME! - replace following code to display the conversation with our normal
  1152. // conversation functions so that it works correctly and tracks changes
  1153. // in the evolving conversation code.
  1154. // The difference is that we won't be displaying the conversation head item
  1155. // as a "post" but displaying instead the photo it is linked to
  1156. $linked_items = q("SELECT * FROM `item` WHERE `resource-id` = '%s' $sql_extra LIMIT 1",
  1157. dbesc($datum)
  1158. );
  1159. if(count($linked_items)) {
  1160. $link_item = $linked_items[0];
  1161. $r = q("SELECT COUNT(*) AS `total`
  1162. FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  1163. WHERE `parent-uri` = '%s' AND `uri` != '%s' AND `item`.`deleted` = 0 and `item`.`moderated` = 0
  1164. AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  1165. AND `item`.`uid` = %d
  1166. $sql_extra ",
  1167. dbesc($link_item['uri']),
  1168. dbesc($link_item['uri']),
  1169. intval($link_item['uid'])
  1170. );
  1171. if(count($r))
  1172. $a->set_pager_total($r[0]['total']);
  1173. $r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
  1174. `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`network`,
  1175. `contact`.`rel`, `contact`.`thumb`, `contact`.`self`,
  1176. `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
  1177. FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  1178. WHERE `parent-uri` = '%s' AND `uri` != '%s' AND `item`.`deleted` = 0 and `item`.`moderated` = 0
  1179. AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  1180. AND `item`.`uid` = %d
  1181. $sql_extra
  1182. ORDER BY `parent` DESC, `id` ASC LIMIT %d ,%d ",
  1183. dbesc($link_item['uri']),
  1184. dbesc($link_item['uri']),
  1185. intval($link_item['uid']),
  1186. intval($a->pager['start']),
  1187. intval($a->pager['itemspage'])
  1188. );
  1189. if((local_user()) && (local_user() == $link_item['uid'])) {
  1190. q("UPDATE `item` SET `unseen` = 0 WHERE `parent` = %d and `uid` = %d",
  1191. intval($link_item['parent']),
  1192. intval(local_user())
  1193. );
  1194. update_thread($link_item['parent']);
  1195. }
  1196. }
  1197. $tags=Null;
  1198. if(count($linked_items) && strlen($link_item['tag'])) {
  1199. $arr = explode(',',$link_item['tag']);
  1200. // parse tags and add links
  1201. $tag_str = '';
  1202. foreach($arr as $t) {
  1203. if(strlen($tag_str))
  1204. $tag_str .= ', ';
  1205. $tag_str .= bbcode($t);
  1206. }
  1207. $tags = array(t('Tags: '), $tag_str);
  1208. if($cmd === 'edit') {
  1209. $tags[] = $a->get_baseurl() . '/tagrm/' . $link_item['id'];
  1210. $tags[] = t('[Remove any tag]');
  1211. }
  1212. }
  1213. $edit = Null;
  1214. if(($cmd === 'edit') && ($can_post)) {
  1215. $edit_tpl = get_markup_template('photo_edit.tpl');
  1216. // Private/public post links for the non-JS ACL form
  1217. $private_post = 1;
  1218. if($_REQUEST['public'])
  1219. $private_post = 0;
  1220. $query_str = $a->query_string;
  1221. if(strpos($query_str, 'public=1') !== false)
  1222. $query_str = str_replace(array('?public=1', '&public=1'), array('', ''), $query_str);
  1223. // I think $a->query_string may never have ? in it, but I could be wrong
  1224. // It looks like it's from the index.php?q=[etc] rewrite that the web
  1225. // server does, which converts any ? to &, e.g. suggest&ignore=61 for suggest?ignore=61
  1226. if(strpos($query_str, '?') === false)
  1227. $public_post_link = '?public=1';
  1228. else
  1229. $public_post_link = '&public=1';
  1230. if($a->theme['template_engine'] === 'internal') {
  1231. $album_e = template_escape($ph[0]['album']);
  1232. $caption_e = template_escape($ph[0]['desc']);
  1233. $aclselect_e = template_escape(populate_acl($ph[0]));
  1234. }
  1235. else {
  1236. $album_e = $ph[0]['album'];
  1237. $caption_e = $ph[0]['desc'];
  1238. $aclselect_e = populate_acl($ph[0]);
  1239. }
  1240. $edit = replace_macros($edit_tpl, array(
  1241. '$id' => $ph[0]['id'],
  1242. '$album' => array('albname', t('New album name'), $album_e,''),
  1243. '$caption' => array('desc', t('Caption'), $caption_e, ''),
  1244. '$tags' => array('newtag', t('Add a Tag'), "", t('Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping')),
  1245. '$rotate_none' => array('rotate',t('Do not rotate'),0,'', true),
  1246. '$rotate_cw' => array('rotate',t('Rotate CW (right)'),1,''),
  1247. '$rotate_ccw' => array('rotate',t('Rotate CCW (left)'),2,''),
  1248. '$nickname' => $a->data['user']['nickname'],
  1249. '$resource_id' => $ph[0]['resource-id'],
  1250. '$permissions' => t('Permissions'),
  1251. '$aclselect' => $aclselect_e,
  1252. '$item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
  1253. '$submit' => t('Submit'),
  1254. '$delete' => t('Delete Photo'),
  1255. // ACL permissions box
  1256. '$acl_data' => construct_acl_data($a, $ph[0]), // For non-Javascript ACL selector
  1257. '$group_perms' => t('Show to Groups'),
  1258. '$contact_perms' => t('Show to Contacts'),
  1259. '$private' => t('Private photo'),
  1260. '$public' => t('Public photo'),
  1261. '$is_private' => $private_post,
  1262. '$return_path' => $query_str,
  1263. '$public_link' => $public_post_link,
  1264. ));
  1265. }
  1266. if(count($linked_items)) {
  1267. $cmnt_tpl = get_markup_template('comment_item.tpl');
  1268. $tpl = get_markup_template('photo_item.tpl');
  1269. $return_url = $a->cmd;
  1270. $like_tpl = get_markup_template('like_noshare.tpl');
  1271. $likebuttons = '';
  1272. if($can_post || can_write_wall($a,$owner_uid)) {
  1273. $likebuttons = replace_macros($like_tpl,array(
  1274. '$id' => $link_item['id'],
  1275. '$likethis' => t("I like this \x28toggle\x29"),
  1276. '$nolike' => (feature_enabled(local_user(), 'dislike') ? t("I don't like this \x28toggle\x29") : ''),
  1277. '$share' => t('Share'),
  1278. '$wait' => t('Please wait'),
  1279. '$return_path' => $a->query_string,
  1280. ));
  1281. }
  1282. $comments = '';
  1283. if(! count($r)) {
  1284. if($can_post || can_write_wall($a,$owner_uid)) {
  1285. if($link_item['last-child']) {
  1286. $comments .= replace_macros($cmnt_tpl,array(
  1287. '$return_path' => '',
  1288. '$jsreload' => $return_url,
  1289. '$type' => 'wall-comment',
  1290. '$id' => $link_item['id'],
  1291. '$parent' => $link_item['id'],
  1292. '$profile_uid' => $owner_uid,
  1293. '$mylink' => $contact['url'],
  1294. '$mytitle' => t('This is you'),
  1295. '$myphoto' => $contact['thumb'],
  1296. '$comment' => t('Comment'),
  1297. '$submit' => t('Submit'),
  1298. '$preview' => t('Preview'),
  1299. '$sourceapp' => t($a->sourcename),
  1300. '$ww' => '',
  1301. '$rand_num' => random_digits(12)
  1302. ));
  1303. }
  1304. }
  1305. }
  1306. $alike = array();
  1307. $dlike = array();
  1308. $like = '';
  1309. $dislike = '';
  1310. // display comments
  1311. if(count($r)) {
  1312. foreach($r as $item) {
  1313. like_puller($a,$item,$alike,'like');
  1314. like_puller($a,$item,$dlike,'dislike');
  1315. }
  1316. $like = ((isset($alike[$link_item['id']])) ? format_like($alike[$link_item['id']],$alike[$link_item['id'] . '-l'],'like',$link_item['id']) : '');
  1317. $dislike = ((isset($dlike[$link_item['id']])) ? format_like($dlike[$link_item['id']],$dlike[$link_item['id'] . '-l'],'dislike',$link_item['id']) : '');
  1318. if($can_post || can_write_wall($a,$owner_uid)) {
  1319. if($link_item['last-child']) {
  1320. $comments .= replace_macros($cmnt_tpl,array(
  1321. '$return_path' => '',
  1322. '$jsreload' => $return_url,
  1323. '$type' => 'wall-comment',
  1324. '$id' => $link_item['id'],
  1325. '$parent' => $link_item['id'],
  1326. '$profile_uid' => $owner_uid,
  1327. '$mylink' => $contact['url'],
  1328. '$mytitle' => t('This is you'),
  1329. '$myphoto' => $contact['thumb'],
  1330. '$comment' => t('Comment'),
  1331. '$submit' => t('Submit'),
  1332. '$preview' => t('Preview'),
  1333. '$sourceapp' => t($a->sourcename),
  1334. '$ww' => '',
  1335. '$rand_num' => random_digits(12)
  1336. ));
  1337. }
  1338. }
  1339. foreach($r as $item) {
  1340. $comment = '';
  1341. $template = $tpl;
  1342. $sparkle = '';
  1343. if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
  1344. continue;
  1345. $redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
  1346. if(local_user() && ($item['contact-uid'] == local_user())
  1347. && ($item['network'] == NETWORK_DFRN) && (! $item['self'] )) {
  1348. $profile_url = $redirect_url;
  1349. $sparkle = ' sparkle';
  1350. }
  1351. else {
  1352. $profile_url = $item['url'];
  1353. $sparkle = '';
  1354. }
  1355. $diff_author = (($item['url'] !== $item['author-link']) ? true : false);
  1356. $profile_name = (((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']);
  1357. $profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $item['thumb']);
  1358. $profile_link = $profile_url;
  1359. $dropping = (($item['contact-id'] == $contact_id) || ($item['uid'] == local_user()));
  1360. $drop = array(
  1361. 'dropping' => $dropping,
  1362. 'pagedrop' => false,
  1363. 'select' => t('Select'),
  1364. 'delete' => t('Delete'),
  1365. );
  1366. if($a->theme['template_engine'] === 'internal') {
  1367. $name_e = template_escape($profile_name);
  1368. $title_e = template_escape($item['title']);
  1369. $body_e = template_escape(bbcode($item