Reupload №4

This commit is contained in:
lalka2016 2023-08-16 20:58:51 +03:00
parent c2b6db1b8a
commit 08b30b445d
24 changed files with 338 additions and 25 deletions

View file

@ -67,6 +67,21 @@ class Album extends MediaCollection
return $this->has($photo);
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted()) {
return false;
}
$owner = $this->getOwner();
if(get_class($owner) == "openvk\\Web\\Models\\Entities\\User") {
return $owner->canBeViewedBy($user) && $owner->getPrivacyPermission('photos.read', $user);
} else {
return $owner->canBeViewedBy($user);
}
}
function toVkApiStruct(?User $user = NULL, bool $need_covers = false, bool $photo_sizes = false): object
{
$res = (object) [];

View file

@ -367,6 +367,11 @@ class Club extends RowModel
$this->save();
}
function canBeViewedBy(?User $user = NULL)
{
return is_null($this->getBanReason());
}
function getAlert(): ?string
{
return $this->getRecord()->alert;

View file

@ -90,4 +90,13 @@ class Comment extends Post
{
return "/wall" . $this->getTarget()->getPrettyId() . "#_comment" . $this->getId();
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getTarget()->isDeleted()) {
return false;
}
return $this->getTarget()->canBeViewedBy($user);
}
}

View file

@ -118,6 +118,15 @@ class Note extends Postable
{
return $this->getRecord()->source;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
return $this->getOwner()->getPrivacyPermission('notes.read', $user) && $this->getOwner()->canBeViewedBy($user);
}
function toVkApiStruct(): object
{

View file

@ -328,6 +328,19 @@ class Photo extends Media
return $res;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
if(!is_null($this->getAlbum())) {
return $this->getAlbum()->canBeViewedBy($user);
} else {
return $this->getOwner()->canBeViewedBy($user);
}
}
static function fastMake(int $owner, string $description = "", array $file, ?Album $album = NULL, bool $anon = false): Photo
{

View file

@ -278,6 +278,17 @@ class Poll extends Attachable
return $poll;
}
function canBeViewedBy(?User $user = NULL): bool
{
# waiting for #935 :(
/*if(!is_null($this->getAttachedPost())) {
return $this->getAttachedPost()->canBeViewedBy($user);
} else {*/
return true;
#}
}
function save(): void
{

View file

@ -245,6 +245,15 @@ class Post extends Postable
$this->unwire();
$this->save();
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted()) {
return false;
}
return $this->getWallOwner()->canBeViewedBy($user);
}
use Traits\TRichText;
}

View file

@ -4,6 +4,16 @@ use openvk\Web\Models\Entities\User;
trait TOwnable
{
function canBeViewedBy(?User $user = NULL): bool
{
# TODO: #950
if($this->isDeleted()) {
return false;
}
return true;
}
function canBeModifiedBy(User $user): bool
{
if(method_exists($this, "isCreatedBySystem"))

View file

@ -1221,7 +1221,54 @@ class User extends RowModel
return $response;
}
function toVkApiStruct(): object
function getProfileType(): int
{
# 0 — открытый профиль, 1 — закрытый
return $this->getRecord()->profile_type;
}
function canBeViewedBy(?User $user = NULL): bool
{
if(!is_null($user)) {
if($this->getId() == $user->getId()) {
return true;
}
if($user->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)) {
return true;
}
if($this->getProfileType() == 0) {
return true;
} else {
if($user->getSubscriptionStatus($this) == User::SUBSCRIPTION_MUTUAL) {
return true;
} else {
return false;
}
}
} else {
if($this->getProfileType() == 0) {
if($this->getPrivacySetting("page.read") == 3) {
return true;
} else {
return false;
}
} else {
return false;
}
}
return true;
}
function isClosed()
{
return (bool) $this->getProfileType();
}
function toVkApiStruct(?User $user = NULL): object
{
$res = (object) [];
@ -1235,6 +1282,12 @@ class User extends RowModel
$res->photo_id = !is_null($this->getAvatarPhoto()) ? $this->getAvatarPhoto()->getPrettyId() : NULL;
# TODO: Perenesti syuda vsyo ostalnoyie
$res->is_closed = $this->isClosed();
if(!is_null($user)) {
$res->can_access_closed = (bool)$this->canBeViewedBy($user);
}
return $res;
}

