Merge branch 'main' into glitch-soc/merge-upstream
This commit is contained in:
		
							
								
								
									
										5
									
								
								.github/workflows/build-image.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/build-image.yml
									
									
									
									
										vendored
									
									
								
							@@ -13,9 +13,6 @@ on:
 | 
			
		||||
jobs:
 | 
			
		||||
  build-image:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        os: [linux/arm64, linux/amd64]
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      - uses: docker/setup-qemu-action@v1
 | 
			
		||||
@@ -39,7 +36,7 @@ jobs:
 | 
			
		||||
      - uses: docker/build-push-action@v2
 | 
			
		||||
        with:
 | 
			
		||||
          context: .
 | 
			
		||||
          platforms: ${{ matrix.os }}
 | 
			
		||||
          platforms: linux/amd64,linux/arm64
 | 
			
		||||
          push: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
          tags: ${{ steps.meta.outputs.tags }}
 | 
			
		||||
          cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/mastodon:latest
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ Changelog
 | 
			
		||||
 | 
			
		||||
All notable changes to this project will be documented in this file.
 | 
			
		||||
 | 
			
		||||
## Unreleased
 | 
			
		||||
## [3.5.0] - 2022-03-30
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- **Add support for incoming edited posts** ([Gargron](https://github.com/mastodon/mastodon/pull/16697), [Gargron](https://github.com/mastodon/mastodon/pull/17727), [Gargron](https://github.com/mastodon/mastodon/pull/17728), [Gargron](https://github.com/mastodon/mastodon/pull/17320), [Gargron](https://github.com/mastodon/mastodon/pull/17404), [Gargron](https://github.com/mastodon/mastodon/pull/17390), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17335), [Gargron](https://github.com/mastodon/mastodon/pull/17696), [Gargron](https://github.com/mastodon/mastodon/pull/17745), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17740), [Gargron](https://github.com/mastodon/mastodon/pull/17697), [Gargron](https://github.com/mastodon/mastodon/pull/17648), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17531), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17499), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17498), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17380), [Gargron](https://github.com/mastodon/mastodon/pull/17373), [Gargron](https://github.com/mastodon/mastodon/pull/17334), [Gargron](https://github.com/mastodon/mastodon/pull/17333), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17699), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17748))
 | 
			
		||||
@@ -197,6 +197,11 @@ All notable changes to this project will be documented in this file.
 | 
			
		||||
- Fix hashtag autocomplete overriding user-typed case ([weex](https://github.com/mastodon/mastodon/pull/16460))
 | 
			
		||||
- Fix WebAuthn authentication setup to not prompt for PIN ([truongnmt](https://github.com/mastodon/mastodon/pull/16545))
 | 
			
		||||
 | 
			
		||||
### Security
 | 
			
		||||
 | 
			
		||||
- Fix being able to post URLs longer than 4096 characters ([Gargron](https://github.com/mastodon/mastodon/pull/17908))
 | 
			
		||||
- Fix being able to bypass e-mail restrictions ([Gargron](https://github.com/mastodon/mastodon/pull/17909))
 | 
			
		||||
 | 
			
		||||
## [3.4.6] - 2022-02-03
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Extractor
 | 
			
		||||
  MAX_DOMAIN_LENGTH = 253
 | 
			
		||||
 | 
			
		||||
  extend Twitter::TwitterText::Extractor
 | 
			
		||||
 | 
			
		||||
  module_function
 | 
			
		||||
@@ -30,6 +32,10 @@ module Extractor
 | 
			
		||||
      after      = $'
 | 
			
		||||
 | 
			
		||||
      unless Twitter::TwitterText::Regex[:end_mention_match].match?(after)
 | 
			
		||||
        _, domain = screen_name.split('@')
 | 
			
		||||
 | 
			
		||||
        next if domain.present? && domain.length > MAX_DOMAIN_LENGTH
 | 
			
		||||
 | 
			
		||||
        start_position = match_data.char_begin(1) - 1
 | 
			
		||||
        end_position   = match_data.char_end(1)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -91,11 +91,11 @@ class User < ApplicationRecord
 | 
			
		||||
  validates :invite_request, presence: true, on: :create, if: :invite_text_required?
 | 
			
		||||
 | 
			
		||||
  validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale?
 | 
			
		||||
  validates_with BlacklistedEmailValidator, on: :create
 | 
			
		||||
  validates_with BlacklistedEmailValidator, if: -> { !confirmed? }
 | 
			
		||||
  validates_with EmailMxValidator, if: :validate_email_dns?
 | 
			
		||||
  validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create
 | 
			
		||||
 | 
			
		||||
  # Those are honeypot/antispam fields
 | 
			
		||||
  # Honeypot/anti-spam fields
 | 
			
		||||
  attr_accessor :registration_form_time, :website, :confirm_password
 | 
			
		||||
 | 
			
		||||
  validates_with RegistrationFormTimeValidator, on: :create
 | 
			
		||||
 
 | 
			
		||||
@@ -3,35 +3,57 @@
 | 
			
		||||
class StatusLengthValidator < ActiveModel::Validator
 | 
			
		||||
  MAX_CHARS = (ENV['MAX_TOOT_CHARS'] || 500).to_i
 | 
			
		||||
  URL_PLACEHOLDER_CHARS = 23
 | 
			
		||||
  URL_PLACEHOLDER = "\1#{'x' * URL_PLACEHOLDER_CHARS}"
 | 
			
		||||
  URL_PLACEHOLDER = 'x' * 23
 | 
			
		||||
 | 
			
		||||
  def validate(status)
 | 
			
		||||
    return unless status.local? && !status.reblog?
 | 
			
		||||
 | 
			
		||||
    @status = status
 | 
			
		||||
    status.errors.add(:text, I18n.t('statuses.over_character_limit', max: MAX_CHARS)) if too_long?
 | 
			
		||||
    status.errors.add(:text, I18n.t('statuses.over_character_limit', max: MAX_CHARS)) if too_long?(status)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def too_long?
 | 
			
		||||
    countable_length > MAX_CHARS
 | 
			
		||||
  def too_long?(status)
 | 
			
		||||
    countable_length(combined_text(status)) > MAX_CHARS
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def countable_length
 | 
			
		||||
    total_text.mb_chars.grapheme_length
 | 
			
		||||
  def countable_length(str)
 | 
			
		||||
    str.mb_chars.grapheme_length
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def total_text
 | 
			
		||||
    [@status.spoiler_text, countable_text].join
 | 
			
		||||
  def combined_text(status)
 | 
			
		||||
    [status.spoiler_text, countable_text(status.text)].join
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def countable_text
 | 
			
		||||
    return '' if @status.text.nil?
 | 
			
		||||
  def countable_text(str)
 | 
			
		||||
    return '' if str.blank?
 | 
			
		||||
 | 
			
		||||
    @status.text.dup.tap do |new_text|
 | 
			
		||||
      new_text.gsub!(FetchLinkCardService::URL_PATTERN, URL_PLACEHOLDER)
 | 
			
		||||
      new_text.gsub!(Account::MENTION_RE, '@\2')
 | 
			
		||||
    # To ensure that we only give length concessions to entities that
 | 
			
		||||
    # will be correctly parsed during formatting, we go through full
 | 
			
		||||
    # entity extraction
 | 
			
		||||
 | 
			
		||||
    entities = Extractor.remove_overlapping_entities(Extractor.extract_urls_with_indices(str, extract_url_without_protocol: false) + Extractor.extract_mentions_or_lists_with_indices(str))
 | 
			
		||||
 | 
			
		||||
    rewrite_entities(str, entities) do |entity|
 | 
			
		||||
      if entity[:url]
 | 
			
		||||
        URL_PLACEHOLDER
 | 
			
		||||
      elsif entity[:screen_name]
 | 
			
		||||
        "@#{entity[:screen_name].split('@').first}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def rewrite_entities(str, entities)
 | 
			
		||||
    entities.sort_by! { |entity| entity[:indices].first }
 | 
			
		||||
    result = ''.dup
 | 
			
		||||
 | 
			
		||||
    last_index = entities.reduce(0) do |index, entity|
 | 
			
		||||
      result << str[index...entity[:indices].first]
 | 
			
		||||
      result << yield(entity)
 | 
			
		||||
      entity[:indices].last
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result << str[last_index..-1]
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ module Mastodon
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def flags
 | 
			
		||||
      'rc3'
 | 
			
		||||
      ''
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def suffix
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,13 @@ describe StatusLengthValidator do
 | 
			
		||||
      expect(status.errors).to have_received(:add)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not count overly long URLs as 23 characters flat' do
 | 
			
		||||
      text = "http://example.com/valid?#{'#foo?' * 1000}"
 | 
			
		||||
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
 | 
			
		||||
      subject.validate(status)
 | 
			
		||||
      expect(status.errors).to have_received(:add)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'counts only the front part of remote usernames' do
 | 
			
		||||
      username = '@alice'
 | 
			
		||||
      chars = StatusLengthValidator::MAX_CHARS - 1 - username.length
 | 
			
		||||
@@ -64,5 +71,13 @@ describe StatusLengthValidator do
 | 
			
		||||
      subject.validate(status)
 | 
			
		||||
      expect(status.errors).to_not have_received(:add)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does count both parts of remote usernames for overly long domains' do
 | 
			
		||||
      text   = "@alice@#{'b' * 500}.com"
 | 
			
		||||
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
 | 
			
		||||
 | 
			
		||||
      subject.validate(status)
 | 
			
		||||
      expect(status.errors).to have_received(:add)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user