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.

1856 lines
56 KiB

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