Commit 76c643a7 authored by Markus Koller's avatar Markus Koller

Limit length of wiki file/directory names

Many common file systems have a limit of 255 bytes for file and
directory names, and while Git and GitLab both support paths exceeding
those limits, the presence of them makes it impossible for users on
those file systems to checkout a wiki repository locally.

To avoid this situation, we enforce these limits when editing pages
through the GitLab web interface and API:

- 245 bytes for page titles (reserving 10 bytes for the file extension)
- 255 bytes for directory names
parent c07163c7
...@@ -5,6 +5,9 @@ class WikiPage ...@@ -5,6 +5,9 @@ class WikiPage
PageChangedError = Class.new(StandardError) PageChangedError = Class.new(StandardError)
PageRenameError = Class.new(StandardError) PageRenameError = Class.new(StandardError)
MAX_TITLE_BYTES = 245
MAX_DIRECTORY_BYTES = 255
include ActiveModel::Validations include ActiveModel::Validations
include ActiveModel::Conversion include ActiveModel::Conversion
include StaticModel include StaticModel
...@@ -51,6 +54,7 @@ class WikiPage ...@@ -51,6 +54,7 @@ class WikiPage
validates :title, presence: true validates :title, presence: true
validates :content, presence: true validates :content, presence: true
validate :validate_path_limits, if: :title_changed?
# The GitLab ProjectWiki instance. # The GitLab ProjectWiki instance.
attr_reader :wiki attr_reader :wiki
...@@ -262,7 +266,7 @@ class WikiPage ...@@ -262,7 +266,7 @@ class WikiPage
end end
def title_changed? def title_changed?
title.present? && self.class.unhyphenize(@page.url_path) != title title.present? && (@page.nil? || self.class.unhyphenize(@page.url_path) != title)
end end
# Updates the current @attributes hash by merging a hash of params # Updates the current @attributes hash by merging a hash of params
...@@ -324,4 +328,16 @@ class WikiPage ...@@ -324,4 +328,16 @@ class WikiPage
set_attributes set_attributes
@persisted = errors.blank? @persisted = errors.blank?
end end
def validate_path_limits
*dirnames, title = @attributes[:title].split('/')
if title.bytesize > MAX_TITLE_BYTES
errors.add(:title, _("exceeds the limit of %{bytes} bytes for page titles") % { bytes: MAX_TITLE_BYTES })
end
if dirnames.any? { |d| d.bytesize > MAX_DIRECTORY_BYTES }
errors.add(:title, _("exceeds the limit of %{bytes} bytes for directory names") % { bytes: MAX_DIRECTORY_BYTES })
end
end
end end
...@@ -17,9 +17,13 @@ ...@@ -17,9 +17,13 @@
= icon('lightbulb-o') = icon('lightbulb-o')
- if @page.persisted? - if @page.persisted?
= s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.") = s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.")
= link_to icon('question-circle'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'), target: '_blank' = link_to icon('question-circle'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'),
target: '_blank', rel: 'noopener noreferrer'
- else - else
= s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.") = s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.")
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/project/wiki/index', anchor: 'creating-a-new-wiki-page'),
target: '_blank', rel: 'noopener noreferrer'
.form-group.row .form-group.row
.col-sm-12= f.label :format, class: 'control-label-full-width' .col-sm-12= f.label :format, class: 'control-label-full-width'
.col-sm-12 .col-sm-12
......
---
title: Limit length of wiki file/directory names
merge_request: 24364
author:
type: changed
...@@ -119,3 +119,7 @@ This limit can be configured for self hosted installations when [enabling ...@@ -119,3 +119,7 @@ This limit can be configured for self hosted installations when [enabling
Elasticsearch](../integration/elasticsearch.md#enabling-elasticsearch). Elasticsearch](../integration/elasticsearch.md#enabling-elasticsearch).
NOTE: **Note:** Set the limit to `0` to disable it. NOTE: **Note:** Set the limit to `0` to disable it.
## Wiki limits
- [Length restrictions for file and directory names](../user/project/wiki/index.md#length-restrictions-for-file-and-directory-names).
...@@ -50,6 +50,8 @@ When you're ready, click the **Create page** and the new page will be created. ...@@ -50,6 +50,8 @@ When you're ready, click the **Create page** and the new page will be created.
![New page](img/wiki_create_new_page.png) ![New page](img/wiki_create_new_page.png)
### Attachment storage
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/33475) in GitLab 11.3. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/33475) in GitLab 11.3.
Starting with GitLab 11.3, any file that is uploaded to the wiki via GitLab's Starting with GitLab 11.3, any file that is uploaded to the wiki via GitLab's
...@@ -58,6 +60,22 @@ if you clone the wiki repository locally. All uploaded files prior to GitLab ...@@ -58,6 +60,22 @@ if you clone the wiki repository locally. All uploaded files prior to GitLab
11.3 are stored in GitLab itself. If you want them to be part of the wiki's Git 11.3 are stored in GitLab itself. If you want them to be part of the wiki's Git
repository, you will have to upload them again. repository, you will have to upload them again.
### Length restrictions for file and directory names
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24364) in GitLab 12.8.
Many common file systems have a [limit of 255 bytes for file and directory names](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits), and while Git and GitLab both support paths exceeding those limits, the presence of them makes it impossible for users on those file systems to checkout a wiki repository locally.
To avoid this situation, these limits are enforced when editing pages through the GitLab web interface and API:
- 245 bytes for page titles (reserving 10 bytes for the file extension).
- 255 bytes for directory names.
Please note that:
- Non-ASCII characters take up more than one byte.
- It's still possible to create files and directories exceeding those limits locally through Git, but this might break on other people's machines.
## Editing a wiki page ## Editing a wiki page
NOTE: **Note:** NOTE: **Note:**
......
...@@ -22721,6 +22721,12 @@ msgstr "" ...@@ -22721,6 +22721,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command." msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "" msgstr ""
msgid "exceeds the limit of %{bytes} bytes for directory names"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes for page titles"
msgstr ""
msgid "expired on %{milestone_due_date}" msgid "expired on %{milestone_due_date}"
msgstr "" msgstr ""
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment