Browse Source

Merge branch 'master' of git://github.com/friendica/friendica

pull/129/head
Tobias Hößl 10 years ago
parent
commit
635958e11d
  1. 8
      .gitignore
  2. 0
      .gitmodules
  3. 2
      LICENSE
  4. 11
      README
  5. 4
      boot.php
  6. 38
      build.xml
  7. 8
      database.sql
  8. 20
      doc/Account-Basics.md
  9. 11
      doc/Bugs-and-Issues.md
  10. 9
      doc/Making-Friends.md
  11. 15
      doc/Remove-Account.md
  12. 13
      docblox.dist.xml
  13. 2
      htconfig.php
  14. BIN
      images/beer_mug.gif
  15. BIN
      images/bug-x.gif
  16. BIN
      images/icons/lock.png.tmp
  17. BIN
      images/smiley-Oo.gif
  18. BIN
      images/smiley-beard.png
  19. BIN
      images/smiley-brokenheart.gif
  20. BIN
      images/smiley-cool.gif
  21. BIN
      images/smiley-cry.gif
  22. BIN
      images/smiley-embarassed.gif
  23. BIN
      images/smiley-foot-in-mouth.gif
  24. BIN
      images/smiley-frown.gif
  25. BIN
      images/smiley-heart.gif
  26. BIN
      images/smiley-innocent.gif
  27. BIN
      images/smiley-kiss.gif
  28. BIN
      images/smiley-laughing.gif
  29. BIN
      images/smiley-money-mouth.gif
  30. BIN
      images/smiley-sealed.gif
  31. BIN
      images/smiley-smile.gif
  32. BIN
      images/smiley-surprised.gif
  33. BIN
      images/smiley-tongue-out.gif
  34. BIN
      images/smiley-undecided.gif
  35. BIN
      images/smiley-whitebeard.png
  36. BIN
      images/smiley-wink.gif
  37. BIN
      images/smiley-yell.gif
  38. BIN
      images/star.png
  39. BIN
      images/star_dummy.png
  40. 5
      include/Scrape.php
  41. 7
      include/acl_selectors.php
  42. 230
      include/conversation.php
  43. 36
      include/enotify.php
  44. 4
      include/html2bbcode.php
  45. 108
      include/items.php
  46. 3
      include/nav.php
  47. 2
      include/notifier.php
  48. 86
      include/security.php
  49. 87
      include/template_processor.php
  50. 43
      include/text.php
  51. 1
      js/fk.autocomplete.js
  52. 2
      js/main.js
  53. 4
      library/phpsec/Net/SSH1.php
  54. 34
      library/spam/b8/storage/storage_frndc.php
  55. 55
      mod/admin.php
  56. 12
      mod/dfrn_confirm.php
  57. 10
      mod/display.php
  58. 81
      mod/group.php
  59. 6
      mod/message.php
  60. 34
      mod/network.php
  61. 6
      mod/notify.php
  62. 23
      mod/ping.php
  63. 2
      mod/profile.php
  64. 2
      mod/search.php
  65. 18
      mod/share.php
  66. 10
      update.php
  67. 6
      util/db_update.php
  68. 145
      util/docblox_errorchecker.php
  69. 1185
      util/messages.po
  70. 2
      view/acl_selector.tpl
  71. 9
      view/admin_plugins_details.tpl
  72. 2
      view/admin_summary.tpl
  73. 18
      view/ca/cmnt_received_eml.tpl
  74. 13
      view/ca/follow_notify_eml.tpl
  75. 19
      view/ca/friend_complete_eml.tpl
  76. 68
      view/ca/htconfig.tpl
  77. 21
      view/ca/intro_complete_eml.tpl
  78. 35
      view/ca/lostpass_eml.tpl
  79. 24
      view/ca/mail_received_html_body_eml.tpl
  80. 9
      view/ca/mail_received_text_body_eml.tpl
  81. 6127
      view/ca/messages.po
  82. 19
      view/ca/passchanged_eml.tpl
  83. 22
      view/ca/register_open_eml.tpl
  84. 23
      view/ca/register_verify_eml.tpl
  85. 13
      view/ca/request_notify_eml.tpl
  86. 1425
      view/ca/strings.php
  87. 18
      view/ca/wall_received_eml.tpl
  88. 2
      view/comment_item.tpl
  89. 2
      view/contact_block.tpl
  90. 1
      view/contact_template.tpl
  91. 14
      view/conversation.tpl
  92. 144
      view/de/messages.po
  93. 140
      view/de/strings.php
  94. 30
      view/group_edit.tpl
  95. 23
      view/group_new.tpl
  96. 16
      view/groupeditor.tpl
  97. 19
      view/jot.tpl
  98. 79
      view/msg-header.tpl
  99. 2
      view/nets.tpl
  100. 72
      view/search_item.tpl

8
.gitignore

@ -10,3 +10,11 @@ home.html
addon
*~
#ignore documentation, it should be newly built
doc/api
#ignore config files from eclipse, we don't want IDE files in our repository
.project
.buildpath
.externalToolBuilders
.settings

0
view/theme/dispy/experimental → .gitmodules

2
LICENSE

@ -1,4 +1,4 @@
Copyright (c) 2010, 2011 the Friendica Project
Copyright (c) 2010-2012 the Friendica Project
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy

11
README

@ -0,0 +1,11 @@
Friendica Social Communications Server
======================================
http://friendica.com
Welcome to the free social web.
Friendica is a communications platform for integrated social communications utilising decentralised communications and linkage to several indie social projects - as well as popular mainstream providers.
Our mission is to free our friends and families from the clutches of data-harvesting corporations, and pave the way to a future where social communications are free and open and flow between alternate providers as easily as email does today.

4
boot.php

@ -9,9 +9,9 @@ require_once('include/nav.php');
require_once('include/cache.php');
define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_VERSION', '2.3.1265' );
define ( 'FRIENDICA_VERSION', '2.3.1275' );
define ( 'DFRN_PROTOCOL_VERSION', '2.22' );
define ( 'DB_UPDATE_VERSION', 1129 );
define ( 'DB_UPDATE_VERSION', 1131 );
define ( 'EOL', "<br />\r\n" );
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );

38
build.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="friendica" default="test">
<!-- =================================== -->
<!-- Target: test -->
<!-- this target runs all test files -->
<!-- =================================== -->
<target name="test">
<!-- there are no tests by now, so, nothing to do -->
</target>
<!-- ===================================================== -->
<!-- Target: clean-doc -->
<!-- this target removes documentation from a previous run -->
<!-- ===================================================== -->
<target name="doc-clean">
<echo msg="Removing old documentation..." />
<delete dir="./doc/api/" />
<echo msg="Generate documentation directory..." />
<mkdir dir="./doc/api/" />
</target>
<!-- ====================================== -->
<!-- Target: doc -->
<!-- this target builds all documentation -->
<!-- ====================================== -->
<target name="doc" depends="doc-clean">
<echo msg="Building documentation..." />
<docblox title="Friendica API" destdir="./doc/api">
<fileset dir=".">
<include name="**/*.php" />
</fileset>
</docblox>
</target>
</project>

8
database.sql

@ -216,6 +216,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`tag` mediumtext NOT NULL,
`attach` mediumtext NOT NULL,
`inform` mediumtext NOT NULL,
`file` mediumtext NOT NULL,
`location` char(255) NOT NULL,
`coord` char(255) NOT NULL,
`allow_cid` mediumtext NOT NULL,
@ -262,6 +263,7 @@ CREATE TABLE IF NOT EXISTS `item` (
FULLTEXT KEY `title` (`title`),
FULLTEXT KEY `body` (`body`),
FULLTEXT KEY `tag` (`tag`),
FULLTEXT KEY `file` (`file`),
FULLTEXT KEY `allow_cid` (`allow_cid`),
FULLTEXT KEY `allow_gid` (`allow_gid`),
FULLTEXT KEY `deny_cid` (`deny_cid`),
@ -752,14 +754,18 @@ CREATE TABLE IF NOT EXISTS `notify` (
`msg` MEDIUMTEXT NOT NULL ,
`uid` INT NOT NULL ,
`link` CHAR( 255 ) NOT NULL ,
`parent` INT( 11 ) NOT NULL,
`seen` TINYINT( 1 ) NOT NULL DEFAULT '0',
`verb` CHAR( 255 ) NOT NULL,
`otype` CHAR( 16 ) NOT NULL,
INDEX ( `hash` ),
INDEX ( `type` ),
INDEX ( `uid` ),
INDEX ( `link` ),
INDEX ( `parent` ),
INDEX ( `seen` ),
INDEX ( `date` )
INDEX ( `date` ),
INDEX ( `otype` )
) ENGINE = MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `item_id` (

20
doc/Account-Basics.md

@ -6,7 +6,9 @@ Account Basics
**Registration**
Not all Friendica sites allow open registration. If registration is allowed, you will see a "Register" link immediately below the login prompts on the site home page. Following this link will take you to the site Registration page.
Not all Friendica sites allow open registration. If registration is allowed, you will see a "Register" link immediately below the login prompts on the site home page. Following this link will take you to the site registration page. The strength of our network is that lots of different sites are all completely compatible with each other. If the site you're visting doesn't allow registration, or you think you might prefer another one, you can find a <a href ="http://dir.friendica.com/siteinfo">list of public servers here</a>, and find one that meets your needs.
If you'd like to have your own server, you can do that too. Visit <a href = "http://friendica.com/download">the Friendica website</a> to download the code with setup instructions. It's a very simple install process that anybody experienced in hosting websites, or with basic Linux experience can handle easily.
*OpenID*
@ -14,11 +16,11 @@ The first field on the Registration page is for an OpenID address. If you do not
*Your Full Name*
Please provide your full name as you would like it to be displayed on this system.
Please provide your full name **as you would like it to be displayed on this system**. Most people use their real name for this, but you're under no obligation to do so yourself.
*Email Address*
Please provide a valid email address. Your email address is **never** published. We need this to send you account information and your login details. You may also occasionally receive notifications of incoming messages or items requiring your attention, but you have the ability to completely disable these from your Settings page once you have logged in.
Please provide a valid email address. Your email address is **never** published. We need this to send you account information and your login details. You may also occasionally receive notifications of incoming messages or items requiring your attention, but you have the ability to completely disable these from your Settings page once you have logged in. This doesn't have to be your primary email address, but it does need to be a real email address. You can't get your initial password, or reset a lost password later without it. This is the only bit of personal information that has to be accurate.
*Nickname*
@ -28,12 +30,12 @@ A nickname is used to generate web addresses for many of your personal pages, an
*Directory Publishing*
The Registration form also allows you to choose whether or not to list your account in the online directory. This is like a "phone book" and you may choose to be unlisted. We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you. If you choose 'No', you will essentially be invisible and have few opportunities for interaction. Whichever you choose, this can be changed any time from your Settings page after you login.
The Registration form also allows you to choose whether or not to list your account in the online directory. This is like a "phone book" and you may choose to be unlisted. We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you. If you choose 'No', you will essentially be invisible and have few opportunities for interaction. Whichever you choose, this can be changed any time from your Settings page after you login.
*Register*
Once you have provided the necessary details, click the 'Register' button. An email will be sent to you providing your account login details. Some sites may require administrator approval before the registration is processed, and you will be alerted if this is the case. Please watch your email (including spam folders) for your registration approval.
Once you have provided the necessary details, click the 'Register' button. An email will be sent to you providing your account login details. Please watch your email (including spam folders) for your registration details and initial password.
@ -58,6 +60,11 @@ After your first login, please visit the 'Settings' page from the top menu bar a
A ['Tips for New Members'](newmember) link will show up on your home page for two weeks to provide some important Getting Started information.
**Retrieving Personal Data**
You can export a copy of your personal data in XML format from the "Export personal data" link at the top of your settings page.
**See Also**
* [Profiles](help/Profiles)
@ -66,4 +73,3 @@ A ['Tips for New Members'](newmember) link will show up on your home page for tw
* [Remove Account](help/Remove-Account)

11
doc/Bugs-and-Issues.md

@ -4,18 +4,19 @@ Bugs and Issues
* [Home](help)
Please report any bugs/issues you encounter using our bug tracker at [[http://bugs.friendica.com]]
If your server has a support page, you should report any bugs/issues you encounter there first. Reporting to your support page before reporting to the developers makes their job easier, as they don't have to deal with bug reports that might not have anything to do with them, and that helps us get new features faster.
Try to provide as much information as you can about the bug (including the full text of any error messages or notices), and if possible your Friendica version.
If you're a technical user, or your site doesn't have a support page, you'll need to use the <a href = "http://bugs.friendica.com/">Bug Tracker</a>. Please perform a search to see if there's already an open bug that matches yours before submitting anything.
Your Friendica version may be found in newer releases by visiting http://YOURFRIENDICASITE/friendica
Try to provide as much information as you can about the bug, including the **full** text of any error messages or notices, and any steps required to replicate the problem in as much detail as possible. It's generally better to provide too much information than not enough.
For older versions, view the HTML source of your profile page. The Friendica version is in the HTML header, 5-10 lines from the top of the page.
<a href = "http://www.chiark.greenend.org.uk/~sgtatham/bugs.html">See this article</a> to learn more about submitting **good** bug reports.
For really old versions which don't have a version number in the HTML header - please upgrade. Your bug was probably fixed a long time ago.
**Bug Sponsorship**
If you find a bug, and it is caused by a problem in main branch (ie, is not specific to our site), you may sponsor it.
The bug/issue database allows you to sponsor issues. This provides an incentive for developers to work on your issue. This isn't necessary - we don't like bugs and will try to fix them. This has more importance for future development projects and feature requests.
Bug sponsorship works on the honour system. If you agree to pay $10 to fix a bug, when the fix has been checked in and verified you should send a paypal payment to the developer assigned to the bug. Don't ever think you can get away with not paying a developer for work performed. Some of these guys could hack into your credit card account if you make them mad.

9
doc/Making-Friends.md

@ -5,7 +5,13 @@ Making Friends
Friendship in Friendica can take on a great many different meanings. But let's keep it simple, you want to be friends with somebody. How do you do it?
The first thing you can do is look at the Directory for somebody you would like to connect with. Visit their profile. Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile).
The easiest thing to do is to join the <a href = "http://kakste.com/profile/newhere">New Here</a> group. This group is especially for people new to the Friendica network. Simply connect to the group, post to the wall, and make new friends. You don't even have to like us - comment on a few of our posts, and other people will start to add you too.
The next thing you can do is look at the Directory. The directory is split up into two parts. If you click the directory button, you will be presented with a list of all members (who chose to be listed) on your server. You'll also see a link to the Global Directory. If you click through to the global directory, you will be presented with a list of everybody who chose to be listed across all instances of Friendica. You will also see a "Show Community Forums" link, which will direct you to Groups, Forums and Fanpages. You connect to people, groups and forums in the same way, except groups and forums will automatically accept your introduction request, whereas a human will approve you manually.
To connect with other Friendica user
Visit their profile. Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile).
Click that. It will take you to a "Connect" form.
@ -23,6 +29,7 @@ When you've submitted the connection page, it will take you back to your own sit
If you already know somebody's Identity Address, you can enter it in the "connect" box on your "Contacts" page. This will take you through a similar process.
**Alternate Networks**
You can also use your Identity Address or other people's Identity Addresses to become friends across networks. The list of possible networks is growing all the time. If you know (for instance) "bob" on identi.ca (a Status.Net site) you could put bob@identi.ca into your Contact page and become friends across networks. (Or you can put in the URL to Bob's identi.ca page if you wish). You can also be "partial" friends with somebody on Google Buzz by putting in their gmail address. Google Buzz does not yet support all the protocols we need for direct messaging, but you should be able to follow status updates from within Friendica. You can do the same for Twitter accounts and Diaspora accounts. In fact you can "follow" most anybody or any website that produces a syndication feed (RSS/Atom,etc.). If we can find an information stream and a name to attach to the contact, we'll try to connect with them.

15
doc/Remove-Account.md

@ -5,9 +5,20 @@ Remove Account
We don't like to see people leave Friendica, but if you need to remove your account, you should visit the URL
http://friendica-site/removeme
http://sitename/removeme
with your web browser. You will need to be logged in at the time. (Replace "friendica-site" with the hostname of your Friendica server)
with your web browser. You will need to be logged in at the time.
You will be asked for your password to confirm the request. If this matches your stored password, your account will immediately be removed. Unlike some social networks we do **not** hold onto it for a grace period in case you change your mind. Your user details, your conversations, your photos, your friends - everything; will be removed immediately and you will be logged out.
When we expire posts we send notifications out to Friendica to remove the posts. Diaspora doesn't have a bulk delete so this step is skipped on that network - and hopefully it will be obvious that deletion doesn't work on any other networks. If you manually delete a post or a range of posts we send individual delete notifications to Friendica and Diaspora for each deleted post.
Diaspora often loses these.
If you delete a post but somebody else has starred it, it is still removed. Your wishes take priority.
When you remove your account we physically remove all your posts and your profile and user data, etc. immediately.
In order to send out a bulk remove we would need to keep your account around to do this, as we would need to prove to your friends who it is that is submitting the request. We can't do this if you don't have an account.
Your friends may still see your posts if your account is gone, but there is no public place within Friendica where they can be viewed. If you had friends on Diaspora, your public posts may stick around and be visible to others from that network.

13
docblox.dist.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<docblox>
<parser>
<target>data/output</target>
</parser>
<transformer>
<target>data/output</target>
</transformer>
<files>
<directory>.</directory>
</files>
</docblox>

2
htconfig.php

@ -69,7 +69,7 @@ $a->config['system']['rino_encrypt'] = true;
// allowed themes (change this from admin panel after installation)
$a->config['system']['allowed_themes'] = 'dispy,quattro,testbubble,vier,darkbubble,darkzero,duepuntozero,greenzero,purplezero,quattro-green,slackr';
$a->config['system']['allowed_themes'] = 'dispy,quattro,testbubble,vier,darkbubble,darkzero,duepuntozero,greenzero,purplezero,quattro-green,slackr,diabook,diabook-blue';
// default system theme

BIN
images/beer_mug.gif

Before

Width: 19  |  Height: 19  |  Size: 1.0 KiB

After

Width: 19  |  Height: 19  |  Size: 1021 B

BIN
images/bug-x.gif

After

Width: 16  |  Height: 16  |  Size: 134 B

BIN
images/icons/lock.png.tmp

Before

Width: 128  |  Height: 128  |  Size: 8.0 KiB

BIN
images/smiley-Oo.gif

Before

Width: 16  |  Height: 16  |  Size: 1.0 KiB

After

Width: 16  |  Height: 16  |  Size: 1003 B

BIN
images/smiley-beard.png

After

Width: 18  |  Height: 18  |  Size: 1.1 KiB

BIN
images/smiley-brokenheart.gif

Before

Width: 18  |  Height: 18  |  Size: 616 B

After

Width: 18  |  Height: 18  |  Size: 598 B

BIN
images/smiley-cool.gif

Before

Width: 18  |  Height: 18  |  Size: 354 B

After

Width: 18  |  Height: 18  |  Size: 315 B

BIN
images/smiley-cry.gif

Before

Width: 18  |  Height: 18  |  Size: 329 B

After

Width: 18  |  Height: 18  |  Size: 303 B

BIN
images/smiley-embarassed.gif

Before

Width: 18  |  Height: 18  |  Size: 331 B

After

Width: 18  |  Height: 18  |  Size: 300 B

BIN
images/smiley-foot-in-mouth.gif

Before

Width: 18  |  Height: 18  |  Size: 344 B

After

Width: 18  |  Height: 18  |  Size: 306 B

BIN
images/smiley-frown.gif

Before

Width: 18  |  Height: 18  |  Size: 340 B

After

Width: 18  |  Height: 18  |  Size: 301 B

BIN
images/smiley-heart.gif

Before

Width: 18  |  Height: 18  |  Size: 592 B

After

Width: 18  |  Height: 18  |  Size: 577 B

BIN
images/smiley-innocent.gif

Before

Width: 18  |  Height: 18  |  Size: 336 B

After

Width: 18  |  Height: 18  |  Size: 305 B

BIN
images/smiley-kiss.gif

Before

Width: 18  |  Height: 18  |  Size: 338 B

After

Width: 18  |  Height: 18  |  Size: 299 B

BIN
images/smiley-laughing.gif

Before

Width: 18  |  Height: 18  |  Size: 344 B

After

Width: 18  |  Height: 18  |  Size: 306 B

BIN
images/smiley-money-mouth.gif

Before

Width: 18  |  Height: 18  |  Size: 321 B

After

Width: 18  |  Height: 18  |  Size: 291 B

BIN
images/smiley-sealed.gif

Before

Width: 18  |  Height: 18  |  Size: 325 B

After

Width: 18  |  Height: 18  |  Size: 293 B

BIN
images/smiley-smile.gif

Before

Width: 18  |  Height: 18  |  Size: 345 B

After

Width: 18  |  Height: 18  |  Size: 306 B

BIN
images/smiley-surprised.gif

Before

Width: 18  |  Height: 18  |  Size: 342 B

After

Width: 18  |  Height: 18  |  Size: 303 B

BIN
images/smiley-tongue-out.gif

Before

Width: 18  |  Height: 18  |  Size: 328 B

After

Width: 18  |  Height: 18  |  Size: 290 B

BIN
images/smiley-undecided.gif

Before

Width: 18  |  Height: 18  |  Size: 337 B

After

Width: 18  |  Height: 18  |  Size: 299 B

BIN
images/smiley-whitebeard.png

After

Width: 18  |  Height: 18  |  Size: 1.0 KiB

BIN
images/smiley-wink.gif

Before

Width: 18  |  Height: 18  |  Size: 351 B

After

Width: 18  |  Height: 18  |  Size: 312 B

BIN
images/smiley-yell.gif

Before

Width: 18  |  Height: 18  |  Size: 336 B

After

Width: 18  |  Height: 18  |  Size: 298 B

BIN
images/star.png

After

Width: 16  |  Height: 16  |  Size: 388 B

BIN
images/star_dummy.png

After

Width: 16  |  Height: 16  |  Size: 183 B

5
include/Scrape.php

@ -255,6 +255,11 @@ function scrape_feed($url) {
}
}
}
// perhaps an RSS version 1 feed with a generic or incorrect content-type?
if(stristr($s,'</item>')) {
$ret['feed_rss'] = $url;
return $ret;
}
}
try {

7
include/acl_selectors.php

@ -1,6 +1,11 @@
<?php
/**
*
*/
/**
* @package acl_selectors
*/
function group_select($selname,$selclass,$preselected = false,$size = 4) {
$a = get_app();

230
include/conversation.php

@ -6,11 +6,6 @@
function localize_item(&$item){
$Text = $item['body'];
// find private image (w/data url) if present and convert image
// link to a magic-auth redirect.
$saved_image = '';
$img_start = strpos($Text,'[img]data:');
$img_end = strpos($Text,'[/img]');
@ -184,8 +179,11 @@ function localize_item(&$item){
* that are based on unique features of the calling module.
*
*/
if(!function_exists('conversation')) {
function conversation(&$a, $items, $mode, $update, $preview = false) {
require_once('bbcode.php');
$profile_owner = 0;
@ -221,7 +219,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
if($update)
$return_url = $_SESSION['return_url'];
else
$return_url = $_SESSION['return_url'] = $a->cmd;
$return_url = $_SESSION['return_url'] = $a->query_string;
load_contact_links(local_user());
@ -231,13 +229,13 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$items = $cb['items'];
$cmnt_tpl = get_markup_template('comment_item.tpl');
$tpl = get_markup_template('wall_item.tpl');
$wallwall = get_markup_template('wallwall_item.tpl');
$tpl = 'wall_item.tpl';
$wallwall = 'wallwall_item.tpl';
$hide_comments_tpl = get_markup_template('hide_comments.tpl');
$alike = array();
$dlike = array();
$o = "";
// array with html for each thread (parent+comments)
$threads = array();
@ -250,7 +248,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
// "New Item View" on network page or search page results
// - just loop through the items and format them minimally for display
$tpl = get_markup_template('search_item.tpl');
//$tpl = get_markup_template('search_item.tpl');
$tpl = 'search_item.tpl';
foreach($items as $item) {
$threadsid++;
@ -316,43 +315,46 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$body = prepare_body($item,true);
$tmp_item = replace_macros($tpl,array(
'$id' => (($preview) ? 'P0' : $item['item_id']),
'$linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'$profile_url' => $profile_link,
'$item_photo_menu' => item_photo_menu($item),
'$name' => template_escape($profile_name),
'$sparkle' => $sparkle,
'$lock' => $lock,
'$thumb' => $profile_avatar,
'$title' => template_escape($item['title']),
'$body' => template_escape($body),
'$ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
'$lock' => $lock,
'$location' => template_escape($location),
'$indent' => '',
'$owner_name' => template_escape($owner_name),
'$owner_url' => $owner_url,
'$owner_photo' => $owner_photo,
'$plink' => get_plink($item),
'$edpost' => false,
'$isstarred' => $isstarred,
'$star' => $star,
'$drop' => $drop,
'$vote' => $likebuttons,
'$like' => '',
'$dislike' => '',
'$comment' => '',
'$conv' => (($preview) ? '' : array('href'=> $a->get_baseurl() . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
'$previewing' => $previewing,
'$wait' => t('Please wait'),
));
//$tmp_item = replace_macros($tpl,array(
$tmp_item = array(
'template' => $tpl,
'id' => (($preview) ? 'P0' : $item['item_id']),
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => template_escape($profile_name),
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => $profile_avatar,
'title' => template_escape($item['title']),
'body' => template_escape($body),
'text' => strip_tags(template_escape($body)),
'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
'lock' => $lock,
'location' => template_escape($location),
'indent' => '',
'owner_name' => template_escape($owner_name),
'owner_url' => $owner_url,
'owner_photo' => $owner_photo,
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,
'star' => $star,
'drop' => $drop,
'vote' => $likebuttons,
'like' => '',
'dislike' => '',
'comment' => '',
'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl() . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
'previewing' => $previewing,
'wait' => t('Please wait'),
);
$arr = array('item' => $item, 'output' => $tmp_item);
call_hooks('display_item', $arr);
$threads[$threadsid]['id'] = $item['item_id'];
$threads[$threadsid]['html'] .= $arr['output'];
$threads[$threadsid]['items'] = array($arr['output']);
}
@ -386,6 +388,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
}
$comments_collapsed = false;
$comment_lastcollapsed = false;
$comment_firstcollapsed = false;
$blowhard = 0;
$blowhard_count = 0;
@ -417,39 +421,26 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$toplevelprivate = (($toplevelpost && $item['private']) ? true : false);
$item_writeable = (($item['writable'] || $item['self']) ? true : false);
// DISABLED
/*
if($blowhard == $item['cid'] && (! $item['self']) && ($mode != 'profile') && ($mode != 'notes')) {
$blowhard_count ++;
if($blowhard_count == 3) {
$o .= '<div class="icollapse-wrapper fakelink" id="icollapse-wrapper-' . $item['parent']
. '" onclick="openClose(' . '\'icollapse-' . $item['parent'] . '\'); $(\'#icollapse-wrapper-' . $item['parent'] . '\').hide();" >'
. t('See more posts like this') . '</div>' . '<div class="icollapse" id="icollapse-'
. $item['parent'] . '" style="display: none;" >';
}
}
else {
$blowhard = $item['cid'];
if($blowhard_count >= 3)
$o .= '</div>';
$blowhard_count = 0;
}
// END DISABLED
*/
$comments_seen = 0;
$comments_collapsed = false;
$comment_lastcollapsed = false;
$comment_firstcollapsed = false;
$threadsid++;
$threads[$threadsid]['id'] = $item['item_id'];
$threads[$threadsid]['html'] = "";
$threads[$threadsid]['private'] = $item['private'];
$threads[$threadsid]['items'] = array();
}
else {
// prevent private email from leaking into public conversation
if((! $toplevelpost) && (! $toplevelprivate) && ($item['private']) && ($profile_owner != local_user()))
// prevent private email reply to public conversation from leaking.
if($item['private'] && ! $threads[$threadsid]['private'])
continue;
$comments_seen ++;
$comment_lastcollapsed = false;
$comment_firstcollapsed = false;
}
$override_comment_box = ((($page_writeable) && ($item_writeable)) ? true : false);
@ -457,23 +448,17 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
if(($comments[$item['parent']] > 2) && ($comments_seen <= ($comments[$item['parent']] - 2)) && ($item['gravity'] == 6)) {
if(! $comments_collapsed) {
// IMPORTANT: the closing </div> in the hide_comments template
// is supplied below in code.
$threads[$threadsid]['html'] .= replace_macros($hide_comments_tpl,array(
'$id' => $item['parent'],
'$num_comments' => sprintf( tt('%d comment','%d comments',$comments[$item['parent']]),
$comments[$item['parent']]),
'$display' => 'none',
'$hide_text' => t('show more')
));
if (!$comments_collapsed){
$threads[$threadsid]['num_comments'] = sprintf( tt('%d comment','%d comments',$comments[$item['parent']]),$comments[$item['parent']] );
$threads[$threadsid]['hide_text'] = t('show more');
$comments_collapsed = true;
$comment_firstcollapsed = true;
}
}
if(($comments[$item['parent']] > 2) && ($comments_seen == ($comments[$item['parent']] - 1))) {
$threads[$threadsid]['html'] .= '</div>';
$comment_lastcollapsed = true;
}
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
@ -503,7 +488,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$template = $wallwall;
$commentww = 'ww';
}
if((! $item['wall']) && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) {
if((! $item['wall']) && (strlen($item['owner-link'])) && (! link_compare($item['owner-link'],$item['author-link']))) {
// Could be anybody.
@ -650,63 +635,72 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
// Build the HTML
$body = prepare_body($item,true);
//$tmp_item = replace_macros($template,
$tmp_item = array(
// collapse comments in template. I don't like this much...
'comment_firstcollapsed' => $comment_firstcollapsed,
'comment_lastcollapsed' => $comment_lastcollapsed,
// template to use to render item (wall, walltowall, search)
'template' => $template,
'type' => implode("",array_slice(split("/",$item['verb']),-1)),
'tags' => $tags,
'body' => template_escape($body),
'text' => strip_tags(template_escape($body)),
'id' => $item['item_id'],
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'olinktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])),
'to' => t('to'),
'wall' => t('Wall-to-Wall'),
'vwall' => t('via Wall-To-Wall:'),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => template_escape($profile_name),
'thumb' => $profile_avatar,
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => template_escape($item['title']),
'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
'lock' => $lock,
'location' => template_escape($location),
'indent' => $indent,
'owner_url' => $owner_url,
'owner_photo' => $owner_photo,
'owner_name' => template_escape($owner_name),
'plink' => get_plink($item),
'edpost' => $edpost,
'isstarred' => $isstarred,
'star' => $star,
'drop' => $drop,
'vote' => $likebuttons,
'like' => $like,
'dislike' => $dislike,
'comment' => $comment,
'previewing' => $previewing,
'wait' => t('Please wait'),
$tmp_item = replace_macros($template,array(
'$type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'$tags' => $tags,
'$body' => template_escape($body),
'$id' => $item['item_id'],
'$linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'$olinktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])),
'$to' => t('to'),
'$wall' => t('Wall-to-Wall'),
'$vwall' => t('via Wall-To-Wall:'),
'$profile_url' => $profile_link,
'$item_photo_menu' => item_photo_menu($item),
'$name' => template_escape($profile_name),
'$thumb' => $profile_avatar,
'$osparkle' => $osparkle,
'$sparkle' => $sparkle,
'$title' => template_escape($item['title']),
'$ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
'$lock' => $lock,
'$location' => template_escape($location),
'$indent' => $indent,
'$owner_url' => $owner_url,
'$owner_photo' => $owner_photo,
'$owner_name' => template_escape($owner_name),
'$plink' => get_plink($item),
'$edpost' => $edpost,
'$isstarred' => $isstarred,
'$star' => $star,
'$drop' => $drop,
'$vote' => $likebuttons,
'$like' => $like,
'$dislike' => $dislike,
'$comment' => $comment,
'$previewing' => $previewing,
'$wait' => t('Please wait'),
));
);
$arr = array('item' => $item, 'output' => $tmp_item);
call_hooks('display_item', $arr);
$threads[$threadsid]['html'] .= $arr['output'];
$threads[$threadsid]['items'][] = $arr['output'];
}
}
}
$page_template = get_markup_template("conversation.tpl");
$o .= replace_macros($page_template, array(
'$baseurl' => $a->get_baseurl(),
'$mode' => $mode,
'$user' => $a->user,
'$threads' => $threads,
'$dropping' => ($dropping?t('Delete Selected Items'):False),
));
return $o;
}
}}
function best_link_url($item,&$sparkle) {

36
include/enotify.php

@ -25,6 +25,9 @@ function notification($params) {
$title = $body = '';
}
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
if($params['type'] == NOTIFY_MAIL) {
$subject = sprintf( t('[Friendica:Notify] New mail received at %s'),$sitename);
@ -41,7 +44,32 @@ function notification($params) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$parent_id = $params['parent'];
// if it's a post figure out who's post it is.
$p = null;
if($params['otype'] === 'item' && $parent_id) {
$p = q("select * from item where id = %d and uid = %d limit 1",
intval($parent_id),
intval($params['uid'])
);
}
$possess_desc = str_replace('<!item_type!>',item_post_type($p[0]),$possess_desc);
// "a post"
$dest_str = sprintf($possess_desc,'a');
// "George Bull's post"
if($p)
$dest_str = sprintf($possess_desc,sprintf( t("%s's"),$p[0]['author-name']));
// "your post"
if($p[0]['owner-name'] == $p[0]['author-name'] && $p[0]['wall'])
$dest_str = sprintf($possess_desc, t('your') );
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
// Before this we have the name of the replier on the subject rendering
@ -49,7 +77,7 @@ function notification($params) {
$subject = sprintf( t('[Friendica:Notify] Comment to conversation #%d by %s'), $parent_id, $params['source_name']);
$preamble = sprintf( t('%s commented on an item/conversation you have been following.'), $params['source_name']);
$epreamble = sprintf( t('%s commented in %s.'), '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', '[url=$itemlink]' . t('a watched conversation') . '[/url]');
$epreamble = sprintf( t('%s commented on %s.'), '[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', '[url=$itemlink]' . $dest_str . '[/url]');
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@ -149,6 +177,7 @@ function notification($params) {
$datarray['date'] = datetime_convert();
$datarray['uid'] = $params['uid'];
$datarray['link'] = $itemlink;
$datarray['parent'] = $parent_id;
$datarray['type'] = $params['type'];
$datarray['verb'] = $params['verb'];
$datarray['otype'] = $params['otype'];
@ -157,8 +186,8 @@ function notification($params) {
// create notification entry in DB
$r = q("insert into notify (hash,name,url,photo,date,uid,link,type,verb,otype)
values('%s','%s','%s','%s','%s',%d,'%s',%d,'%s','%s')",
$r = q("insert into notify (hash,name,url,photo,date,uid,link,parent,type,verb,otype)
values('%s','%s','%s','%s','%s',%d,'%s',%d,%d,'%s','%s')",
dbesc($datarray['hash']),
dbesc($datarray['name']),
dbesc($datarray['url']),
@ -166,6 +195,7 @@ function notification($params) {
dbesc($datarray['date']),
intval($datarray['uid']),
dbesc($datarray['link']),
intval($datarray['parent']),
intval($datarray['type']),
dbesc($datarray['verb']),
dbesc($datarray['otype'])

4
include/html2bbcode.php

@ -10,7 +10,7 @@ Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
do {
$done = node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb);
$done = node2bbcodesub($doc, $oldnode, $attributes, $startbb, $endbb);
} while ($done);
}
@ -212,7 +212,7 @@ function html2bbcode($message)
node2bbcode($doc, 'audio', array('src'=>'/(.+)/'), '[audio]$1', '[/audio]');
node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]');
node2bbcode($doc, 'code', array(), '[code]$1', '[/code]');
node2bbcode($doc, 'code', array(), '[code]', '[/code]');
$message = $doc->saveHTML();

108
include/items.php

@ -1598,6 +1598,14 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
// only one like or dislike per person
$r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
intval($datarray['uid']),
intval($datarray['contact-id']),
dbesc($datarray['verb'])
);
if($r && count($r))
continue;
}
if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@ -1750,6 +1758,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$datarray['parent-uri'] = $item_id;
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
if(! link_compare($datarray['owner-link'],$contact['url'])) {
// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
// but otherwise there's a possible data mixup on the sender's system.
// the tgroup delivery code called from item_store will correct it if it's a forum,
// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
logger('local_delivery: Correcting item owner.', LOGGER_DEBUG);
$datarray['owner-name'] = $contact['name'];
$datarray['owner-link'] = $contact['url'];
$datarray['owner-avatar'] = $contact['thumb'];
}
$r = item_store($datarray);
continue;
@ -2139,6 +2159,14 @@ function local_delivery($importer,$data) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
$datarray['last-child'] = 0;
// only one like or dislike per person
$r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
intval($datarray['uid']),
intval($datarray['contact-id']),
dbesc($datarray['verb'])
);
if($r && count($r))
continue;
}
if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@ -2288,6 +2316,15 @@ function local_delivery($importer,$data) {
if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
// only one like or dislike per person
$r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
intval($datarray['uid']),
intval($datarray['contact-id']),
dbesc($datarray['verb'])
);
if($r && count($r))
continue;
}
if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@ -2328,35 +2365,44 @@ function local_delivery($importer,$data) {
if(count($myconv)) {
$importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname'];
foreach($myconv as $conv) {
if(! link_compare($conv['author-link'],$importer_url))
continue;
// first make sure this isn't our own post coming back to us from a wall-to-wall event
if(! link_compare($datarray['author-link'],$importer_url)) {
require_once('include/enotify.php');
$conv_parent = $conv['parent'];
notification(array(
'type' => NOTIFY_COMMENT,
'notify_flags' => $importer['notify-flags'],
'language' => $importer['language'],
'to_name' => $importer['username'],
'to_email' => $importer['email'],
'uid' => $importer['importer_uid'],
'item' => $datarray,
'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id,
'source_name' => stripslashes($datarray['author-name']),
'source_link' => $datarray['author-link'],
'source_photo' => ((link_compare($datarray['author-link'],$importer['url']))
? $importer['thumb'] : $datarray['author-avatar']),
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $conv_parent,
foreach($myconv as $conv) {
));
// now if we find a match, it means we're in this conversation
if(! link_compare($conv['author-link'],$importer_url))
continue;
break;
require_once('include/enotify.php');
$conv_parent = $conv['parent'];
notification(array(
'type' => NOTIFY_COMMENT,
'notify_flags' => $importer['notify-flags'],
'language' => $importer['language'],
'to_name' => $importer['username'],
'to_email' => $importer['email'],
'uid' => $importer['importer_uid'],
'item' => $datarray,
'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id,
'source_name' => stripslashes($datarray['author-name']),
'source_link' => $datarray['author-link'],
'source_photo' => ((link_compare($datarray['author-link'],$importer['url']))
? $importer['thumb'] : $datarray['author-avatar']),
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $conv_parent,
));
// only send one notification
break;
}
}
}
}
@ -2427,12 +2473,24 @@ function local_delivery($importer,$data) {
// This is my contact on another system, but it's really me.
// Turn this into a wall post.
if($contact['remote_self'])
if($importer['remote_self'])
$datarray['wall'] = 1;
$datarray['parent-uri'] = $item_id;
$datarray['uid'] = $importer['importer_uid'];
$datarray['contact-id'] = $importer['id'];
if(! link_compare($datarray['owner-link'],$contact['url'])) {
// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
// but otherwise there's a possible data mixup on the sender's system.
// the tgroup delivery code called from item_store will correct it if it's a forum,
// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
logger('local_delivery: Correcting item owner.', LOGGER_DEBUG);
$datarray['owner-name'] = $importer['senderName'];
$datarray['owner-link'] = $importer['url'];
$datarray['owner-avatar'] = $importer['thumb'];
}
$r = item_store($datarray);
continue;
}

3
include/nav.php

@ -122,6 +122,9 @@ function nav(&$a) {
}
$nav['messages'] = array('message', t('Messages'), "", t('Private mail'));
$nav['messages']['inbox'] = array('message', t('Inbox'), "", t('Inbox'));
$nav['messages']['outbox']= array('message/sent', t('Outbox'), "", t('Outbox'));
$nav['messages']['new'] = array('message/new', t('New Message'), "", t('New Message'));
if(is_array($a->identities) && count($a->identities) > 1) {
$nav['manage'] = array('manage', t('Manage'), "", t('Manage other pages'));

2
include/notifier.php

@ -201,7 +201,7 @@ function notifier_run($argv, $argc){
// by stringing togther an array of retractions and sending them onward.
$localhost = $a->get_hostname();
$localhost = str_replace('www.','',$a->get_hostname());
if(strpos($localhost,':'))
$localhost = substr($localhost,0,strpos($localhost,':'));

86
include/security.php

@ -108,14 +108,18 @@ function can_write_wall(&$a,$owner) {
if(remote_user()) {
// user remembered decision and avoid a DB lookup for each and every display item
// use remembered decision and avoid a DB lookup for each and every display item
// DO NOT use this function if there are going to be multiple owners
// We have a contact-id for an authenticated remote user, this block determines if the contact
// belongs to this page owner, and has the necessary permissions to post content
if($verified === 2)
return true;
elseif($verified === 1)
return false;
else {
$r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` LEFT JOIN `user` on `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `user`.`blockwall` = 0 AND `readonly` = 0 AND ( `contact`.`rel` IN ( %d , %d ) OR `user`.`page-flags` = %d ) LIMIT 1",
@ -125,6 +129,7 @@ function can_write_wall(&$a,$owner) {
intval(CONTACT_IS_FRIEND),
intval(PAGE_COMMUNITY)
);
if(count($r)) {
$verified = 2;
return true;
@ -197,7 +202,7 @@ function permissions_sql($owner_id,$remote_verified = false,$groups = null) {
" AND ( allow_cid = '' OR allow_cid REGEXP '<%d>' )
AND ( deny_cid = '' OR NOT deny_cid REGEXP '<%d>' )
AND ( allow_gid = '' OR allow_gid REGEXP '%s' )
AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s')
AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s')
",
intval($remote_user),
intval($remote_user),
@ -207,4 +212,79 @@ function permissions_sql($owner_id,$remote_verified = false,$groups = null) {
}
}
return $sql;
}
}
function item_permissions_sql($owner_id,$remote_verified = false,$groups = null) {
$local_user = local_user();
$remote_user = remote_user();
/**
* Construct permissions
*
* default permissions - anonymous user
*/
$sql = " AND allow_cid = ''
AND allow_gid = ''
AND deny_cid = ''
AND deny_gid = ''
AND private = 0
";
/**
* Profile owner - everything is visible
*/
if(($local_user) && ($local_user == $owner_id)) {
$sql = '';
}
/**
* Authenticated visitor. Unless pre-verified,
* check that the contact belongs to this $owner_id
* and load the groups the visitor belongs to.
* If pre-verified, the caller is expected to have already
* done this and passed the groups into this function.
*/
elseif($remote_user) {
if(! $remote_verified) {
$r = q("SELECT id FROM contact WHERE id = %d AND uid = %d AND blocked = 0 LIMIT 1",
intval($remote_user),
intval($owner_id)
);
if(count($r)) {
$remote_verified = true;
$groups = init_groups_visitor($remote_user);
}
}
if($remote_verified) {
$gs = '<<>>'; // should be impossible to match
if(is_array($groups) && count($groups)) {
foreach($groups as $g)
$gs .= '|<' . intval($g) . '>';
}
$sql = sprintf(
" AND ( private = 0 OR ( private = 1 AND wall = 1 AND ( allow_cid = '' OR allow_cid REGEXP '<%d>' )
AND ( deny_cid = '' OR NOT deny_cid REGEXP '<%d>' )
AND ( allow_gid = '' OR allow_gid REGEXP '%s' )
AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s')))
",
intval($remote_user),
intval($remote_user),
dbesc($gs),
dbesc($gs)
);
}
}
return $sql;
}

87
include/template_processor.php

@ -1,5 +1,5 @@
<?php
define ("KEY_NOT_EXISTS", '^R_key_not_Exists^');
class Template {
var $r;
@ -28,30 +28,18 @@
die();
}
private function _build_replace($r, $prefix){
if(is_array($r) && count($r)) {
foreach ($r as $k => $v ) {
if (is_array($v)) {
$this->_build_replace($v, "$prefix$k.");
} else {
$this->search[] = $prefix . $k;
$this->replace[] = $v;
}
}
}
}
private function _push_stack(){
$this->stack[] = array($this->r, $this->search, $this->replace, $this->nodes);
$this->stack[] = array($this->r, $this->nodes);
}
private function _pop_stack(){
list($this->r, $this->search, $this->replace, $this->nodes) = array_pop($this->stack);
list($this->r, $this->nodes) = array_pop($this->stack);
}
private function _get_var($name){
$keys = array_map('trim',explode(".",$name));
private function _get_var($name, $retNoKey=false){
$keys = array_map('trim',explode(".",$name));
if ($retNoKey && !array_key_exists($keys[0], $this->r)) return KEY_NOT_EXISTS;
$val = $this->r;
foreach($keys as $k) {
$val = (isset($val[$k]) ? $val[$k] : null);
@ -121,7 +109,15 @@
* {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }}
*/
private function _replcb_inc($args){
list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
if (strpos($args[2],"with")) {
list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
} else {
$tplfile = trim($args[2]);
$newctx = null;
}
if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile);
$this->_push_stack();
$r = $this->r;
if (!is_null($newctx)) {
@ -166,40 +162,33 @@
return $s;
}
/*
private function _str_replace($str){
#$this->search,$this->replace,
$searchs = $this->search;
foreach($searchs as $search){
$search = "|".preg_quote($search)."(\|[a-zA-Z0-9_]*)*|";
$m = array();
if (preg_match_all($search, $str,$m)){
foreach ($m[0] as $match){
$toks = explode("|",$match);
$val = $this->_get_var($toks[0]);
for($k=1; $k<count($toks); $k++){
$func = $toks[$k];
if (function_exists($func)) $val = $func($val);
}
if (count($toks)>1){
$str = str_replace( $match, $val, $str);
}
}
}
private function var_replace($s){
$m = array();
/** regexp:
* \$ literal $
* (\[)? optional open square bracket
* ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional
* dot, repeated at least 1 time
* (?(1)\]) if there was opened square bracket
* (subgrup 1), match close bracket
*/
if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)){
foreach($m[0] as $var){
$varn = str_replace(array("[","]"), array("",""), $var);
$val = $this->_get_var($varn, true);
if ($val!=KEY_NOT_EXISTS)
$s = str_replace($var, $val, $s);
}
}
return str_replace($this->search,$this->replace, $str);
}*/
return $s;
}
public function replace($s, $r) {
$this->r = $r;
$this->search = array();
$this->replace = array();
$this->_build_replace($r, "");
#$s = str_replace(array("\n","\r"),array("§n§","§r§"),$s);
$s = $this->_build_nodes($s);
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
@ -207,12 +196,12 @@
// remove comments block
$s = preg_replace('/{#[^#]*#}/', "" , $s);
// replace strings recursively (limit to 10 loops)
$os = ""; $count=0;
while($os!=$s && $count<10){
$os=$s; $count++;
//$s = $this->_str_replace($s);
$s = str_replace($this->search, $this->replace, $s);
$s = $this->var_replace($s);