$bestname = $profile->getBestName();
$sitename = common_config('site', 'name');
$personal = $this->trimmed('personal');
+ $language = $this->trimmed('language');
$addresses = explode("\n", $this->trimmed('addresses'));
foreach ($addresses as $email) {
} catch (NoSuchUserException $e) {
// If email was not known, let's send an invite!
$this->sent[] = $email;
- $this->sendInvitation($email, $user, $personal);
+ $this->sendInvitation($email, $user, $personal, $language);
}
}
}
}
- function sendInvitation($email, $user, $personal)
+ function sendInvitation($email, $user, $personal, $language)
{
$profile = $user->getProfile();
$bestname = $profile->getBestName();
$title = (empty($personal)) ? 'invite' : 'invitepersonal';
// @todo FIXME: i18n issue.
- $inviteTemplate = DocFile::forTitle($title, DocFile::mailPaths());
+ $inviteTemplate = DocFile::forTitle($title, DocFile::mailPaths(), $language);
$body = $inviteTemplate->toHTML(array('inviter' => $bestname,
'inviterurl' => $profile->profileurl,
// TRANS: Client error when page not found (404)
$this->clientError(_('No such page.'), 404);
}
-<<<<<<< HEAD
-
- return true;
- }
-
- /**
- * Handle a request
- *
- * Just show the page. All args already handled.
- *
- * @param array $args $_REQUEST data
- *
- * @return void
- */
- function handle(array $args=array())
- {
- parent::handle($args);
- $this->showPage();
-=======
->>>>>>> 1442ca16b410d327d7ec6269944144dfa075ff17
}
/**
throw new ClientException(_('You cannot repeat your own notice.'));
}
- if ($repeat->scope != Notice::SITE_SCOPE &&
- $repeat->scope != Notice::PUBLIC_SCOPE) {
+ if ($repeat->isPrivateScope()) {
// TRANS: Client error displayed when trying to repeat a non-public notice.
throw new ClientException(_('Cannot repeat a private notice.'), 403);
}
*/
public function getTags()
{
+ // Check default scope (non-private notices)
+ $inScope = (!$this->isPrivateScope());
+
+ // Get current user
+ $user = common_current_user();
+
+ // Is the general scope check okay and the user in logged in?
+ /* NOISY-DEBUG: */ common_debug('[' . __METHOD__ . ':' . __LINE__ . ']: inScope=' . intval($inScope) . ',user[]=' . gettype($user));
+ if (($inScope === TRUE) && ($user instanceof User)) {
+ // Get profile from it
+ $profile = $user->getProfile();
+ /* NOISY-DEBUG: */ common_debug('[' . __METHOD__ . ':' . __LINE__ . ']: inScope=' . intval($inScope) . ',profile[]=' . gettype($profile));
+
+ /*
+ * Check scope, else a privacy leaks happens this way:
+ *
+ * 1) Bob and Alice follow each other and write private notices
+ * (this->scope=2) to each other.
+ * 2) Bob uses tags in his private notice to alice (which she can
+ * read from him).
+ * 3) Alice adds that notice (with tags) to her favorites
+ * ("faving") it.
+ * 4) The tags from Bob's private notice becomes visible in Alice's
+ * profile.
+ *
+ * This has the simple background that the scope is not being
+ * re-checked. This has to be done here at this point because given
+ * above scenario is a privacy leak as the tags may be *really*
+ * private (nobody else shall see them) such as initmate words or
+ * very political words.
+ */
+ $inScope = $this->inScope($profile);
+ /* NOISY-DEBUG: */ common_debug('[' . __METHOD__ . ':' . __LINE__ . ']: inScope=' . intval($inScope) . ' - After inScope() has been called.');
+ }
+
$tags = array();
$keypart = sprintf('notice:tags:%d', $this->id);
} else {
$tag = new Notice_tag();
$tag->notice_id = $this->id;
- if ($tag->find()) {
+
+ // Check scope for privacy-leak protection (see some lines above why)
+ if (($inScope === TRUE) && ($tag->find())) {
while ($tag->fetch()) {
$tags[] = $tag->tag;
}
$notice->_setRepeats($repeats);
}
}
+
+ /**
+ * Checks whether this notice is in "private scope" (non-public notice)
+ *
+ * @return $isPrivate Whether this notice is private
+ */
+ public function isPrivateScope ()
+ {
+ return ($this->scope != Notice::SITE_SCOPE &&
+ $this->scope != Notice::PUBLIC_SCOPE);
+ }
}
public $selfLink; // <link rel='self' type='application/atom+xml'>
public $editLink; // <link rel='edit' type='application/atom+xml'>
public $generator; // ActivityObject representing the generating application
+
/**
* Turns a regular old Atom <entry> into a magical activity
*
$this->filename = $filename;
}
- static function forTitle($title, $paths)
+ static function forTitle($title, array $paths, $language=null)
{
- if (!is_array($paths)) {
- $paths = array($paths);
- }
-
$filename = null;
if (Event::handle('StartDocFileForTitle', array($title, &$paths, &$filename))) {
}
if (!empty($lang) || !empty($def)) {
- $filename = self::negotiateLanguage($lang, $def);
+ $filename = self::negotiateLanguage($lang, $def, $language);
break;
}
}
}
}
- function toHTML(array $args=null)
+ function toHTML(array $args=array())
{
- if (is_null($args)) {
- $args = array();
- }
-
if (empty($this->contents)) {
$this->contents = file_get_contents($this->filename);
}
INSTALLDIR.'/doc-src/');
$site = GNUsocial::currentSite();
-
+
if (!empty($site)) {
array_unshift($paths, INSTALLDIR.'/local/doc-src/'.$site.'/');
}
INSTALLDIR.'/mail-src/');
$site = GNUsocial::currentSite();
-
+
if (!empty($site)) {
array_unshift($paths, INSTALLDIR.'/local/mail-src/'.$site.'/');
}
return $paths;
}
- static function negotiateLanguage($filenames, $defaultFilename=null)
+ private static function negotiateLanguage(array $filenames, $defaultFilename=null, $language = null)
{
- // XXX: do this better
-
+ // Default is current language
$langcode = common_language();
+ // Is a language set?
+ if (!empty($language)) {
+ // And is it valid?
+ if (common_valid_language($language)) {
+ // Use this as language (e.g. from form)
+ $langcode = strval($language);
+ }
+ }
+
foreach ($filenames as $filename) {
if (preg_match('/\.'.$langcode.'$/', $filename)) {
return $filename;
define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE);
-define('GNUSOCIAL_CODENAME', 'Not decided yet');
+define('GNUSOCIAL_CODENAME', 'Only a fixed bug is a good bug.');
define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48);
function formData()
{
$this->out->elementStart('ul', 'form_data');
+
$this->out->elementStart('li');
$this->out->textarea(
'addresses',
_('Addresses of friends to invite (one per line).')
);
$this->out->elementEnd('li');
+
$this->out->elementStart('li');
$this->out->textarea(
// TRANS: Field label for a personal message to send to invitees.
_('Optionally add a personal message to the invitation.')
);
$this->out->elementEnd('li');
+
+ $language = common_language();
+
+ $this->out->elementStart('li');
+ $this->out->dropdown('language', _('Language'),
+ // TRANS: Tooltip for dropdown list label in form for profile settings.
+ get_nice_language_list(), _('Preferred language.'),
+ false, $language);
+ $this->out->elementEnd('li');
+
$this->out->elementEnd('ul');
}
// TRANS: H2 text for user statistics.
$this->element('h2', null, _('Statistics'));
- $profile = $this->target;
- $actionParams = array('nickname' => $profile->nickname);
+ $actionParams = array('nickname' => $this->target->nickname);
$stats = array(
array(
'id' => 'user-id',
// TRANS: Label for user statistics.
'label' => _('User ID'),
- 'value' => $profile->id,
+ 'value' => $this->target->id,
),
array(
'id' => 'member-since',
// TRANS: Label for user statistics.
'label' => _('Member since'),
- 'value' => date('j M Y', strtotime($profile->created))
+ 'value' => date('j M Y', strtotime($this->target->created))
),
array(
'id' => 'notices',
);
// Give plugins a chance to add stats entries
- Event::handle('ProfileStats', array($profile, &$stats));
+ Event::handle('ProfileStats', array($this->target, &$stats));
foreach ($stats as $row) {
$this->showStatsRow($row);
$dir = dirname(__FILE__);
// @todo FIXME: i18n issue.
- $docFile = DocFile::forTitle($title, $dir.'/doc-src/');
+ $docFile = DocFile::forTitle($title, array($dir . '/doc-src/'));
if (!empty($docFile)) {
$output = $docFile->toHTML();
mail_send($recipients, $headers, $body);
}
- function onEndDocFileForTitle($title, $paths, &$filename)
+ function onEndDocFileForTitle($title, array $paths, &$filename)
{
if ($title == 'confirmemailreg' && empty($filename)) {
$filename = dirname(__FILE__).'/mail-src/'.$title;
return true;
}
- function onEndDocFileForTitle($title, $paths, &$filename)
+ function onEndDocFileForTitle($title, array $paths, &$filename)
{
if (empty($filename)) {
$filename = dirname(__FILE__) . '/mail-src/' . $title;
* Send a real live email reminder
*
* @todo This would probably be better as two or more sep functions
+ * @todo Add language support?
*
* @param string $type type of reminder
* @param mixed $object Confirm_address or Invitation object
*
* @return array Array of Fave objects
*/
- static public function byNotice($notice)
+ static public function byNotice(Notice $notice)
{
if (!isset(self::$_faves[$notice->id])) {
self::fillFaves(array($notice->id));
* @param array $stats
* @return boolean hook return value
*/
- function onProfileStats($profile, &$stats)
+ function onProfileStats(Profile $profile, array &$stats)
{
$cur = common_current_user();
if (!empty($cur) && $cur->id == $profile->id) {