mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-10-01 01:36:12 -04:00
* Only sanitize strings when generating RSS feeds and emails (fixes #4003) * clippy * fix test
This commit is contained in:
parent
6d7b38f4de
commit
291ff19718
@ -554,29 +554,3 @@ test("Report a post", async () => {
|
|||||||
expect(betaReport.original_post_body).toBe(alphaReport.original_post_body);
|
expect(betaReport.original_post_body).toBe(alphaReport.original_post_body);
|
||||||
expect(betaReport.reason).toBe(alphaReport.reason);
|
expect(betaReport.reason).toBe(alphaReport.reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Sanitize HTML", async () => {
|
|
||||||
let betaCommunity = (await resolveBetaCommunity(beta)).community;
|
|
||||||
if (!betaCommunity) {
|
|
||||||
throw "Missing beta community";
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = randomString(5);
|
|
||||||
let body = "<script>alert('xss');</script> hello &\"'";
|
|
||||||
let form: CreatePost = {
|
|
||||||
name,
|
|
||||||
body,
|
|
||||||
community_id: betaCommunity.community.id,
|
|
||||||
};
|
|
||||||
let post = await beta.createPost(form);
|
|
||||||
// first escaping for the api
|
|
||||||
expect(post.post_view.post.body).toBe(
|
|
||||||
"<script>alert('xss');</script> hello &"'",
|
|
||||||
);
|
|
||||||
|
|
||||||
let alphaPost = (await resolvePost(alpha, post.post_view.post)).post;
|
|
||||||
// second escaping over federation, avoid double escape of &
|
|
||||||
expect(alphaPost?.post.body).toBe(
|
|
||||||
"<script>alert('xss');</script> hello &"'",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||||||
comment::{CommentReportResponse, CreateCommentReport},
|
comment::{CommentReportResponse, CreateCommentReport},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{check_community_ban, sanitize_html_api, send_new_report_email_to_admins},
|
utils::{check_community_ban, send_new_report_email_to_admins},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -26,7 +26,7 @@ pub async fn create_comment_report(
|
|||||||
) -> Result<Json<CommentReportResponse>, LemmyError> {
|
) -> Result<Json<CommentReportResponse>, LemmyError> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = sanitize_html_api(data.reason.trim());
|
let reason = data.reason.trim().to_string();
|
||||||
check_report_reason(&reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
|||||||
community::{BanFromCommunity, BanFromCommunityResponse},
|
community::{BanFromCommunity, BanFromCommunityResponse},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{is_mod_or_admin, remove_user_data_in_community, sanitize_html_api_opt},
|
utils::{is_mod_or_admin, remove_user_data_in_community},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -81,7 +81,7 @@ pub async fn ban_from_community(
|
|||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_person_id: data.person_id,
|
other_person_id: data.person_id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
reason: sanitize_html_api_opt(&data.reason),
|
reason: data.reason.clone(),
|
||||||
banned: Some(data.ban),
|
banned: Some(data.ban),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||||||
community::{CommunityResponse, HideCommunity},
|
community::{CommunityResponse, HideCommunity},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{is_admin, sanitize_html_api_opt},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -34,7 +34,7 @@ pub async fn hide_community(
|
|||||||
let mod_hide_community_form = ModHideCommunityForm {
|
let mod_hide_community_form = ModHideCommunityForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
reason: sanitize_html_api_opt(&data.reason),
|
reason: data.reason.clone(),
|
||||||
hidden: Some(data.hidden),
|
hidden: Some(data.hidden),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::{BanPerson, BanPersonResponse},
|
person::{BanPerson, BanPersonResponse},
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{is_admin, remove_user_data, sanitize_html_api_opt},
|
utils::{is_admin, remove_user_data},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -61,7 +61,7 @@ pub async fn ban_from_site(
|
|||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: local_user_view.person.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_person_id: data.person_id,
|
other_person_id: data.person_id,
|
||||||
reason: sanitize_html_api_opt(&data.reason),
|
reason: data.reason.clone(),
|
||||||
banned: Some(data.ban),
|
banned: Some(data.ban),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ use actix_web::web::{Data, Json};
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::SaveUserSettings,
|
person::SaveUserSettings,
|
||||||
utils::{sanitize_html_api_opt, send_verification_email},
|
utils::send_verification_email,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
@ -28,13 +28,10 @@ pub async fn save_user_settings(
|
|||||||
) -> Result<Json<SuccessResponse>, LemmyError> {
|
) -> Result<Json<SuccessResponse>, LemmyError> {
|
||||||
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
||||||
|
|
||||||
let bio = sanitize_html_api_opt(&data.bio);
|
|
||||||
let display_name = sanitize_html_api_opt(&data.display_name);
|
|
||||||
|
|
||||||
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
||||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
let bio = diesel_option_overwrite(bio);
|
let bio = diesel_option_overwrite(data.bio.clone());
|
||||||
let display_name = diesel_option_overwrite(display_name);
|
let display_name = diesel_option_overwrite(data.display_name.clone());
|
||||||
let matrix_user_id = diesel_option_overwrite(data.matrix_user_id.clone());
|
let matrix_user_id = diesel_option_overwrite(data.matrix_user_id.clone());
|
||||||
let email_deref = data.email.as_deref().map(str::to_lowercase);
|
let email_deref = data.email.as_deref().map(str::to_lowercase);
|
||||||
let email = diesel_option_overwrite(email_deref.clone());
|
let email = diesel_option_overwrite(email_deref.clone());
|
||||||
@ -82,7 +79,6 @@ pub async fn save_user_settings(
|
|||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
let default_listing_type = data.default_listing_type;
|
let default_listing_type = data.default_listing_type;
|
||||||
let default_sort_type = data.default_sort_type;
|
let default_sort_type = data.default_sort_type;
|
||||||
let theme = sanitize_html_api_opt(&data.theme);
|
|
||||||
|
|
||||||
let person_form = PersonUpdateForm {
|
let person_form = PersonUpdateForm {
|
||||||
display_name,
|
display_name,
|
||||||
@ -114,7 +110,7 @@ pub async fn save_user_settings(
|
|||||||
show_scores: data.show_scores,
|
show_scores: data.show_scores,
|
||||||
default_sort_type,
|
default_sort_type,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
theme,
|
theme: data.theme.clone(),
|
||||||
interface_language: data.interface_language.clone(),
|
interface_language: data.interface_language.clone(),
|
||||||
open_links_in_new_tab: data.open_links_in_new_tab,
|
open_links_in_new_tab: data.open_links_in_new_tab,
|
||||||
infinite_scroll_enabled: data.infinite_scroll_enabled,
|
infinite_scroll_enabled: data.infinite_scroll_enabled,
|
||||||
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
post::{CreatePostReport, PostReportResponse},
|
post::{CreatePostReport, PostReportResponse},
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{check_community_ban, sanitize_html_api, send_new_report_email_to_admins},
|
utils::{check_community_ban, send_new_report_email_to_admins},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -26,7 +26,7 @@ pub async fn create_post_report(
|
|||||||
) -> Result<Json<PostReportResponse>, LemmyError> {
|
) -> Result<Json<PostReportResponse>, LemmyError> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = sanitize_html_api(data.reason.trim());
|
let reason = data.reason.trim().to_string();
|
||||||
check_report_reason(&reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
|
@ -3,7 +3,7 @@ use actix_web::web::{Data, Json};
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
|
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
|
||||||
utils::{sanitize_html_api, send_new_report_email_to_admins},
|
utils::send_new_report_email_to_admins,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -24,7 +24,7 @@ pub async fn create_pm_report(
|
|||||||
) -> Result<Json<PrivateMessageReportResponse>, LemmyError> {
|
) -> Result<Json<PrivateMessageReportResponse>, LemmyError> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let reason = sanitize_html_api(data.reason.trim());
|
let reason = data.reason.trim().to_string();
|
||||||
check_report_reason(&reason, &local_site)?;
|
check_report_reason(&reason, &local_site)?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
@ -35,7 +35,7 @@ pub async fn create_pm_report(
|
|||||||
creator_id: person_id,
|
creator_id: person_id,
|
||||||
private_message_id,
|
private_message_id,
|
||||||
original_pm_text: private_message.content,
|
original_pm_text: private_message.content,
|
||||||
reason: reason.clone(),
|
reason,
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = PrivateMessageReport::report(&mut context.pool(), &report_form)
|
let report = PrivateMessageReport::report(&mut context.pool(), &report_form)
|
||||||
|
@ -2,7 +2,7 @@ use actix_web::web::{Data, Json};
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{PurgeComment, PurgeItemResponse},
|
site::{PurgeComment, PurgeItemResponse},
|
||||||
utils::{is_admin, sanitize_html_api_opt},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -35,10 +35,9 @@ pub async fn purge_comment(
|
|||||||
Comment::delete(&mut context.pool(), comment_id).await?;
|
Comment::delete(&mut context.pool(), comment_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = sanitize_html_api_opt(&data.reason);
|
|
||||||
let form = AdminPurgeCommentForm {
|
let form = AdminPurgeCommentForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason: data.reason.clone(),
|
||||||
post_id,
|
post_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::purge_image_from_pictrs,
|
request::purge_image_from_pictrs,
|
||||||
site::{PurgeCommunity, PurgeItemResponse},
|
site::{PurgeCommunity, PurgeItemResponse},
|
||||||
utils::{is_admin, purge_image_posts_for_community, sanitize_html_api_opt},
|
utils::{is_admin, purge_image_posts_for_community},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -42,10 +42,9 @@ pub async fn purge_community(
|
|||||||
Community::delete(&mut context.pool(), community_id).await?;
|
Community::delete(&mut context.pool(), community_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = sanitize_html_api_opt(&data.reason);
|
|
||||||
let form = AdminPurgeCommunityForm {
|
let form = AdminPurgeCommunityForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason: data.reason.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
AdminPurgeCommunity::create(&mut context.pool(), &form).await?;
|
AdminPurgeCommunity::create(&mut context.pool(), &form).await?;
|
||||||
|
@ -3,7 +3,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::delete_image_from_pictrs,
|
request::delete_image_from_pictrs,
|
||||||
site::{PurgeItemResponse, PurgePerson},
|
site::{PurgeItemResponse, PurgePerson},
|
||||||
utils::{is_admin, sanitize_html_api_opt},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -41,10 +41,9 @@ pub async fn purge_person(
|
|||||||
Person::delete(&mut context.pool(), person_id).await?;
|
Person::delete(&mut context.pool(), person_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = sanitize_html_api_opt(&data.reason);
|
|
||||||
let form = AdminPurgePersonForm {
|
let form = AdminPurgePersonForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason: data.reason.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
AdminPurgePerson::create(&mut context.pool(), &form).await?;
|
AdminPurgePerson::create(&mut context.pool(), &form).await?;
|
||||||
|
@ -3,7 +3,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::purge_image_from_pictrs,
|
request::purge_image_from_pictrs,
|
||||||
site::{PurgeItemResponse, PurgePost},
|
site::{PurgeItemResponse, PurgePost},
|
||||||
utils::{is_admin, sanitize_html_api_opt},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -43,10 +43,9 @@ pub async fn purge_post(
|
|||||||
Post::delete(&mut context.pool(), post_id).await?;
|
Post::delete(&mut context.pool(), post_id).await?;
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let reason = sanitize_html_api_opt(&data.reason);
|
|
||||||
let form = AdminPurgePostForm {
|
let form = AdminPurgePostForm {
|
||||||
admin_person_id: local_user_view.person.id,
|
admin_person_id: local_user_view.person.id,
|
||||||
reason,
|
reason: data.reason.clone(),
|
||||||
community_id,
|
community_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@ use lemmy_db_schema::{
|
|||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
|
use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
|
||||||
use lemmy_db_views_actor::structs::CommunityView;
|
use lemmy_db_views_actor::structs::CommunityView;
|
||||||
use lemmy_utils::{error::LemmyError, utils::mention::MentionData};
|
use lemmy_utils::{
|
||||||
|
error::LemmyError,
|
||||||
|
utils::{markdown::markdown_to_html, mention::MentionData},
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn build_comment_response(
|
pub async fn build_comment_response(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
@ -121,10 +124,11 @@ pub async fn send_local_notifs(
|
|||||||
// Send an email to those local users that have notifications on
|
// Send an email to those local users that have notifications on
|
||||||
if do_send_email {
|
if do_send_email {
|
||||||
let lang = get_interface_language(&mention_user_view);
|
let lang = get_interface_language(&mention_user_view);
|
||||||
|
let content = markdown_to_html(&comment.content);
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&mention_user_view,
|
&mention_user_view,
|
||||||
&lang.notification_mentioned_by_subject(&person.name),
|
&lang.notification_mentioned_by_subject(&person.name),
|
||||||
&lang.notification_mentioned_by_body(&comment.content, &inbox_link, &person.name),
|
&lang.notification_mentioned_by_body(&content, &inbox_link, &person.name),
|
||||||
context.settings(),
|
context.settings(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -164,10 +168,11 @@ pub async fn send_local_notifs(
|
|||||||
|
|
||||||
if do_send_email {
|
if do_send_email {
|
||||||
let lang = get_interface_language(&parent_user_view);
|
let lang = get_interface_language(&parent_user_view);
|
||||||
|
let content = markdown_to_html(&comment.content);
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&parent_user_view,
|
&parent_user_view,
|
||||||
&lang.notification_comment_reply_subject(&person.name),
|
&lang.notification_comment_reply_subject(&person.name),
|
||||||
&lang.notification_comment_reply_body(&comment.content, &inbox_link, &person.name),
|
&lang.notification_comment_reply_body(&content, &inbox_link, &person.name),
|
||||||
context.settings(),
|
context.settings(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -201,10 +206,11 @@ pub async fn send_local_notifs(
|
|||||||
|
|
||||||
if do_send_email {
|
if do_send_email {
|
||||||
let lang = get_interface_language(&parent_user_view);
|
let lang = get_interface_language(&parent_user_view);
|
||||||
|
let content = markdown_to_html(&comment.content);
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&parent_user_view,
|
&parent_user_view,
|
||||||
&lang.notification_post_reply_subject(&person.name),
|
&lang.notification_post_reply_subject(&person.name),
|
||||||
&lang.notification_post_reply_body(&comment.content, &inbox_link, &person.name),
|
&lang.notification_post_reply_body(&content, &inbox_link, &person.name),
|
||||||
context.settings(),
|
context.settings(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -723,37 +723,6 @@ pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError
|
|||||||
Ok(Url::parse(&format!("{community_id}/moderators"))?.into())
|
Ok(Url::parse(&format!("{community_id}/moderators"))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace special HTML characters in API parameters to prevent XSS attacks.
|
|
||||||
///
|
|
||||||
/// Taken from https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md#output-encoding-for-html-contexts
|
|
||||||
///
|
|
||||||
/// `>` is left in place because it is interpreted as markdown quote.
|
|
||||||
pub fn sanitize_html_api(data: &str) -> String {
|
|
||||||
data
|
|
||||||
.replace('&', "&")
|
|
||||||
.replace('<', "<")
|
|
||||||
.replace('\"', """)
|
|
||||||
.replace('\'', "'")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sanitize_html_api_opt(data: &Option<String>) -> Option<String> {
|
|
||||||
data.as_ref().map(|d| sanitize_html_api(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replace special HTML characters in federation parameters to prevent XSS attacks.
|
|
||||||
///
|
|
||||||
/// Unlike [sanitize_html_api()] it leaves `&` in place to avoid double escaping.
|
|
||||||
pub fn sanitize_html_federation(data: &str) -> String {
|
|
||||||
data
|
|
||||||
.replace('<', "<")
|
|
||||||
.replace('\"', """)
|
|
||||||
.replace('\'', "'")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sanitize_html_federation_opt(data: &Option<String>) -> Option<String> {
|
|
||||||
data.as_ref().map(|d| sanitize_html_federation(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_login_cookie(jwt: Sensitive<String>) -> Cookie<'static> {
|
pub fn create_login_cookie(jwt: Sensitive<String>) -> Cookie<'static> {
|
||||||
let mut cookie = Cookie::new(AUTH_COOKIE_NAME, jwt.into_inner());
|
let mut cookie = Cookie::new(AUTH_COOKIE_NAME, jwt.into_inner());
|
||||||
cookie.set_secure(true);
|
cookie.set_secure(true);
|
||||||
|
@ -12,7 +12,6 @@ use lemmy_api_common::{
|
|||||||
generate_local_apub_endpoint,
|
generate_local_apub_endpoint,
|
||||||
get_post,
|
get_post,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
sanitize_html_api,
|
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -52,7 +51,6 @@ pub async fn create_comment(
|
|||||||
&local_site_to_slur_regex(&local_site),
|
&local_site_to_slur_regex(&local_site),
|
||||||
);
|
);
|
||||||
is_valid_body_field(&Some(content.clone()), false)?;
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
let content = sanitize_html_api(&content);
|
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||||||
comment::{CommentResponse, EditComment},
|
comment::{CommentResponse, EditComment},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{check_community_ban, local_site_to_slur_regex, sanitize_html_api_opt},
|
utils::{check_community_ban, local_site_to_slur_regex},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -63,7 +63,6 @@ pub async fn update_comment(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|c| remove_slurs(c, &local_site_to_slur_regex(&local_site)));
|
.map(|c| remove_slurs(c, &local_site_to_slur_regex(&local_site)));
|
||||||
is_valid_body_field(&content, false)?;
|
is_valid_body_field(&content, false)?;
|
||||||
let content = sanitize_html_api_opt(&content);
|
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let form = CommentUpdateForm {
|
let form = CommentUpdateForm {
|
||||||
|
@ -11,8 +11,6 @@ use lemmy_api_common::{
|
|||||||
generate_shared_inbox_url,
|
generate_shared_inbox_url,
|
||||||
is_admin,
|
is_admin,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
sanitize_html_api,
|
|
||||||
sanitize_html_api_opt,
|
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -57,14 +55,10 @@ pub async fn create_community(
|
|||||||
let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
|
let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
|
let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
|
||||||
|
|
||||||
let name = sanitize_html_api(&data.name);
|
|
||||||
let title = sanitize_html_api(&data.title);
|
|
||||||
let description = sanitize_html_api_opt(&data.description);
|
|
||||||
|
|
||||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
check_slurs(&name, &slur_regex)?;
|
check_slurs(&data.name, &slur_regex)?;
|
||||||
check_slurs(&title, &slur_regex)?;
|
check_slurs(&data.title, &slur_regex)?;
|
||||||
check_slurs_opt(&description, &slur_regex)?;
|
check_slurs_opt(&data.description, &slur_regex)?;
|
||||||
|
|
||||||
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
|
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
|
||||||
is_valid_body_field(&data.description, false)?;
|
is_valid_body_field(&data.description, false)?;
|
||||||
@ -85,9 +79,9 @@ pub async fn create_community(
|
|||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
|
|
||||||
let community_form = CommunityInsertForm::builder()
|
let community_form = CommunityInsertForm::builder()
|
||||||
.name(name)
|
.name(data.name.clone())
|
||||||
.title(title)
|
.title(data.title.clone())
|
||||||
.description(description)
|
.description(data.description.clone())
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.banner(banner)
|
.banner(banner)
|
||||||
.nsfw(data.nsfw)
|
.nsfw(data.nsfw)
|
||||||
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||||||
community::{CommunityResponse, EditCommunity},
|
community::{CommunityResponse, EditCommunity},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{local_site_to_slur_regex, sanitize_html_api_opt},
|
utils::local_site_to_slur_regex,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::PersonId,
|
newtypes::PersonId,
|
||||||
@ -37,12 +37,9 @@ pub async fn update_community(
|
|||||||
check_slurs_opt(&data.description, &slur_regex)?;
|
check_slurs_opt(&data.description, &slur_regex)?;
|
||||||
is_valid_body_field(&data.description, false)?;
|
is_valid_body_field(&data.description, false)?;
|
||||||
|
|
||||||
let title = sanitize_html_api_opt(&data.title);
|
|
||||||
let description = sanitize_html_api_opt(&data.description);
|
|
||||||
|
|
||||||
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
let description = diesel_option_overwrite(description);
|
let description = diesel_option_overwrite(data.description.clone());
|
||||||
|
|
||||||
// Verify its a mod (only mods can edit it)
|
// Verify its a mod (only mods can edit it)
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
@ -67,7 +64,7 @@ pub async fn update_community(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let community_form = CommunityUpdateForm {
|
let community_form = CommunityUpdateForm {
|
||||||
title,
|
title: data.title.clone(),
|
||||||
description,
|
description,
|
||||||
icon,
|
icon,
|
||||||
banner,
|
banner,
|
||||||
|
@ -3,7 +3,7 @@ use actix_web::web::Json;
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
||||||
utils::{is_admin, sanitize_html_api},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
||||||
@ -23,15 +23,11 @@ pub async fn create_custom_emoji(
|
|||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let shortcode = sanitize_html_api(data.shortcode.to_lowercase().trim());
|
|
||||||
let alt_text = sanitize_html_api(&data.alt_text);
|
|
||||||
let category = sanitize_html_api(&data.category);
|
|
||||||
|
|
||||||
let emoji_form = CustomEmojiInsertForm::builder()
|
let emoji_form = CustomEmojiInsertForm::builder()
|
||||||
.local_site_id(local_site.id)
|
.local_site_id(local_site.id)
|
||||||
.shortcode(shortcode)
|
.shortcode(data.shortcode.to_lowercase().trim().to_string())
|
||||||
.alt_text(alt_text)
|
.alt_text(data.alt_text.to_string())
|
||||||
.category(category)
|
.category(data.category.to_string())
|
||||||
.image_url(data.clone().image_url.into())
|
.image_url(data.clone().image_url.into())
|
||||||
.build();
|
.build();
|
||||||
let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
|
let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
|
||||||
|
@ -3,7 +3,7 @@ use actix_web::web::Json;
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
||||||
utils::{is_admin, sanitize_html_api},
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
||||||
@ -23,13 +23,10 @@ pub async fn update_custom_emoji(
|
|||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let alt_text = sanitize_html_api(&data.alt_text);
|
|
||||||
let category = sanitize_html_api(&data.category);
|
|
||||||
|
|
||||||
let emoji_form = CustomEmojiUpdateForm::builder()
|
let emoji_form = CustomEmojiUpdateForm::builder()
|
||||||
.local_site_id(local_site.id)
|
.local_site_id(local_site.id)
|
||||||
.alt_text(alt_text)
|
.alt_text(data.alt_text.to_string())
|
||||||
.category(category)
|
.category(data.category.to_string())
|
||||||
.image_url(data.clone().image_url.into())
|
.image_url(data.clone().image_url.into())
|
||||||
.build();
|
.build();
|
||||||
let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
|
let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
|
||||||
|
@ -13,8 +13,6 @@ use lemmy_api_common::{
|
|||||||
honeypot_check,
|
honeypot_check,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
mark_post_as_read,
|
mark_post_as_read,
|
||||||
sanitize_html_api,
|
|
||||||
sanitize_html_api_opt,
|
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -92,11 +90,6 @@ pub async fn create_post(
|
|||||||
.map(|u| (u.title, u.description, u.embed_video_url))
|
.map(|u| (u.title, u.description, u.embed_video_url))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let name = sanitize_html_api(data.name.trim());
|
|
||||||
let body = sanitize_html_api_opt(&data.body);
|
|
||||||
let embed_title = sanitize_html_api_opt(&embed_title);
|
|
||||||
let embed_description = sanitize_html_api_opt(&embed_description);
|
|
||||||
|
|
||||||
// Only need to check if language is allowed in case user set it explicitly. When using default
|
// Only need to check if language is allowed in case user set it explicitly. When using default
|
||||||
// language, it already only returns allowed languages.
|
// language, it already only returns allowed languages.
|
||||||
CommunityLanguage::is_allowed_community_language(
|
CommunityLanguage::is_allowed_community_language(
|
||||||
@ -120,9 +113,9 @@ pub async fn create_post(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let post_form = PostInsertForm::builder()
|
let post_form = PostInsertForm::builder()
|
||||||
.name(name)
|
.name(data.name.trim().to_string())
|
||||||
.url(url)
|
.url(url)
|
||||||
.body(body)
|
.body(data.body.clone())
|
||||||
.community_id(data.community_id)
|
.community_id(data.community_id)
|
||||||
.creator_id(local_user_view.person.id)
|
.creator_id(local_user_view.person.id)
|
||||||
.nsfw(data.nsfw)
|
.nsfw(data.nsfw)
|
||||||
|
@ -6,7 +6,7 @@ use lemmy_api_common::{
|
|||||||
post::{EditPost, PostResponse},
|
post::{EditPost, PostResponse},
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{check_community_ban, local_site_to_slur_regex, sanitize_html_api_opt},
|
utils::{check_community_ban, local_site_to_slur_regex},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -75,12 +75,6 @@ pub async fn update_post(
|
|||||||
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let name = sanitize_html_api_opt(&data.name);
|
|
||||||
let body = sanitize_html_api_opt(&data.body);
|
|
||||||
let body = diesel_option_overwrite(body);
|
|
||||||
let embed_title = embed_title.map(|e| sanitize_html_api_opt(&e));
|
|
||||||
let embed_description = embed_description.map(|e| sanitize_html_api_opt(&e));
|
|
||||||
|
|
||||||
let language_id = data.language_id;
|
let language_id = data.language_id;
|
||||||
CommunityLanguage::is_allowed_community_language(
|
CommunityLanguage::is_allowed_community_language(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
@ -90,9 +84,9 @@ pub async fn update_post(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let post_form = PostUpdateForm {
|
let post_form = PostUpdateForm {
|
||||||
name,
|
name: data.name.clone(),
|
||||||
url,
|
url,
|
||||||
body,
|
body: diesel_option_overwrite(data.body.clone()),
|
||||||
nsfw: data.nsfw,
|
nsfw: data.nsfw,
|
||||||
embed_title,
|
embed_title,
|
||||||
embed_description,
|
embed_description,
|
||||||
|
@ -9,7 +9,6 @@ use lemmy_api_common::{
|
|||||||
generate_local_apub_endpoint,
|
generate_local_apub_endpoint,
|
||||||
get_interface_language,
|
get_interface_language,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
sanitize_html_api,
|
|
||||||
send_email_to_user,
|
send_email_to_user,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
},
|
},
|
||||||
@ -24,7 +23,7 @@ use lemmy_db_schema::{
|
|||||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageView};
|
use lemmy_db_views::structs::{LocalUserView, PrivateMessageView};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyError, LemmyErrorExt, LemmyErrorType},
|
error::{LemmyError, LemmyErrorExt, LemmyErrorType},
|
||||||
utils::{slurs::remove_slurs, validation::is_valid_body_field},
|
utils::{markdown::markdown_to_html, slurs::remove_slurs, validation::is_valid_body_field},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
@ -35,8 +34,7 @@ pub async fn create_private_message(
|
|||||||
) -> Result<Json<PrivateMessageResponse>, LemmyError> {
|
) -> Result<Json<PrivateMessageResponse>, LemmyError> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
let content = sanitize_html_api(&data.content);
|
let content = remove_slurs(&data.content, &local_site_to_slur_regex(&local_site));
|
||||||
let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
|
|
||||||
is_valid_body_field(&Some(content.clone()), false)?;
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
|
|
||||||
check_person_block(
|
check_person_block(
|
||||||
@ -83,6 +81,7 @@ pub async fn create_private_message(
|
|||||||
let lang = get_interface_language(&local_recipient);
|
let lang = get_interface_language(&local_recipient);
|
||||||
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
|
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
|
||||||
let sender_name = &local_user_view.person.name;
|
let sender_name = &local_user_view.person.name;
|
||||||
|
let content = markdown_to_html(&content);
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&local_recipient,
|
&local_recipient,
|
||||||
&lang.notification_private_message_subject(sender_name),
|
&lang.notification_private_message_subject(sender_name),
|
||||||
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
|||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
private_message::{EditPrivateMessage, PrivateMessageResponse},
|
private_message::{EditPrivateMessage, PrivateMessageResponse},
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{local_site_to_slur_regex, sanitize_html_api},
|
utils::local_site_to_slur_regex,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -36,8 +36,7 @@ pub async fn update_private_message(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Doing the update
|
// Doing the update
|
||||||
let content = sanitize_html_api(&data.content);
|
let content = remove_slurs(&data.content, &local_site_to_slur_regex(&local_site));
|
||||||
let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
|
|
||||||
is_valid_body_field(&Some(content.clone()), false)?;
|
is_valid_body_field(&Some(content.clone()), false)?;
|
||||||
|
|
||||||
let private_message_id = data.private_message_id;
|
let private_message_id = data.private_message_id;
|
||||||
|
@ -4,13 +4,7 @@ use actix_web::web::{Data, Json};
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{CreateSite, SiteResponse},
|
site::{CreateSite, SiteResponse},
|
||||||
utils::{
|
utils::{generate_site_inbox_url, is_admin, local_site_rate_limit_to_rate_limit_config},
|
||||||
generate_site_inbox_url,
|
|
||||||
is_admin,
|
|
||||||
local_site_rate_limit_to_rate_limit_config,
|
|
||||||
sanitize_html_api,
|
|
||||||
sanitize_html_api_opt,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::DbUrl,
|
newtypes::DbUrl,
|
||||||
@ -55,14 +49,11 @@ pub async fn create_site(
|
|||||||
let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
|
let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
|
||||||
let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
|
let inbox_url = Some(generate_site_inbox_url(&actor_id)?);
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
let name = sanitize_html_api(&data.name);
|
|
||||||
let sidebar = sanitize_html_api_opt(&data.sidebar);
|
|
||||||
let description = sanitize_html_api_opt(&data.description);
|
|
||||||
|
|
||||||
let site_form = SiteUpdateForm {
|
let site_form = SiteUpdateForm {
|
||||||
name: Some(name),
|
name: Some(data.name.clone()),
|
||||||
sidebar: diesel_option_overwrite(sidebar),
|
sidebar: diesel_option_overwrite(data.sidebar.clone()),
|
||||||
description: diesel_option_overwrite(description),
|
description: diesel_option_overwrite(data.description.clone()),
|
||||||
icon: diesel_option_overwrite_to_url(&data.icon)?,
|
icon: diesel_option_overwrite_to_url(&data.icon)?,
|
||||||
banner: diesel_option_overwrite_to_url(&data.banner)?,
|
banner: diesel_option_overwrite_to_url(&data.banner)?,
|
||||||
actor_id: Some(actor_id),
|
actor_id: Some(actor_id),
|
||||||
@ -77,10 +68,6 @@ pub async fn create_site(
|
|||||||
|
|
||||||
Site::update(&mut context.pool(), site_id, &site_form).await?;
|
Site::update(&mut context.pool(), site_id, &site_form).await?;
|
||||||
|
|
||||||
let application_question = sanitize_html_api_opt(&data.application_question);
|
|
||||||
let default_theme = sanitize_html_api_opt(&data.default_theme);
|
|
||||||
let legal_information = sanitize_html_api_opt(&data.legal_information);
|
|
||||||
|
|
||||||
let local_site_form = LocalSiteUpdateForm {
|
let local_site_form = LocalSiteUpdateForm {
|
||||||
// Set the site setup to true
|
// Set the site setup to true
|
||||||
site_setup: Some(true),
|
site_setup: Some(true),
|
||||||
@ -89,11 +76,11 @@ pub async fn create_site(
|
|||||||
enable_nsfw: data.enable_nsfw,
|
enable_nsfw: data.enable_nsfw,
|
||||||
community_creation_admin_only: data.community_creation_admin_only,
|
community_creation_admin_only: data.community_creation_admin_only,
|
||||||
require_email_verification: data.require_email_verification,
|
require_email_verification: data.require_email_verification,
|
||||||
application_question: diesel_option_overwrite(application_question),
|
application_question: diesel_option_overwrite(data.application_question.clone()),
|
||||||
private_instance: data.private_instance,
|
private_instance: data.private_instance,
|
||||||
default_theme,
|
default_theme: data.default_theme.clone(),
|
||||||
default_post_listing_type: data.default_post_listing_type,
|
default_post_listing_type: data.default_post_listing_type,
|
||||||
legal_information: diesel_option_overwrite(legal_information),
|
legal_information: diesel_option_overwrite(data.legal_information.clone()),
|
||||||
application_email_admins: data.application_email_admins,
|
application_email_admins: data.application_email_admins,
|
||||||
hide_modlog_mod_names: data.hide_modlog_mod_names,
|
hide_modlog_mod_names: data.hide_modlog_mod_names,
|
||||||
updated: Some(Some(naive_now())),
|
updated: Some(Some(naive_now())),
|
||||||
|
@ -3,7 +3,7 @@ use actix_web::web::{Data, Json};
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{EditSite, SiteResponse},
|
site::{EditSite, SiteResponse},
|
||||||
utils::{is_admin, local_site_rate_limit_to_rate_limit_config, sanitize_html_api_opt},
|
utils::{is_admin, local_site_rate_limit_to_rate_limit_config},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -54,14 +54,10 @@ pub async fn update_site(
|
|||||||
SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
|
SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = sanitize_html_api_opt(&data.name);
|
|
||||||
let sidebar = sanitize_html_api_opt(&data.sidebar);
|
|
||||||
let description = sanitize_html_api_opt(&data.description);
|
|
||||||
|
|
||||||
let site_form = SiteUpdateForm {
|
let site_form = SiteUpdateForm {
|
||||||
name,
|
name: data.name.clone(),
|
||||||
sidebar: diesel_option_overwrite(sidebar),
|
sidebar: diesel_option_overwrite(data.sidebar.clone()),
|
||||||
description: diesel_option_overwrite(description),
|
description: diesel_option_overwrite(data.description.clone()),
|
||||||
icon: diesel_option_overwrite_to_url(&data.icon)?,
|
icon: diesel_option_overwrite_to_url(&data.icon)?,
|
||||||
banner: diesel_option_overwrite_to_url(&data.banner)?,
|
banner: diesel_option_overwrite_to_url(&data.banner)?,
|
||||||
updated: Some(Some(naive_now())),
|
updated: Some(Some(naive_now())),
|
||||||
@ -74,21 +70,17 @@ pub async fn update_site(
|
|||||||
// Diesel will throw an error for empty update forms
|
// Diesel will throw an error for empty update forms
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let application_question = sanitize_html_api_opt(&data.application_question);
|
|
||||||
let default_theme = sanitize_html_api_opt(&data.default_theme);
|
|
||||||
let legal_information = sanitize_html_api_opt(&data.legal_information);
|
|
||||||
|
|
||||||
let local_site_form = LocalSiteUpdateForm {
|
let local_site_form = LocalSiteUpdateForm {
|
||||||
enable_downvotes: data.enable_downvotes,
|
enable_downvotes: data.enable_downvotes,
|
||||||
registration_mode: data.registration_mode,
|
registration_mode: data.registration_mode,
|
||||||
enable_nsfw: data.enable_nsfw,
|
enable_nsfw: data.enable_nsfw,
|
||||||
community_creation_admin_only: data.community_creation_admin_only,
|
community_creation_admin_only: data.community_creation_admin_only,
|
||||||
require_email_verification: data.require_email_verification,
|
require_email_verification: data.require_email_verification,
|
||||||
application_question: diesel_option_overwrite(application_question),
|
application_question: diesel_option_overwrite(data.application_question.clone()),
|
||||||
private_instance: data.private_instance,
|
private_instance: data.private_instance,
|
||||||
default_theme,
|
default_theme: data.default_theme.clone(),
|
||||||
default_post_listing_type: data.default_post_listing_type,
|
default_post_listing_type: data.default_post_listing_type,
|
||||||
legal_information: diesel_option_overwrite(legal_information),
|
legal_information: diesel_option_overwrite(data.legal_information.clone()),
|
||||||
application_email_admins: data.application_email_admins,
|
application_email_admins: data.application_email_admins,
|
||||||
hide_modlog_mod_names: data.hide_modlog_mod_names,
|
hide_modlog_mod_names: data.hide_modlog_mod_names,
|
||||||
updated: Some(Some(naive_now())),
|
updated: Some(Some(naive_now())),
|
||||||
|
@ -12,8 +12,6 @@ use lemmy_api_common::{
|
|||||||
honeypot_check,
|
honeypot_check,
|
||||||
local_site_to_slur_regex,
|
local_site_to_slur_regex,
|
||||||
password_length_check,
|
password_length_check,
|
||||||
sanitize_html_api,
|
|
||||||
sanitize_html_api_opt,
|
|
||||||
send_new_applicant_email_to_admins,
|
send_new_applicant_email_to_admins,
|
||||||
send_verification_email,
|
send_verification_email,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
@ -93,12 +91,6 @@ pub async fn register(
|
|||||||
check_slurs(&data.username, &slur_regex)?;
|
check_slurs(&data.username, &slur_regex)?;
|
||||||
check_slurs_opt(&data.answer, &slur_regex)?;
|
check_slurs_opt(&data.answer, &slur_regex)?;
|
||||||
|
|
||||||
if sanitize_html_api(&data.username) != data.username {
|
|
||||||
Err(LemmyErrorType::InvalidName)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let answer = sanitize_html_api_opt(&data.answer);
|
|
||||||
|
|
||||||
let actor_keypair = generate_actor_keypair()?;
|
let actor_keypair = generate_actor_keypair()?;
|
||||||
is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
|
is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
|
||||||
let actor_id = generate_local_apub_endpoint(
|
let actor_id = generate_local_apub_endpoint(
|
||||||
@ -154,7 +146,7 @@ pub async fn register(
|
|||||||
let form = RegistrationApplicationInsertForm {
|
let form = RegistrationApplicationInsertForm {
|
||||||
local_user_id: inserted_local_user.id,
|
local_user_id: inserted_local_user.id,
|
||||||
// We already made sure answer was not null above
|
// We already made sure answer was not null above
|
||||||
answer: answer.expect("must have an answer"),
|
answer: data.answer.clone().expect("must have an answer"),
|
||||||
};
|
};
|
||||||
|
|
||||||
RegistrationApplication::create(&mut context.pool(), &form).await?;
|
RegistrationApplication::create(&mut context.pool(), &form).await?;
|
||||||
|
@ -23,7 +23,7 @@ use anyhow::anyhow;
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{remove_user_data, remove_user_data_in_community, sanitize_html_federation_opt},
|
utils::{remove_user_data, remove_user_data_in_community},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -173,7 +173,7 @@ impl ActivityHandler for BlockUser {
|
|||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
reason: sanitize_html_federation_opt(&self.summary),
|
reason: self.summary,
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
@ -207,7 +207,7 @@ impl ActivityHandler for BlockUser {
|
|||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
reason: sanitize_html_federation_opt(&self.summary),
|
reason: self.summary,
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@ use activitypub_federation::{
|
|||||||
protocol::verification::verify_domains_match,
|
protocol::verification::verify_domains_match,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{ActivityHandler, Actor},
|
||||||
};
|
};
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_federation_opt};
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
@ -118,7 +118,7 @@ impl ActivityHandler for UndoBlockUser {
|
|||||||
let form = ModBanForm {
|
let form = ModBanForm {
|
||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
reason: sanitize_html_federation_opt(&self.object.summary),
|
reason: self.object.summary,
|
||||||
banned: Some(false),
|
banned: Some(false),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
@ -137,7 +137,7 @@ impl ActivityHandler for UndoBlockUser {
|
|||||||
mod_person_id: mod_person.id,
|
mod_person_id: mod_person.id,
|
||||||
other_person_id: blocked_person.id,
|
other_person_id: blocked_person.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
reason: sanitize_html_federation_opt(&self.object.summary),
|
reason: self.object.summary,
|
||||||
banned: Some(false),
|
banned: Some(false),
|
||||||
expires,
|
expires,
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ use activitypub_federation::{
|
|||||||
kinds::activity::FlagType,
|
kinds::activity::FlagType,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{ActivityHandler, Actor},
|
||||||
};
|
};
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_federation};
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
@ -90,7 +90,7 @@ impl ActivityHandler for Report {
|
|||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
original_post_name: post.name.clone(),
|
original_post_name: post.name.clone(),
|
||||||
original_post_url: post.url.clone(),
|
original_post_url: post.url.clone(),
|
||||||
reason: sanitize_html_federation(&self.summary),
|
reason: self.summary.clone(),
|
||||||
original_post_body: post.body.clone(),
|
original_post_body: post.body.clone(),
|
||||||
};
|
};
|
||||||
PostReport::report(&mut context.pool(), &report_form).await?;
|
PostReport::report(&mut context.pool(), &report_form).await?;
|
||||||
@ -100,7 +100,7 @@ impl ActivityHandler for Report {
|
|||||||
creator_id: actor.id,
|
creator_id: actor.id,
|
||||||
comment_id: comment.id,
|
comment_id: comment.id,
|
||||||
original_comment_text: comment.content.clone(),
|
original_comment_text: comment.content.clone(),
|
||||||
reason: sanitize_html_federation(&self.summary),
|
reason: self.summary.clone(),
|
||||||
};
|
};
|
||||||
CommentReport::report(&mut context.pool(), &report_form).await?;
|
CommentReport::report(&mut context.pool(), &report_form).await?;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
|
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
|
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_federation_opt};
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentUpdateForm},
|
||||||
@ -105,8 +105,6 @@ pub(in crate::activities) async fn receive_remove_action(
|
|||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let reason = sanitize_html_federation_opt(&reason);
|
|
||||||
|
|
||||||
match DeletableObjects::read_from_db(object, context).await? {
|
match DeletableObjects::read_from_db(object, context).await? {
|
||||||
DeletableObjects::Community(community) => {
|
DeletableObjects::Community(community) => {
|
||||||
if community.local {
|
if community.local {
|
||||||
|
@ -16,10 +16,7 @@ use activitypub_federation::{
|
|||||||
traits::Object,
|
traits::Object,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
||||||
context::LemmyContext,
|
|
||||||
utils::{local_site_opt_to_slur_regex, sanitize_html_federation},
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentInsertForm, CommentUpdateForm},
|
comment::{Comment, CommentInsertForm, CommentUpdateForm},
|
||||||
@ -162,7 +159,6 @@ impl Object for ApubComment {
|
|||||||
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
||||||
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
||||||
let content = remove_slurs(&content, slur_regex);
|
let content = remove_slurs(&content, slur_regex);
|
||||||
let content = sanitize_html_federation(&content);
|
|
||||||
let language_id =
|
let language_id =
|
||||||
LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?;
|
LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?;
|
||||||
|
|
||||||
|
@ -17,10 +17,7 @@ use activitypub_federation::{
|
|||||||
traits::{Actor, Object},
|
traits::{Actor, Object},
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
||||||
context::LemmyContext,
|
|
||||||
utils::{local_site_opt_to_slur_regex, sanitize_html_federation_opt},
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::InstanceId,
|
newtypes::InstanceId,
|
||||||
source::{
|
source::{
|
||||||
@ -135,8 +132,6 @@ impl Object for ApubSite {
|
|||||||
let instance = DbInstance::read_or_create(&mut data.pool(), domain.to_string()).await?;
|
let instance = DbInstance::read_or_create(&mut data.pool(), domain.to_string()).await?;
|
||||||
|
|
||||||
let sidebar = read_from_string_or_source_opt(&apub.content, &None, &apub.source);
|
let sidebar = read_from_string_or_source_opt(&apub.content, &None, &apub.source);
|
||||||
let sidebar = sanitize_html_federation_opt(&sidebar);
|
|
||||||
let description = sanitize_html_federation_opt(&apub.summary);
|
|
||||||
|
|
||||||
let site_form = SiteInsertForm {
|
let site_form = SiteInsertForm {
|
||||||
name: apub.name.clone(),
|
name: apub.name.clone(),
|
||||||
@ -144,7 +139,7 @@ impl Object for ApubSite {
|
|||||||
updated: apub.updated,
|
updated: apub.updated,
|
||||||
icon: apub.icon.clone().map(|i| i.url.into()),
|
icon: apub.icon.clone().map(|i| i.url.into()),
|
||||||
banner: apub.image.clone().map(|i| i.url.into()),
|
banner: apub.image.clone().map(|i| i.url.into()),
|
||||||
description,
|
description: apub.summary,
|
||||||
actor_id: Some(apub.id.clone().into()),
|
actor_id: Some(apub.id.clone().into()),
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
inbox_url: Some(apub.inbox.clone().into()),
|
inbox_url: Some(apub.inbox.clone().into()),
|
||||||
|
@ -20,12 +20,7 @@ use activitypub_federation::{
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
utils::{
|
utils::{generate_outbox_url, local_site_opt_to_slur_regex},
|
||||||
generate_outbox_url,
|
|
||||||
local_site_opt_to_slur_regex,
|
|
||||||
sanitize_html_federation,
|
|
||||||
sanitize_html_federation_opt,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
@ -150,17 +145,14 @@ impl Object for ApubPerson {
|
|||||||
) -> Result<ApubPerson, LemmyError> {
|
) -> Result<ApubPerson, LemmyError> {
|
||||||
let instance_id = fetch_instance_actor_for_object(&person.id, context).await?;
|
let instance_id = fetch_instance_actor_for_object(&person.id, context).await?;
|
||||||
|
|
||||||
let name = sanitize_html_federation(&person.preferred_username);
|
|
||||||
let display_name = sanitize_html_federation_opt(&person.name);
|
|
||||||
let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source);
|
let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source);
|
||||||
let bio = sanitize_html_federation_opt(&bio);
|
|
||||||
|
|
||||||
// Some Mastodon users have `name: ""` (empty string), need to convert that to `None`
|
// Some Mastodon users have `name: ""` (empty string), need to convert that to `None`
|
||||||
// https://github.com/mastodon/mastodon/issues/25233
|
// https://github.com/mastodon/mastodon/issues/25233
|
||||||
let display_name = display_name.filter(|n| !n.is_empty());
|
let display_name = person.name.filter(|n| !n.is_empty());
|
||||||
|
|
||||||
let person_form = PersonInsertForm {
|
let person_form = PersonInsertForm {
|
||||||
name,
|
name: person.preferred_username,
|
||||||
display_name,
|
display_name,
|
||||||
banned: None,
|
banned: None,
|
||||||
ban_expires: None,
|
ban_expires: None,
|
||||||
@ -275,7 +267,7 @@ pub(crate) mod tests {
|
|||||||
assert_eq!(person.name, "lanodan");
|
assert_eq!(person.name, "lanodan");
|
||||||
assert!(!person.local);
|
assert!(!person.local);
|
||||||
assert_eq!(context.request_count(), 0);
|
assert_eq!(context.request_count(), 0);
|
||||||
assert_eq!(person.bio.as_ref().unwrap().len(), 878);
|
assert_eq!(person.bio.as_ref().unwrap().len(), 873);
|
||||||
|
|
||||||
cleanup((person, site), &context).await;
|
cleanup((person, site), &context).await;
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,7 @@ use html2md::parse_html;
|
|||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{
|
utils::{is_mod_or_admin, local_site_opt_to_sensitive, local_site_opt_to_slur_regex},
|
||||||
is_mod_or_admin,
|
|
||||||
local_site_opt_to_sensitive,
|
|
||||||
local_site_opt_to_slur_regex,
|
|
||||||
sanitize_html_federation,
|
|
||||||
sanitize_html_federation_opt,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
self,
|
self,
|
||||||
@ -231,17 +225,11 @@ impl Object for ApubPost {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
||||||
|
|
||||||
let body_slurs_removed =
|
let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source)
|
||||||
read_from_string_or_source_opt(&page.content, &page.media_type, &page.source)
|
|
||||||
.map(|s| remove_slurs(&s, slur_regex));
|
.map(|s| remove_slurs(&s, slur_regex));
|
||||||
let language_id =
|
let language_id =
|
||||||
LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;
|
LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;
|
||||||
|
|
||||||
let name = sanitize_html_federation(&name);
|
|
||||||
let body = sanitize_html_federation_opt(&body_slurs_removed);
|
|
||||||
let embed_title = sanitize_html_federation_opt(&embed_title);
|
|
||||||
let embed_description = sanitize_html_federation_opt(&embed_description);
|
|
||||||
|
|
||||||
PostInsertForm {
|
PostInsertForm {
|
||||||
name,
|
name,
|
||||||
url: url.map(Into::into),
|
url: url.map(Into::into),
|
||||||
|
@ -12,10 +12,7 @@ use activitypub_federation::{
|
|||||||
traits::Object,
|
traits::Object,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, utils::check_person_block};
|
||||||
context::LemmyContext,
|
|
||||||
utils::{check_person_block, sanitize_html_federation},
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
person::Person,
|
person::Person,
|
||||||
@ -125,7 +122,6 @@ impl Object for ApubPrivateMessage {
|
|||||||
check_person_block(creator.id, recipient.id, &mut context.pool()).await?;
|
check_person_block(creator.id, recipient.id, &mut context.pool()).await?;
|
||||||
|
|
||||||
let content = read_from_string_or_source(¬e.content, &None, ¬e.source);
|
let content = read_from_string_or_source(¬e.content, &None, ¬e.source);
|
||||||
let content = sanitize_html_federation(&content);
|
|
||||||
|
|
||||||
let form = PrivateMessageInsertForm {
|
let form = PrivateMessageInsertForm {
|
||||||
creator_id: creator.id,
|
creator_id: creator.id,
|
||||||
|
@ -23,10 +23,7 @@ use activitypub_federation::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, utils::local_site_opt_to_slur_regex};
|
||||||
context::LemmyContext,
|
|
||||||
utils::{local_site_opt_to_slur_regex, sanitize_html_federation, sanitize_html_federation_opt},
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::InstanceId,
|
newtypes::InstanceId,
|
||||||
source::community::{CommunityInsertForm, CommunityUpdateForm},
|
source::community::{CommunityInsertForm, CommunityUpdateForm},
|
||||||
@ -97,14 +94,11 @@ impl Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_insert_form(self, instance_id: InstanceId) -> CommunityInsertForm {
|
pub(crate) fn into_insert_form(self, instance_id: InstanceId) -> CommunityInsertForm {
|
||||||
let name = sanitize_html_federation(&self.preferred_username);
|
|
||||||
let title = sanitize_html_federation(&self.name.unwrap_or(self.preferred_username));
|
|
||||||
let description = read_from_string_or_source_opt(&self.summary, &None, &self.source);
|
let description = read_from_string_or_source_opt(&self.summary, &None, &self.source);
|
||||||
let description = sanitize_html_federation_opt(&description);
|
|
||||||
|
|
||||||
CommunityInsertForm {
|
CommunityInsertForm {
|
||||||
name,
|
name: self.preferred_username.clone(),
|
||||||
title,
|
title: self.name.unwrap_or(self.preferred_username.clone()),
|
||||||
description,
|
description,
|
||||||
removed: None,
|
removed: None,
|
||||||
published: self.published,
|
published: self.published,
|
||||||
|
@ -22,7 +22,7 @@ use lemmy_db_views_actor::{
|
|||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
cache_header::cache_1hour,
|
cache_header::cache_1hour,
|
||||||
error::LemmyError,
|
error::LemmyError,
|
||||||
utils::markdown::markdown_to_html,
|
utils::markdown::{markdown_to_html, sanitize_html},
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rss::{
|
use rss::{
|
||||||
@ -289,7 +289,7 @@ async fn get_feed_community(
|
|||||||
.items(items);
|
.items(items);
|
||||||
|
|
||||||
if let Some(community_desc) = community.description {
|
if let Some(community_desc) = community.description {
|
||||||
channel_builder.description(&community_desc);
|
channel_builder.description(markdown_to_html(&community_desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(channel_builder)
|
Ok(channel_builder)
|
||||||
@ -328,7 +328,7 @@ async fn get_feed_front(
|
|||||||
.items(items);
|
.items(items);
|
||||||
|
|
||||||
if let Some(site_desc) = site_view.site.description {
|
if let Some(site_desc) = site_view.site.description {
|
||||||
channel_builder.description(&site_desc);
|
channel_builder.description(markdown_to_html(&site_desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(channel_builder)
|
Ok(channel_builder)
|
||||||
@ -457,7 +457,7 @@ fn create_post_items(
|
|||||||
let mut i = ItemBuilder::default();
|
let mut i = ItemBuilder::default();
|
||||||
let mut dc_extension = DublinCoreExtensionBuilder::default();
|
let mut dc_extension = DublinCoreExtensionBuilder::default();
|
||||||
|
|
||||||
i.title(p.post.name);
|
i.title(sanitize_html(&p.post.name));
|
||||||
|
|
||||||
dc_extension.creators(vec![p.creator.actor_id.to_string()]);
|
dc_extension.creators(vec![p.creator.actor_id.to_string()]);
|
||||||
|
|
||||||
@ -472,14 +472,18 @@ fn create_post_items(
|
|||||||
.build();
|
.build();
|
||||||
i.guid(guid);
|
i.guid(guid);
|
||||||
|
|
||||||
let community_url = format!("{}/c/{}", protocol_and_hostname, p.community.name);
|
let community_url = format!(
|
||||||
|
"{}/c/{}",
|
||||||
|
protocol_and_hostname,
|
||||||
|
sanitize_html(&p.community.name)
|
||||||
|
);
|
||||||
|
|
||||||
// TODO add images
|
// TODO add images
|
||||||
let mut description = format!("submitted by <a href=\"{}\">{}</a> to <a href=\"{}\">{}</a><br>{} points | <a href=\"{}\">{} comments</a>",
|
let mut description = format!("submitted by <a href=\"{}\">{}</a> to <a href=\"{}\">{}</a><br>{} points | <a href=\"{}\">{} comments</a>",
|
||||||
p.creator.actor_id,
|
p.creator.actor_id,
|
||||||
p.creator.name,
|
sanitize_html(&p.creator.name),
|
||||||
community_url,
|
community_url,
|
||||||
p.community.name,
|
sanitize_html(&p.community.name),
|
||||||
p.counts.score,
|
p.counts.score,
|
||||||
post_url,
|
post_url,
|
||||||
p.counts.comments);
|
p.counts.comments);
|
||||||
|
@ -12,6 +12,20 @@ static MARKDOWN_PARSER: Lazy<MarkdownIt> = Lazy::new(|| {
|
|||||||
parser
|
parser
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Replace special HTML characters in API parameters to prevent XSS attacks.
|
||||||
|
///
|
||||||
|
/// Taken from https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md#output-encoding-for-html-contexts
|
||||||
|
///
|
||||||
|
/// `>` is left in place because it is interpreted as markdown quote.
|
||||||
|
pub fn sanitize_html(text: &str) -> String {
|
||||||
|
text
|
||||||
|
.replace('&', "&")
|
||||||
|
.replace('<', "<")
|
||||||
|
.replace('\"', """)
|
||||||
|
.replace('\'', "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts text from markdown to HTML, while escaping special characters.
|
||||||
pub fn markdown_to_html(text: &str) -> String {
|
pub fn markdown_to_html(text: &str) -> String {
|
||||||
MARKDOWN_PARSER.parse(text).xrender()
|
MARKDOWN_PARSER.parse(text).xrender()
|
||||||
}
|
}
|
||||||
@ -21,7 +35,7 @@ mod tests {
|
|||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
#![allow(clippy::indexing_slicing)]
|
#![allow(clippy::indexing_slicing)]
|
||||||
|
|
||||||
use crate::utils::markdown::markdown_to_html;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_markdown() {
|
fn test_basic_markdown() {
|
||||||
@ -71,6 +85,11 @@ mod tests {
|
|||||||
"::: spoiler click to see more\nhow spicy!\n:::\n",
|
"::: spoiler click to see more\nhow spicy!\n:::\n",
|
||||||
"<details><summary>click to see more</summary><p>how spicy!\n</p></details>\n"
|
"<details><summary>click to see more</summary><p>how spicy!\n</p></details>\n"
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"escape html special chars",
|
||||||
|
"<script>alert('xss');</script> hello &\"",
|
||||||
|
"<p><script>alert(‘xss’);</script> hello &"</p>\n"
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
tests.iter().for_each(|&(msg, input, expected)| {
|
tests.iter().for_each(|&(msg, input, expected)| {
|
||||||
@ -83,4 +102,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sanitize_html() {
|
||||||
|
let sanitized = sanitize_html("<script>alert('xss');</script> hello &\"'");
|
||||||
|
let expected = "<script>alert('xss');</script> hello &"'";
|
||||||
|
assert_eq!(expected, sanitized)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 18da10858d8c63750beb06247947f25d91944741
|
Subproject commit e943f97fe481dc425acdebc8872bf1fdcabaf875
|
Loading…
Reference in New Issue
Block a user