View file

@ -219,4 +219,18 @@ class Video extends Media
return $video;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
if(get_class($this->getOwner()) == "openvk\\Web\\Models\\Entities\\User") {
return $this->getOwner()->canBeViewedBy($user) && $this->getOwner()->getPrivacyPermission('videos.read', $user);
} else {
# Groups doesn't have videos but ok
return $this->getOwner()->canBeViewedBy($user);
}
}
}

View file

@ -128,6 +128,9 @@ class Users
case "doNotSearchMe":
$result->where("id !=", $paramValue);
break;
case "doNotSearchPrivate":
$result->where("profile_type", 0);
break;
}
}
}

View file

@ -43,6 +43,10 @@ final class CommentPresenter extends OpenVKPresenter
$entity = $repo->get($eId);
if(!$entity) $this->notFound();
if(!$entity->canBeViewedBy($this->user->identity)) {
$this->flashFail("err", tr("error"), tr("forbidden"));
}
if($entity instanceof Topic && $entity->isClosed())
$this->notFound();

View file

@ -20,9 +20,12 @@ final class GiftsPresenter extends OpenVKPresenter
$this->assertUserLoggedIn();
$user = $this->users->get($user);
if(!$user)
if(!$user || $user->isDeleted())
$this->notFound();
if(!$user->canBeViewedBy($this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->user = $user;
$this->template->page = $page = (int) ($this->queryParam("p") ?? 1);
$this->template->count = $user->getGiftCount();
@ -50,7 +53,10 @@ final class GiftsPresenter extends OpenVKPresenter
$cat = $this->gifts->getCat((int) ($this->queryParam("pack") ?? 0));
if(!$user || !$cat)
$this->flashFail("err", "Не удалось подарить", "Пользователь или набор не существуют.");
if(!$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->page = $page = (int) ($this->queryParam("p") ?? 1);
$gifts = $cat->getGifts($page, null, $this->template->count);
@ -71,6 +77,9 @@ final class GiftsPresenter extends OpenVKPresenter
if(!$gift->canUse($this->user->identity))
$this->flashFail("err", "Не удалось подарить", "У вас больше не осталось таких подарков.");
if(!$user->canBeViewedBy($this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$coinsLeft = $this->user->identity->getCoins() - $gift->getPrice();
if($coinsLeft < 0)
$this->flashFail("err", "Не удалось подарить", "Ору нищ не пук.");

View file

@ -19,7 +19,7 @@ final class NotesPresenter extends OpenVKPresenter
{
$user = (new Users)->get($owner);
if(!$user) $this->notFound();
if(!$user->getPrivacyPermission('notes.read', $this->user->identity ?? NULL))
if(!$user->getPrivacyPermission('notes.read', $this->user->identity ?? NULL) || !$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->notes = $this->notes->getUserNotes($user, (int)($this->queryParam("p") ?? 1));
@ -40,6 +40,8 @@ final class NotesPresenter extends OpenVKPresenter
$this->notFound();
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if(!$note->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->cCount = $note->getCommentsCount();
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);

View file

@ -25,7 +25,7 @@ final class PhotosPresenter extends OpenVKPresenter
if($owner > 0) {
$user = $this->users->get($owner);
if(!$user) $this->notFound();
if (!$user->getPrivacyPermission('photos.read', $this->user->identity ?? NULL))
if (!$user->getPrivacyPermission('photos.read', $this->user->identity ?? NULL) || !$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->albums = $this->albums->getUserAlbums($user, $this->queryParam("p") ?? 1);
$this->template->count = $this->albums->getUserAlbumsCount($user);
@ -136,6 +136,9 @@ final class PhotosPresenter extends OpenVKPresenter
if(!$album) $this->notFound();
if($album->getPrettyId() !== $owner . "_" . $id || $album->isDeleted())
$this->notFound();
if(!$album->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if($owner > 0 /* bc we currently don't have perms for clubs */) {
$ownerObject = (new Users)->get($owner);
@ -158,7 +161,8 @@ final class PhotosPresenter extends OpenVKPresenter
{
$photo = $this->photos->getByOwnerAndVID($ownerId, $photoId);
if(!$photo || $photo->isDeleted()) $this->notFound();
if(!$photo->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if(!is_null($this->queryParam("from"))) {
if(preg_match("%^album([0-9]++)$%", $this->queryParam("from"), $matches) === 1) {
$album = $this->albums->get((int) $matches[1]);

View file

@ -86,7 +86,8 @@ final class SearchPresenter extends OpenVKPresenter
"hometown" => $this->queryParam("hometown") != "" ? $this->queryParam("hometown") : NULL,
"before" => $this->queryParam("datebefore") != "" ? strtotime($this->queryParam("datebefore")) : NULL,
"after" => $this->queryParam("dateafter") != "" ? strtotime($this->queryParam("dateafter")) : NULL,
"gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL
"gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL,
"doNotSearchPrivate" => true,
];
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");

View file

@ -29,10 +29,14 @@ final class UserPresenter extends OpenVKPresenter
function renderView(int $id): void
{
$user = $this->users->get($id);
if(!$user || $user->isDeleted()) {
if(!$user || $user->isDeleted() || !$user->canBeViewedBy($this->user->identity)) {
if(!is_null($user) && $user->isDeactivated()) {
$this->template->_template = "User/deactivated.xml";
$this->template->user = $user;
} else if(!$user->canBeViewedBy($this->user->identity)) {
$this->template->_template = "User/private.xml";
$this->template->user = $user;
} else {
$this->template->_template = "User/deleted.xml";
@ -58,7 +62,7 @@ final class UserPresenter extends OpenVKPresenter
$page = abs($this->queryParam("p") ?? 1);
if(!$user)
$this->notFound();
elseif (!$user->getPrivacyPermission('friends.read', $this->user->identity ?? NULL))
elseif (!$user->getPrivacyPermission('friends.read', $this->user->identity ?? NULL) || !$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
else
$this->template->user = $user;
@ -86,7 +90,7 @@ final class UserPresenter extends OpenVKPresenter
$user = $this->users->get($id);
if(!$user)
$this->notFound();
elseif (!$user->getPrivacyPermission('groups.read', $this->user->identity ?? NULL))
elseif (!$user->getPrivacyPermission('groups.read', $this->user->identity ?? NULL) || !$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
else {
if($this->queryParam("act") === "managed" && $this->user->id !== $user->getId())
@ -435,6 +439,11 @@ final class UserPresenter extends OpenVKPresenter
$input = $this->postParam(str_replace(".", "_", $setting));
$user->setPrivacySetting($setting, min(3, abs($input ?? $user->getPrivacySetting($setting))));
}
$prof = $this->postParam("profile_type") == 1 || $this->postParam("profile_type") == 0 ? (int)$this->postParam("profile_type") : 0;
$user->setProfile_type($prof);
$user->save();
} else if($_GET['act'] === "finance.top-up") {
$token = $this->postParam("key0") . $this->postParam("key1") . $this->postParam("key2") . $this->postParam("key3");
$voucher = (new Vouchers)->getByToken($token);

View file

@ -22,7 +22,7 @@ final class VideosPresenter extends OpenVKPresenter
{
$user = $this->users->get($id);
if(!$user) $this->notFound();
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL))
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL) || !$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->user = $user;
@ -40,9 +40,10 @@ final class VideosPresenter extends OpenVKPresenter
{
$user = $this->users->get($owner);
if(!$user) $this->notFound();
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL))
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL) || !$video->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$video = $this->videos->getByOwnerAndVID($owner, $vId);
if($this->videos->getByOwnerAndVID($owner, $vId)->isDeleted()) $this->notFound();
$this->template->user = $user;

View file

@ -46,7 +46,7 @@ final class WallPresenter extends OpenVKPresenter
function renderWall(int $user, bool $embedded = false): void
{
$owner = ($user < 0 ? (new Clubs) : (new Users))->get(abs($user));
if ($owner->isBanned())
if ($owner->isBanned() || !$owner->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("error"), tr("forbidden"));
if(is_null($this->user)) {
@ -93,7 +93,7 @@ final class WallPresenter extends OpenVKPresenter
if(is_null($this->user)) {
$canPost = false;
} else if($user > 0) {
if(!$owner->isBanned())
if(!$owner->isBanned() && $owner->canBeViewedBy($this->user->identity))
$canPost = $owner->getPrivacyPermission("wall.write", $this->user->identity);
else
$this->flashFail("err", tr("error"), tr("forbidden"));
@ -169,7 +169,8 @@ final class WallPresenter extends OpenVKPresenter
$page = (int) ($_GET["p"] ?? 1);
$pPage = min((int) ($_GET["posts"] ?? OPENVK_DEFAULT_PER_PAGE), 50);
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0";
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) LEFT JOIN `profiles` ON LEAST(`posts`.`wall`, 0) = 0 AND `profiles`.`id` = ABS(`posts`.`wall`)";
$queryBase .= "WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND (`profiles`.`profile_type` = 0 OR `profiles`.`first_name` IS NULL) AND `posts`.`deleted` = 0"; # AND `posts`.`suggested` = 0
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
$queryBase .= " AND `nsfw` = 0";
@ -215,7 +216,7 @@ final class WallPresenter extends OpenVKPresenter
$wallOwner = ($wall > 0 ? (new Users)->get($wall) : (new Clubs)->get($wall * -1))
?? $this->flashFail("err", tr("failed_to_publish_post"), tr("error_4"));
if ($wallOwner->isBanned())
if ($wallOwner->isBanned() || !$wallOwner->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("error"), tr("forbidden"));
if($wall > 0) {
@ -345,22 +346,25 @@ final class WallPresenter extends OpenVKPresenter
$post = $this->posts->getPostById($wall, $post_id);
if(!$post || $post->isDeleted())
$this->notFound();
if(!$post->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("error"), tr("forbidden"));
$this->logPostView($post, $wall);
$this->template->post = $post;
if ($post->getTargetWall() > 0) {
$this->template->wallOwner = (new Users)->get($post->getTargetWall());
$this->template->isWallOfGroup = false;
$this->template->wallOwner = (new Users)->get($post->getTargetWall());
$this->template->isWallOfGroup = false;
if($this->template->wallOwner->isBanned())
$this->flashFail("err", tr("error"), tr("forbidden"));
} else {
$this->template->wallOwner = (new Clubs)->get(abs($post->getTargetWall()));
$this->template->isWallOfGroup = true;
} else {
$this->template->wallOwner = (new Clubs)->get(abs($post->getTargetWall()));
$this->template->isWallOfGroup = true;
if ($this->template->wallOwner->isBanned())
$this->flashFail("err", tr("error"), tr("forbidden"));
}
}
$this->template->cCount = $post->getCommentsCount();
$this->template->cPage = (int) ($_GET["p"] ?? 1);
$this->template->comments = iterator_to_array($post->getComments($this->template->cPage));

View file

@ -266,8 +266,6 @@
<select name="page.read" style="width: 164px;">
<option value="3" {if $user->getPrivacySetting('page.read') == 3}selected{/if}>{_privacy_value_anybody_dative}</option>
<option value="2" {if $user->getPrivacySetting('page.read') == 2}selected{/if}>{_privacy_value_users}</option>
<option value="1" {if $user->getPrivacySetting('page.read') == 1}selected{/if}>{_privacy_value_friends_dative}</option>
<option value="0" {if $user->getPrivacySetting('page.read') == 0}selected{/if}>{_privacy_value_only_me_dative}</option>
</select>
</td>
</tr>
@ -384,6 +382,17 @@
</select>
</td>
</tr>
<tr>
<td width="120" valign="top">
<span class="nobold">{_profile_type}</span>
</td>
<td>
<select name="profile_type", style="width: 164px;">
<option value="0" {if $user->getProfileType() == 0}selected{/if}>{_profile_type_open}</option>
<option value="1" {if $user->getProfileType() == 1}selected{/if}>{_profile_type_closed}</option>
</select>
</td>
</tr>
<tr>
<td>

View file

@ -0,0 +1,96 @@
{extends "../@layout.xml"}
{block title}{$user->getCanonicalName()}{/block}
{block header}
{$user->getCanonicalName()}
<img n:if="$user->isVerified()"
class="name-checkmark"
src="/assets/packages/static/openvk/img/checkmark.png"
/>
{/block}
{block content}
<div class="left_small_block">
<div>
<img src="{$user->getAvatarUrl('normal')}"
alt="{$user->getCanonicalName()}"
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
</div>
<div id="profile_links">
<a style="width: 194px;" n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_send_message}</a>
{var $subStatus = $user->getSubscriptionStatus($thisUser)}
{if $subStatus === 0}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_add}" style="width: 194px;" />
</form>
{elseif $subStatus === 1}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_accept}" style="width: 194px;" />
</form>
{elseif $subStatus === 2}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="rem" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_reject}" style="width: 194px;" />
</form>
{/if}
<a class="profile_link" style="display:block;width:96%;" href="javascript:reportUser()">{_report}</a>
<script>
function reportUser() {
uReportMsgTxt = "Вы собираетесь пожаловаться на данного пользователя.";
uReportMsgTxt += "<br/>Что именно вам кажется недопустимым в этом материале?";
uReportMsgTxt += "<br/><br/><b>Причина жалобы</b>: <input type='text' id='uReportMsgInput' placeholder='Причина' />"
MessageBox("Пожаловаться?", uReportMsgTxt, ["Подтвердить", "Отмена"], [
(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + {$user->getId()} + "?reason=" + res + "&type=user", true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("reason") === -1)
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
else
MessageBox("Операция успешна", "Скоро её рассмотрят модераторы", ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
</script>
</div>
</div>
<div class="right_big_block">
<div class="page_info">
<div class="accountInfo clearFix">
<div class="profileName">
<h2>{$user->getFullName()}</h2>
<div class="page_status" style="color: #AAA;">{_closed_page}</div>
</div>
</div>
<div class="msg msg_yellow" style="width: 93%;margin-top: 10px;">
{var $m = $user->isFemale() ? "f" : "m"}
{tr("limited_access_to_page_$m", $user->getFirstName())}
{if isset($thisUser)}
{if $subStatus != 2}
<br /><br />
{_you_can_add}
<a href="javascript:addToFriends.submit()">{tr("add_to_friends_$m")}</a>
{/if}
{else}
<br /><br />
{tr("register_to_access_page_$m")}
{/if}
</div>
</div>
</div>
{/block}

View file

@ -1002,6 +1002,11 @@ table.User {
background-color: #f5e9ec;
}
.msg.msg_yellow {
border-color:#D4BC4C;
background-color:#F9F6E7;
}
.edit_link {
color: #c5c5c5;
font-family: verdana, arial, sans-serif;

View file

@ -0,0 +1 @@
ALTER TABLE `profiles` ADD `profile_type` TINYINT(1) NOT NULL DEFAULT '0' AFTER `client_name`;

View file

@ -132,6 +132,20 @@
"updated_at" = "Обновлено $1";
"user_banned" = "К сожалению, нам пришлось заблокировать страницу пользователя <b>$1</b>.";
"user_banned_comment" = "Комментарий модератора:";
"closed_page" = "Закрытая страница";
"limited_access_to_page_m" = "$1 ограничил доступ к своей странице.";
"limited_access_to_page_f" = "$1 ограничила доступ к своей странице.";
"you_can_add" = "Вы можете";
"add_to_friends_m" = "добавить его в друзья.";
"add_to_friends_f" = "добавить её в друзья.";
"register_to_access_page_m" = "Зарегистрируйтесь, чтобы получить доступ к его странице.";
"register_to_access_page_f" = "Зарегистрируйтесь, чтобы получить доступ к её странице.";
"private_profile_warning" = "Этот профиль закрытый, но вы имеете к нему доступ, потому что вы — администратор.";
"private_profile_warning_desc" = "Пожалуйста, уважайте право на личную жизнь и не злоупотребляйте этой возможностью.";
/* Wall */
@ -500,6 +514,9 @@
"privacy_value_only_me" = "Только я";
"privacy_value_only_me_dative" = "Только мне";
"privacy_value_nobody" = "Никто";
"profile_type" = "Тип профиля";
"profile_type_open" = "Открытый";
"profile_type_closed" = "Закрытый";
"your_email_address" = "Адрес Вашей электронной почты";
"your_page_address" = "Адрес Вашей страницы";
"page_address" = "Адрес страницы";