mirror of
https://github.com/gogs/gogs.git
synced 2026-03-01 17:50:59 +01:00
Compare commits
395 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a38e4a0b02 | ||
|
|
def39d191b | ||
|
|
67a9416ae5 | ||
|
|
0af74b36ad | ||
|
|
d02e45f985 | ||
|
|
e5d6f4ce56 | ||
|
|
485ea6f14f | ||
|
|
28580aee63 | ||
|
|
6a23252edc | ||
|
|
e407df54f0 | ||
|
|
bad533a219 | ||
|
|
7d3932b9cd | ||
|
|
b61ef40406 | ||
|
|
767bf82eab | ||
|
|
5cd887dba5 | ||
|
|
b7e26aa5e3 | ||
|
|
aa35be975f | ||
|
|
6ed96b7a20 | ||
|
|
3cc04682c5 | ||
|
|
f15fa9167a | ||
|
|
cd0ee35b3f | ||
|
|
3a44143b81 | ||
|
|
9420eecb87 | ||
|
|
17a34949eb | ||
|
|
775bd65234 | ||
|
|
85f384f271 | ||
|
|
ba77a3b0b4 | ||
|
|
19525abfc4 | ||
|
|
f989805050 | ||
|
|
fc1befcf3c | ||
|
|
2a2596fe61 | ||
|
|
3f2e99962c | ||
|
|
216683004e | ||
|
|
87b90372a7 | ||
|
|
5a99e9a37b | ||
|
|
afccd0a3ee | ||
|
|
0669897226 | ||
|
|
ddddad9792 | ||
|
|
fc6d80d619 | ||
|
|
92036a78d1 | ||
|
|
3c65265871 | ||
|
|
79f3281548 | ||
|
|
16018e8323 | ||
|
|
15d4f32825 | ||
|
|
04adc94b26 | ||
|
|
2f40f614b5 | ||
|
|
23f3f60dcf | ||
|
|
1ab09e4f1b | ||
|
|
01cef678a3 | ||
|
|
02c5bade0f | ||
|
|
f706102890 | ||
|
|
7140f50637 | ||
|
|
e0329c0eb5 | ||
|
|
4dfffee9fb | ||
|
|
3e307e7862 | ||
|
|
e91b28eb9b | ||
|
|
5d4425bbbc | ||
|
|
7f71fe9dae | ||
|
|
5589445557 | ||
|
|
98f7f6bef8 | ||
|
|
43bf94e1aa | ||
|
|
a7662f4a39 | ||
|
|
8e238058b2 | ||
|
|
26bccef297 | ||
|
|
e8b62e8957 | ||
|
|
32fb5ea5d0 | ||
|
|
e43bd15b96 | ||
|
|
4de0b19cec | ||
|
|
902f19f70b | ||
|
|
bfce0def25 | ||
|
|
5c4b85c029 | ||
|
|
57291d1e2a | ||
|
|
956c59b282 | ||
|
|
0a2068d7fb | ||
|
|
cd6376f093 | ||
|
|
d4fc8880eb | ||
|
|
b8425ccbec | ||
|
|
7ec42465a7 | ||
|
|
89ea3e1acc | ||
|
|
facd491a6d | ||
|
|
4c4488213a | ||
|
|
ac29dc93cd | ||
|
|
27bd2157ed | ||
|
|
b293b6eaa6 | ||
|
|
3d9cda2d98 | ||
|
|
faddaff90d | ||
|
|
569fcc30f3 | ||
|
|
32152d2363 | ||
|
|
69d98e9edd | ||
|
|
66a9c0d71d | ||
|
|
7e3d66673d | ||
|
|
fb9dcfa921 | ||
|
|
d8394bb2e0 | ||
|
|
ee6786216a | ||
|
|
37fcc8daf2 | ||
|
|
9803f84c88 | ||
|
|
c0e9481fa6 | ||
|
|
c6b87aaf02 | ||
|
|
077d1ae70b | ||
|
|
61608f13a0 | ||
|
|
4ef3245413 | ||
|
|
2a70d6b723 | ||
|
|
bb103e8723 | ||
|
|
161774d4fb | ||
|
|
edbfbfa66e | ||
|
|
830bc75107 | ||
|
|
8e384ce46c | ||
|
|
cf59057ef3 | ||
|
|
0e286a0ca9 | ||
|
|
bd414a2d1f | ||
|
|
be8bdc0393 | ||
|
|
9fa287e4f7 | ||
|
|
210306bd64 | ||
|
|
eae08ea8f4 | ||
|
|
452cca35e0 | ||
|
|
7170011f4d | ||
|
|
f99690a545 | ||
|
|
bdd6aef746 | ||
|
|
e6f97c78ff | ||
|
|
50d91f3b6a | ||
|
|
7d4cef6008 | ||
|
|
d0827e5d5e | ||
|
|
bb26285a12 | ||
|
|
9e61ec316e | ||
|
|
13e35398aa | ||
|
|
9f4e584122 | ||
|
|
04d698bfbc | ||
|
|
c7cbdd34fb | ||
|
|
d5c6b53571 | ||
|
|
f0ca16d78f | ||
|
|
6251626de4 | ||
|
|
9b0858b1ad | ||
|
|
c73e9057ae | ||
|
|
fd70f9ec1b | ||
|
|
d016eaaa09 | ||
|
|
44fa9147b7 | ||
|
|
0b56272c13 | ||
|
|
677b1ec627 | ||
|
|
3ea1443885 | ||
|
|
6643647687 | ||
|
|
b6272d1803 | ||
|
|
40de2f78c4 | ||
|
|
aa2148a7a9 | ||
|
|
bd555551ce | ||
|
|
e1c5008238 | ||
|
|
0f1ff9b1ad | ||
|
|
52cc58fd9d | ||
|
|
477bea574a | ||
|
|
37566f71a9 | ||
|
|
afdb0c7f9d | ||
|
|
63c1f9a23f | ||
|
|
e948c7c262 | ||
|
|
81a44e4cd0 | ||
|
|
f059866a21 | ||
|
|
234a7c19a4 | ||
|
|
35dd41c3a2 | ||
|
|
afc659442d | ||
|
|
6a6636d451 | ||
|
|
46742a79ca | ||
|
|
d61def86e1 | ||
|
|
30c750a5df | ||
|
|
bae1d65564 | ||
|
|
995a805a31 | ||
|
|
c0cfd62b90 | ||
|
|
e193005c66 | ||
|
|
fff8109567 | ||
|
|
3af757ed77 | ||
|
|
ebbe6177a9 | ||
|
|
97b39ae2e4 | ||
|
|
0f77ad219c | ||
|
|
8b31be43c6 | ||
|
|
21dbcb7c77 | ||
|
|
0d7bb9af46 | ||
|
|
86e9ebdcc9 | ||
|
|
350e0080e6 | ||
|
|
66e2016eeb | ||
|
|
030b3d751e | ||
|
|
79537467da | ||
|
|
a18decf4cc | ||
|
|
20b5c23a19 | ||
|
|
e6e2cf7855 | ||
|
|
c884ecfea1 | ||
|
|
edbe1de026 | ||
|
|
2321b4b272 | ||
|
|
007cf33e88 | ||
|
|
b231b8c927 | ||
|
|
d01e7b0173 | ||
|
|
bb267e30b6 | ||
|
|
eca42bcb44 | ||
|
|
5ffeca35e7 | ||
|
|
87be137b88 | ||
|
|
0a697517ac | ||
|
|
c4820f119d | ||
|
|
57b3be4016 | ||
|
|
b033f2f535 | ||
|
|
f34b04cfc0 | ||
|
|
ec71d538fc | ||
|
|
6919c80f0b | ||
|
|
99599c099f | ||
|
|
d01f2f3c22 | ||
|
|
1a5aa5e0c0 | ||
|
|
9803c421f5 | ||
|
|
792ec63c8a | ||
|
|
c9e0b3b987 | ||
|
|
28766479a7 | ||
|
|
9ac940d31d | ||
|
|
b553ea45ee | ||
|
|
ac4a10456e | ||
|
|
2f3a7e53cb | ||
|
|
42c7bb7529 | ||
|
|
35140f1cc7 | ||
|
|
4f4392b83e | ||
|
|
db6c0ebf76 | ||
|
|
cf7ebfbdc8 | ||
|
|
bc8721fb6c | ||
|
|
01ba771783 | ||
|
|
9ee80e3e54 | ||
|
|
b2c6a6920f | ||
|
|
e321469884 | ||
|
|
b7ebbb4064 | ||
|
|
9a1fe801e5 | ||
|
|
6f71632e3e | ||
|
|
2844674587 | ||
|
|
0daef29053 | ||
|
|
21081836ba | ||
|
|
a2f6e1803b | ||
|
|
39c068400e | ||
|
|
47e7175b80 | ||
|
|
0b785ad967 | ||
|
|
069486d169 | ||
|
|
298ebc58c1 | ||
|
|
3fd41d138c | ||
|
|
35b02997f8 | ||
|
|
adc1ac689e | ||
|
|
528c075ad6 | ||
|
|
e577f2fff3 | ||
|
|
daf96dfae1 | ||
|
|
d4a1d9f82a | ||
|
|
f7f4ea1dcf | ||
|
|
0af3a5b603 | ||
|
|
00cf3e4dab | ||
|
|
cb6be94358 | ||
|
|
54ef1cee1d | ||
|
|
b9999427a8 | ||
|
|
ddeb076890 | ||
|
|
d06d58e461 | ||
|
|
48bb0fadc2 | ||
|
|
cd627ba16e | ||
|
|
d0a80e432d | ||
|
|
9558999698 | ||
|
|
5338808600 | ||
|
|
82da024a4d | ||
|
|
5c866fc737 | ||
|
|
d75013a0e8 | ||
|
|
1591a37ad5 | ||
|
|
3e528f34af | ||
|
|
b6437b5a4c | ||
|
|
db4951bc61 | ||
|
|
d6132aaa88 | ||
|
|
9adc8e9d3f | ||
|
|
be54b4bf26 | ||
|
|
64d90a761b | ||
|
|
4d123d0a93 | ||
|
|
5dd8308686 | ||
|
|
9c2120eb34 | ||
|
|
4f8d888e66 | ||
|
|
ca09a0b516 | ||
|
|
a43164877c | ||
|
|
515641d033 | ||
|
|
54d25c13d7 | ||
|
|
23d53561d1 | ||
|
|
0cce61de3a | ||
|
|
5b96e3fcc7 | ||
|
|
79dae254cf | ||
|
|
5b32cdd960 | ||
|
|
f9ad8d6903 | ||
|
|
1b66600bd0 | ||
|
|
dc53270da9 | ||
|
|
8ea7ba3afa | ||
|
|
ef275ebf62 | ||
|
|
22ab4fa1b0 | ||
|
|
55dfe2c978 | ||
|
|
3c3f7c2a56 | ||
|
|
0c92da7e9c | ||
|
|
8fac41768c | ||
|
|
c418b83678 | ||
|
|
b53f6357fc | ||
|
|
11ca3dedfb | ||
|
|
f77680520f | ||
|
|
2d8c414f8c | ||
|
|
ce8d4cc80b | ||
|
|
37d8d3afe9 | ||
|
|
db0026c507 | ||
|
|
51f6148851 | ||
|
|
c0549a169a | ||
|
|
1e47e2df85 | ||
|
|
5d9ef2bb12 | ||
|
|
d21d7171b0 | ||
|
|
32dcaefafa | ||
|
|
d1a60e3643 | ||
|
|
a0f9197b45 | ||
|
|
340a4595dd | ||
|
|
4c770b87c5 | ||
|
|
47f37e55e9 | ||
|
|
52d66ba6c8 | ||
|
|
437dd5272f | ||
|
|
6bdb8ec4b9 | ||
|
|
9dc3c93a6a | ||
|
|
9e22840483 | ||
|
|
8eb5120fbd | ||
|
|
8c9338a537 | ||
|
|
21b9d5fa1f | ||
|
|
4f360d8f08 | ||
|
|
dfa4b38081 | ||
|
|
e0de6cb5ad | ||
|
|
ff8578082e | ||
|
|
35977cd34c | ||
|
|
abc57b6e43 | ||
|
|
a01b4baca2 | ||
|
|
fc5985f425 | ||
|
|
23eec25274 | ||
|
|
4e7eb5be9d | ||
|
|
b375192352 | ||
|
|
0c5ba4573a | ||
|
|
69a98236bd | ||
|
|
b866dc92d7 | ||
|
|
78f4f59380 | ||
|
|
743b55b9b0 | ||
|
|
0d5d555521 | ||
|
|
80c6cc6321 | ||
|
|
6588ce52fe | ||
|
|
5094e9501c | ||
|
|
e9875edcad | ||
|
|
7e2ea7639e | ||
|
|
5b290013a9 | ||
|
|
2c28ed8c05 | ||
|
|
283c81316c | ||
|
|
beb8a77fc5 | ||
|
|
b9881d1e7b | ||
|
|
87be4623cf | ||
|
|
377530ec21 | ||
|
|
bff1e157d5 | ||
|
|
e84e0ab904 | ||
|
|
c7f56d7483 | ||
|
|
83283bca4c | ||
|
|
f1d8746264 | ||
|
|
baae94b9cf | ||
|
|
3794111460 | ||
|
|
d7ea49b9f5 | ||
|
|
d87a9cb362 | ||
|
|
93b9a2acc0 | ||
|
|
d4a608f64c | ||
|
|
8209bf74f8 | ||
|
|
d88ebd9a4b | ||
|
|
ec8ec58b17 | ||
|
|
a342d58d7e | ||
|
|
d7d167ac63 | ||
|
|
146c8efee3 | ||
|
|
3abc41ccca | ||
|
|
9e3a1bc11a | ||
|
|
cb2da7bf2c | ||
|
|
1aa12c7452 | ||
|
|
fa241efa6d | ||
|
|
ecf3eb4307 | ||
|
|
9ae92459a5 | ||
|
|
5b3f1efd9f | ||
|
|
e0f945959e | ||
|
|
885833892f | ||
|
|
91127d9016 | ||
|
|
1a38f0e0d9 | ||
|
|
fb8beaf19a | ||
|
|
4a8a70dde0 | ||
|
|
8d2a6fc484 | ||
|
|
29ac3980ff | ||
|
|
89bd994c83 | ||
|
|
3e4db7299d | ||
|
|
80dd548b39 | ||
|
|
451f328a4c | ||
|
|
9e4c2afad7 | ||
|
|
2dd4ab65c7 | ||
|
|
b93ae452fe | ||
|
|
c04aea8d9d | ||
|
|
0d7b9065c6 | ||
|
|
452ccff81c | ||
|
|
fb839ca0fb | ||
|
|
b7b7863364 | ||
|
|
3005c4f6db | ||
|
|
963354c5d7 | ||
|
|
17c1bc7383 | ||
|
|
5103f16f78 | ||
|
|
e848b17fab | ||
|
|
3600498c8f | ||
|
|
b2632dec09 | ||
|
|
211dc74816 | ||
|
|
c9e5e38fcf |
@@ -14,7 +14,7 @@ watch_dirs = [
|
||||
watch_exts = [".go", ".ini"]
|
||||
build_delay = 1500
|
||||
cmds = [
|
||||
["go", "install", "-tags", "sqlite cert"],
|
||||
["go", "install", "-tags", "sqlite cert"],# redis memcache
|
||||
["go", "build", "-tags", "sqlite cert"],
|
||||
["./gogs", "web"]
|
||||
]
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
*.db
|
||||
*.log
|
||||
log/
|
||||
custom/
|
||||
data/
|
||||
.vendor/
|
||||
@@ -8,28 +9,19 @@ data/
|
||||
*.iml
|
||||
public/img/avatar/
|
||||
files/
|
||||
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.exe~
|
||||
/gogs
|
||||
@@ -42,3 +34,5 @@ config.codekit
|
||||
docker/fig.yml
|
||||
docker/docker/Dockerfile
|
||||
docker/docker/init_gogs.sh
|
||||
gogs.sublime-project
|
||||
gogs.sublime-workspace
|
||||
|
||||
@@ -10,6 +10,7 @@ filesets:
|
||||
- README_ZH.md
|
||||
excludes:
|
||||
- \.git
|
||||
depth: 5
|
||||
settings:
|
||||
build: |
|
||||
if test "$GOOS" = "windows" -a "$GOARCH" = "386"
|
||||
|
||||
51
.gopmfile
51
.gopmfile
@@ -2,30 +2,35 @@
|
||||
path = github.com/gogits/gogs
|
||||
|
||||
[deps]
|
||||
github.com/beego/memcache = commit:2aea774416
|
||||
github.com/beego/redigo = commit:856744a0d5
|
||||
github.com/bradfitz/gomemcache = commit:72a68649ba
|
||||
github.com/Unknwon/cae = commit:2e70a1351b
|
||||
github.com/Unknwon/com = commit:2cbcbc6916
|
||||
github.com/Unknwon/goconfig = commit:0f8d8dc1c0
|
||||
github.com/Unknwon/i18n = commit:47baeff8d0
|
||||
github.com/Unknwon/macaron = commit:4927b78ad9
|
||||
github.com/codegangsta/cli = commit:7381bc4e62
|
||||
github.com/go-sql-driver/mysql = commit:8111ee3ec3
|
||||
github.com/go-xorm/core = commit:750aae0fa5
|
||||
github.com/go-xorm/xorm = commit:2d8b3135b1
|
||||
github.com/gogits/gfm = commit:40f747a9c0
|
||||
github.com/gogits/oauth2 = commit:99cbec870a
|
||||
github.com/lib/pq = commit:b021d0ef20
|
||||
github.com/macaron-contrib/cache = commit:204d8e5137
|
||||
github.com/macaron-contrib/captcha = commit:d37d37eeea
|
||||
github.com/macaron-contrib/csrf = commit:8e980822b0
|
||||
github.com/macaron-contrib/i18n = commit:2246f45894
|
||||
github.com/macaron-contrib/session = commit:42ad41e323
|
||||
github.com/macaron-contrib/toolbox = commit:57127bcc89
|
||||
github.com/mattn/go-sqlite3 = commit:a80c27ba33
|
||||
github.com/nfnt/resize = commit:581d15cb53
|
||||
github.com/russross/blackfriday = commit:05b8cefd6a
|
||||
github.com/saintfish/chardet = commit:3af4cd4741
|
||||
github.com/Unknwon/com = commit:188d690b1a
|
||||
github.com/Unknwon/i18n = commit:1e88666229
|
||||
github.com/Unknwon/macaron = commit:e089393c3f
|
||||
github.com/codegangsta/cli = commit:6086d7927e
|
||||
github.com/go-sql-driver/mysql = commit:27633f0519
|
||||
github.com/go-xorm/core = commit:16cb27928f
|
||||
github.com/go-xorm/xorm = commit:f2d3be988e
|
||||
github.com/gogits/chardet = commit:2404f77725
|
||||
github.com/gogits/go-gogs-client = commit:92e76d616a
|
||||
github.com/lib/pq = commit:835d5eb08d
|
||||
github.com/macaron-contrib/binding = commit:dc739fabc3
|
||||
github.com/macaron-contrib/cache = commit:b68f6b448f
|
||||
github.com/macaron-contrib/captcha = commit:066c50c7eb
|
||||
github.com/macaron-contrib/csrf = commit:98ddf5a710
|
||||
github.com/macaron-contrib/i18n = commit:eeebd44f64
|
||||
github.com/macaron-contrib/oauth2 = commit:8f394c3629
|
||||
github.com/macaron-contrib/session = commit:8e8d938b27
|
||||
github.com/macaron-contrib/toolbox = commit:acbfe36e16
|
||||
github.com/mattn/go-sqlite3 = commit:25d045f12a
|
||||
github.com/microcosm-cc/bluemonday = commit:fcd0f5074e
|
||||
github.com/nfnt/resize = commit:8f44931448
|
||||
github.com/russross/blackfriday = commit:77efab57b2
|
||||
github.com/shurcooL/go = commit:329f57438c
|
||||
golang.org/x/net =
|
||||
golang.org/x/text =
|
||||
gopkg.in/ini.v1 = commit:4febc4104c
|
||||
gopkg.in/redis.v2 = commit:e617904962
|
||||
|
||||
[res]
|
||||
include = conf|etc|public|scripts|templates
|
||||
|
||||
@@ -2,9 +2,7 @@ targets:
|
||||
ubuntu-14.04:
|
||||
ubuntu-12.04:
|
||||
debian-7:
|
||||
build_dependencies:
|
||||
- mercurial
|
||||
- bzr
|
||||
centos-6:
|
||||
dependencies:
|
||||
- git
|
||||
before:
|
||||
|
||||
12
.travis.yml
12
.travis.yml
@@ -2,4 +2,14 @@ language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.3
|
||||
- 1.4
|
||||
- tip
|
||||
|
||||
sudo: false
|
||||
|
||||
script: go build -v
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- u@gogs.io
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> This guidelines sheet is forked from [CONTRIBUTING.md](https://github.com/drone/drone/blob/master/CONTRIBUTING.md).
|
||||
|
||||
Gogs is not perfect and it has bugs, or incomplete features for rare cases. You're welcome to tell us or contribute some code. This document describles details about how can you contribute to Gogs project.
|
||||
Gogs is not perfect and it has bugs, or incomplete features for rare cases. You're welcome to tell us or contribute some code. This document describes details about how can you contribute to Gogs project.
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
@@ -15,36 +15,30 @@ Depends on the situation, you will:
|
||||
|
||||
### Bug Report
|
||||
|
||||
If you find or consider something is a bug, please create a issue on [GitHub](https://github.com/gogits/gogs/issues). To reduce unnecessary time wasting of interacting and waiting with team members, please use following form as template in the first place:
|
||||
If you find or consider something is a bug, please create a issue on [GitHub](https://github.com/gogits/gogs/issues). To reduce unnecessary time wasting of interacting and waiting with team members, please include following information in the first place with a comfortable form for you:
|
||||
|
||||
```
|
||||
- **Bug Description**:
|
||||
- **Gogs Version**:
|
||||
- **Git Version**:
|
||||
- **System Type**:
|
||||
- **Error Log**:
|
||||
- **Other information**:
|
||||
```
|
||||
- Bug Description
|
||||
- Gogs Version
|
||||
- Git Version
|
||||
- System Type
|
||||
- Error Log
|
||||
- Other information
|
||||
|
||||
Please take a moment to check that an issue on [GitHub](https://github.com/gogits/gogs/issues) doesn't already exist documenting your bug report or improvement proposal. If it does, it never hurts to add a quick "+1" or "I have this problem too". This will help prioritize the most common problems and requests.
|
||||
|
||||
#### Bug Report Example
|
||||
|
||||
- **Bug Description**: Crash when create repository with license|
|
||||
- **Gogs Version**: `v0.4.9.0901`
|
||||
- **Git Version**: `1.9.0`
|
||||
- **System Type**: `Ubuntu 12.04`
|
||||
- **Error Log**:
|
||||
Gogs crashed when create repository with license, using v0.5.13.0207, SQLite3, Git 1.9.0, Ubuntu 12.04.
|
||||
|
||||
Error log:
|
||||
|
||||
```
|
||||
2014/09/01 07:21:49 [E] nil pointer
|
||||
```
|
||||
|
||||
- **Other information**: Use SQLite3 as database
|
||||
|
||||
### Feature Request
|
||||
|
||||
There is no standard form of making a feature request, just try to describle the feature as clear as possible because team members may not have experience with the functionality you're talking about.
|
||||
There is no standard form of making a feature request, just try to describe the feature as clear as possible because team members may not have experience with the functionality you're talking about.
|
||||
|
||||
### Pull Request
|
||||
|
||||
@@ -54,7 +48,7 @@ We are always thrilled to receive pull requests, and do our best to process them
|
||||
|
||||
If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve.
|
||||
|
||||
We're trying very hard to keep Gogs lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature.
|
||||
We're trying very hard to keep Gogs lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature. We believe you do like to discuss with us first in [Gitter](https://gitter.im/gogits/gogs).
|
||||
|
||||
### Ask For Help
|
||||
|
||||
@@ -64,8 +58,17 @@ Before open any new issue, please check your problem on [Troubleshooting](http:/
|
||||
|
||||
Please take a moment to check that an issue on [GitHub](https://github.com/gogits/gogs/issues) or card on [Trello](https://trello.com/b/uxAoeLUl/gogs-go-git-service) doesn't already exist documenting your bug report or improvement proposal. If it does, it never hurts to add a quick "+1" or "I have this problem too". This will help prioritize the most common problems and requests.
|
||||
|
||||
### Discuss your design on the mailing list
|
||||
## Code of conduct
|
||||
|
||||
We recommend discussing your plans [on the mailing list](https://groups.google.com/forum/#!forum/gogits) before starting to code - especially for more ambitious contributions. This gives other contributors a chance to point you in the right direction, give feedback on your design, and maybe point out if someone else is working on the same thing.
|
||||
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We may close your pull request if not first discussed on the mailing list. We aren't doing this to be jerks. We are doing this to prevent people from spending large amounts of time on changes that may need to be designed or architected in a specific way, or may not align with the vision of the project.
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
||||
|
||||
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior can be
|
||||
reported by emailing contact@gitlab.com
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
||||
|
||||
40
LICENSE
40
LICENSE
@@ -1,27 +1,19 @@
|
||||
Copyright (c) 2014
|
||||
All rights reserved.
|
||||
Copyright (c) 2014 All Gogs Contributors
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the {organization} nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
28
README.md
28
README.md
@@ -1,16 +1,20 @@
|
||||
Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://travis-ci.org/gogits/gogs)
|
||||
Gogs - Go Git Service [](https://travis-ci.org/gogits/gogs)
|
||||
=====================
|
||||
|
||||
[](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Gogs(Go Git Service) is a painless self-hosted Git Service written in Go.
|
||||
|
||||

|
||||

|
||||
|
||||
##### Current version: 0.5.5 Beta
|
||||
##### Current version: 0.5.13 Beta
|
||||
|
||||
### NOTICES
|
||||
|
||||
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **June 21, 2014** and will reset multiple times after. Please do **NOT** put your important data on the site.
|
||||
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
|
||||
- Demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch.
|
||||
- You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing a issue or making a Pull Request.
|
||||
- If you think there are vulnerabilities in the project, please talk private to **u@gogs.io**, thanks!
|
||||
|
||||
#### Other language version
|
||||
|
||||
@@ -24,27 +28,31 @@ The goal of this project is to make the easiest, fastest and most painless way t
|
||||
|
||||
- Please see [Documentation](http://gogs.io/docs/intro/) for project design, known issues, and change log.
|
||||
- See [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team.
|
||||
- Try it before anything? Do it [online](https://try.gogs.io/Unknown/gogs) or go down to **Installation -> Install from binary** section!
|
||||
- Try it before anything? Do it [online](https://try.gogs.io/unknwon/gogs) or go down to **Installation -> Install from binary** section!
|
||||
- Having troubles? Get help from [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md).
|
||||
- Want to help on localization? Check out [Crowdin](https://crowdin.com/project/gogs)!
|
||||
|
||||
## Features
|
||||
|
||||
- Activity timeline
|
||||
- SSH/HTTP(S) protocol support
|
||||
- SMTP/LDAP/reverse proxy authentication support
|
||||
- Reverse proxy suburl support
|
||||
- Register/delete/rename account
|
||||
- Create/manage/delete organization with team management
|
||||
- Create/migrate/mirror/delete/watch/rename/transfer public/private repository
|
||||
- Create/fork/migrate/mirror/delete/watch/rename/transfer public/private repository
|
||||
- Repository viewer/release/issue tracker
|
||||
- Repository and Organization level webhooks
|
||||
- Repository Git hooks
|
||||
- Add/remove repository collaborators
|
||||
- Gravatar and cache support
|
||||
- Mail service(register, issue)
|
||||
- Administration panel
|
||||
- Slack webhook integration
|
||||
- Drone CI integration
|
||||
- Supports MySQL, PostgreSQL and SQLite3
|
||||
- Social account login(GitHub, Google, QQ, Weibo)
|
||||
- Multi-language support(English, Simplified Chinese, Traditional Chinese, Germany, French, Dutch etc.)
|
||||
- Multi-language support([10 languages](https://crowdin.com/project/gogs))
|
||||
|
||||
## System Requirements
|
||||
|
||||
@@ -68,13 +76,15 @@ There are 5 ways to install Gogs:
|
||||
- Router and middleware mechanism of [Macaron](https://github.com/Unknwon/macaron).
|
||||
- Mail Service, modules design is inspired by [WeTalk](https://github.com/beego/wetalk).
|
||||
- System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog).
|
||||
- Usage and modification from [beego](http://beego.me) modules.
|
||||
- Thanks [lavachen](http://www.lavachen.cn/) and [Rocker](http://weibo.com/rocker1989) for designing Logo.
|
||||
- Thanks [gobuild.io](http://gobuild.io) for providing binary compile and download service.
|
||||
- Thanks [Crowdin](https://crowdin.com/project/gogs) for providing open source translation plan.
|
||||
|
||||
## Contributors
|
||||
|
||||
The [core team](http://gogs.io/team) of this project. See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors.
|
||||
- The [core team](http://gogs.io/team) of this project.
|
||||
- See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors.
|
||||
- See [TRANSLATORS](conf/locale/TRANSLATORS) for full list of translators.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
38
README_ZH.md
38
README_ZH.md
@@ -1,11 +1,11 @@
|
||||
Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://travis-ci.org/gogits/gogs)
|
||||
Gogs - Go Git Service [](https://travis-ci.org/gogits/gogs)
|
||||
=====================
|
||||
|
||||
Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务。
|
||||
|
||||

|
||||

|
||||
|
||||
##### 当前版本:0.5.5 Beta
|
||||
##### 当前版本:0.5.13 Beta
|
||||
|
||||
## 开发目的
|
||||
|
||||
@@ -15,27 +15,31 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
|
||||
|
||||
- 有关项目设计、已知问题和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。
|
||||
- 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。
|
||||
- 想要先睹为快?通过 [在线体验](https://try.gogs.io/Unknown/gogs) 或查看 **安装部署 -> 二进制安装** 小节。
|
||||
- 想要先睹为快?通过 [在线体验](https://try.gogs.io/unknwon/gogs) 或查看 **安装部署 -> 二进制安装** 小节。
|
||||
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.md) 页面获取帮助。
|
||||
- 希望帮助多国语言界面的翻译吗?请立即访问 [Crowdin](https://crowdin.com/project/gogs)!
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 活动时间线
|
||||
- 支持 SSH/HTTP(S) 协议
|
||||
- 支持 SMTP/LDAP/反向代理 用户认证
|
||||
- 注册/删除/重命名 用户
|
||||
- 创建/管理/删除 组织以及团队管理功能
|
||||
- 创建/迁移/镜像/删除/关注/重命名/转移 公开/私有 仓库
|
||||
- 仓库 浏览/发布/工单管理
|
||||
- 仓库和组织级别 Web 钩子
|
||||
- 添加/删除 仓库协作者
|
||||
- Gravatar 以及缓存支持
|
||||
- 邮件服务(注册、Issue)
|
||||
- 支持反向代理子路径
|
||||
- 支持 注册/删除/重命名 用户
|
||||
- 支持 创建/管理/删除 组织以及团队管理功能
|
||||
- 支持 创建/派生/迁移/镜像/删除/关注/重命名/转移 公开/私有 仓库
|
||||
- 支持仓库 浏览/发布/工单管理
|
||||
- 支持仓库和组织级别 Web 钩子
|
||||
- 支持仓库 Git 钩子
|
||||
- 支持 添加/删除 仓库协作者
|
||||
- 支持 Gravatar 以及本地缓存
|
||||
- 支持邮件服务(注册、Issue)
|
||||
- 管理员面板
|
||||
- Slack Web 钩子集成
|
||||
- Drone CI 持续部署集成
|
||||
- 支持 MySQL、PostgreSQL 以及 SQLite3 数据库
|
||||
- 社交帐号登录(GitHub、Google、QQ、微博)
|
||||
- 多语言支持(英文、简体中文、繁体中文、德语、法语、荷兰语等等)
|
||||
- 多语言支持([10 种语言]([more](https://crowdin.com/project/gogs)))
|
||||
|
||||
## 系统要求
|
||||
|
||||
@@ -56,16 +60,18 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
|
||||
|
||||
## 特别鸣谢
|
||||
|
||||
- [Macaron](https://github.com/Unknwon/macaron) 的路由与中间件机制。
|
||||
- [beego](http://beego.me) 模块的使用与修改。
|
||||
- 基于 [Macaron](https://github.com/Unknwon/macaron) 的路由与中间件机制。
|
||||
- 基于 [WeTalk](https://github.com/beego/wetalk) 修改的邮件服务和模块设计。
|
||||
- 基于 [GoBlog](https://github.com/fuxiaohei/goblog) 修改的系统监视状态。
|
||||
- 感谢 [gobuild.io](http://gobuild.io) 提供二进制编译与下载服务。
|
||||
- 感谢 [lavachen](http://www.lavachen.cn/) 和 [Rocker](http://weibo.com/rocker1989) 设计的 Logo。
|
||||
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
|
||||
|
||||
## 贡献成员
|
||||
|
||||
本项目的 [开发团队](http://gogs.io/team)。您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取完整的贡献者列表。
|
||||
- 本项目的 [开发团队](http://gogs.io/team)。
|
||||
- 您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取完整的贡献者列表。
|
||||
- 您可以通过查看 [TRANSLATORS](conf/locale/TRANSLATORS) 文件获取完整的翻译人员列表。
|
||||
|
||||
## 授权许可
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"os"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
@@ -19,16 +19,9 @@ var CmdCert = cli.Command{
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
Action: runCert,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{"host", "", "Comma-separated hostnames and IPs to generate a certificate for", ""},
|
||||
cli.StringFlag{"ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521", ""},
|
||||
cli.IntFlag{"rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set", ""},
|
||||
cli.StringFlag{"start-date", "", "Creation date formatted as Jan 1 15:04:05 2011", ""},
|
||||
cli.DurationFlag{"duration", 365 * 24 * time.Hour, "Duration that certificate is valid for", ""},
|
||||
cli.BoolFlag{"ca", "whether this cert should be its own Certificate Authority", ""},
|
||||
},
|
||||
}
|
||||
|
||||
func runCert(ctx *cli.Context) {
|
||||
fmt.Println("Command cert not available, please use build tags 'cert' to rebuild.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -25,11 +25,15 @@ var CmdDump = cli.Command{
|
||||
It can be used for backup and capture Gogs server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""},
|
||||
cli.BoolFlag{"verbose, v", "show process details", ""},
|
||||
},
|
||||
}
|
||||
|
||||
func runDump(ctx *cli.Context) {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
setting.NewConfigContext()
|
||||
models.LoadModelsConfig()
|
||||
models.SetEngine()
|
||||
@@ -58,8 +62,9 @@ func runDump(ctx *cli.Context) {
|
||||
workDir, _ := setting.WorkDir()
|
||||
z.AddFile("gogs-repo.zip", path.Join(workDir, "gogs-repo.zip"))
|
||||
z.AddFile("gogs-db.sql", path.Join(workDir, "gogs-db.sql"))
|
||||
z.AddFile("custom/conf/app.ini", path.Join(workDir, "custom/conf/app.ini"))
|
||||
z.AddDir("custom", path.Join(workDir, "custom"))
|
||||
z.AddDir("log", path.Join(workDir, "log"))
|
||||
// FIXME: SSH key file.
|
||||
if err = z.Close(); err != nil {
|
||||
os.Remove(fileName)
|
||||
log.Fatalf("Fail to save %s: %v", fileName, err)
|
||||
|
||||
181
cmd/fix.go
181
cmd/fix.go
@@ -1,181 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var CmdFix = cli.Command{
|
||||
Name: "fix",
|
||||
Usage: "This command for upgrade from old version",
|
||||
Action: runFix,
|
||||
Subcommands: fixCommands,
|
||||
Flags: []cli.Flag{},
|
||||
}
|
||||
|
||||
func runFix(ctx *cli.Context) {
|
||||
}
|
||||
|
||||
var fixCommands = []cli.Command{
|
||||
{
|
||||
Name: "location",
|
||||
Usage: "Change Gogs app location",
|
||||
Description: `Command location fixes location change of Gogs
|
||||
|
||||
gogs fix location <old Gogs path>
|
||||
`,
|
||||
Action: runFixLocation,
|
||||
},
|
||||
}
|
||||
|
||||
// rewriteAuthorizedKeys replaces old Gogs path to the new one.
|
||||
func rewriteAuthorizedKeys(sshPath, oldPath, newPath string) error {
|
||||
fr, err := os.Open(sshPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
tmpPath := sshPath + ".tmp"
|
||||
fw, err := os.Create(tmpPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
oldPath = "command=\"" + oldPath + " serv"
|
||||
newPath = "command=\"" + newPath + " serv"
|
||||
buf := bufio.NewReader(fr)
|
||||
for {
|
||||
line, errRead := buf.ReadString('\n')
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if errRead != nil {
|
||||
if errRead != io.EOF {
|
||||
return errRead
|
||||
}
|
||||
|
||||
// Reached end of file, if nothing to read then break,
|
||||
// otherwise handle the last line.
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Still finding the line, copy the line that currently read.
|
||||
if _, err = fw.WriteString(strings.Replace(line, oldPath, newPath, 1) + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if errRead == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.Remove(sshPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpPath, sshPath)
|
||||
}
|
||||
|
||||
func rewriteUpdateHook(path, appPath string) error {
|
||||
if runtime.GOOS == "windows" {
|
||||
rp := strings.NewReplacer("\\", "/")
|
||||
appPath = "\"" + rp.Replace(appPath) + "\""
|
||||
} else {
|
||||
rp := strings.NewReplacer("\\", "/", " ", "\\ ")
|
||||
appPath = rp.Replace(appPath)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(path, []byte(fmt.Sprintf(models.TPL_UPDATE_HOOK,
|
||||
setting.ScriptType, appPath)), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkDir(rootPath, recPath, appPath string, depth int) error {
|
||||
depth++
|
||||
if depth > 3 {
|
||||
return nil
|
||||
} else if depth == 3 {
|
||||
if err := rewriteUpdateHook(path.Join(rootPath, "hooks/update"), appPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
dir, err := os.Open(rootPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fi := range fis {
|
||||
if strings.Contains(fi.Name(), ".DS_Store") {
|
||||
continue
|
||||
}
|
||||
|
||||
relPath := path.Join(recPath, fi.Name())
|
||||
curPath := path.Join(rootPath, fi.Name())
|
||||
if fi.IsDir() {
|
||||
if err = walkDir(curPath, relPath, appPath, depth); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runFixLocation(ctx *cli.Context) {
|
||||
if len(ctx.Args()) != 1 {
|
||||
fmt.Println("Incorrect arguments number, expect 1")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
execPath, _ := setting.ExecPath()
|
||||
|
||||
oldPath := ctx.Args().First()
|
||||
fmt.Printf("Old location: %s\n", oldPath)
|
||||
fmt.Println("This command should be executed in the new Gogs path")
|
||||
fmt.Printf("Do you want to change Gogs app path from old location to:\n")
|
||||
fmt.Printf("-> %s?\n", execPath)
|
||||
fmt.Print("Press <enter> to continue, use <Ctrl+c> to exit.")
|
||||
fmt.Scanln()
|
||||
|
||||
// Fix in authorized_keys file.
|
||||
sshPath := path.Join(models.SshPath, "authorized_keys")
|
||||
fmt.Printf("Fixing pathes in file: %s\n", sshPath)
|
||||
if err := rewriteAuthorizedKeys(sshPath, oldPath, execPath); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fix position in gogs-repositories.
|
||||
setting.NewConfigContext()
|
||||
fmt.Printf("Fixing pathes in repositories: %s\n", setting.RepoRootPath)
|
||||
if err := walkDir(setting.RepoRootPath, "", execPath, 0); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Fix position finished!")
|
||||
}
|
||||
30
cmd/serve.go
30
cmd/serve.go
@@ -27,12 +27,20 @@ var CmdServ = cli.Command{
|
||||
Usage: "This command should only be called by SSH shell",
|
||||
Description: `Serv provide access auth for repositories`,
|
||||
Action: runServ,
|
||||
Flags: []cli.Flag{},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""},
|
||||
},
|
||||
}
|
||||
|
||||
func setup(logPath string) {
|
||||
setting.NewConfigContext()
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
|
||||
if setting.DisableSSH {
|
||||
println("Gogs: SSH has been disabled")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
models.LoadModelsConfig()
|
||||
|
||||
if models.UseSQLite3 {
|
||||
@@ -77,9 +85,15 @@ func In(b string, sl map[string]models.AccessType) bool {
|
||||
}
|
||||
|
||||
func runServ(k *cli.Context) {
|
||||
if k.IsSet("config") {
|
||||
setting.CustomConf = k.String("config")
|
||||
}
|
||||
setup("serv.log")
|
||||
|
||||
keys := strings.Split(os.Args[2], "-")
|
||||
if len(k.Args()) < 1 {
|
||||
log.GitLogger.Fatal(2, "Not enough arguments")
|
||||
}
|
||||
keys := strings.Split(k.Args()[0], "-")
|
||||
if len(keys) != 2 {
|
||||
println("Gogs: auth file format error")
|
||||
log.GitLogger.Fatal(2, "Invalid auth file format: %s", os.Args[2])
|
||||
@@ -96,7 +110,7 @@ func runServ(k *cli.Context) {
|
||||
println("Gogs: you are not the owner of SSH key")
|
||||
log.GitLogger.Fatal(2, "Invalid owner of SSH key: %d", keyId)
|
||||
}
|
||||
println("Gogs: internal error:", err)
|
||||
println("Gogs: internal error:", err.Error())
|
||||
log.GitLogger.Fatal(2, "Fail to get user by key ID(%d): %v", keyId, err)
|
||||
}
|
||||
|
||||
@@ -125,7 +139,7 @@ func runServ(k *cli.Context) {
|
||||
println("Gogs: given repository owner are not registered")
|
||||
log.GitLogger.Fatal(2, "Unregistered owner: %s", repoUserName)
|
||||
}
|
||||
println("Gogs: internal error:", err)
|
||||
println("Gogs: internal error:", err.Error())
|
||||
log.GitLogger.Fatal(2, "Fail to get repository owner(%s): %v", repoUserName, err)
|
||||
}
|
||||
|
||||
@@ -134,7 +148,7 @@ func runServ(k *cli.Context) {
|
||||
case isWrite:
|
||||
has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.WRITABLE)
|
||||
if err != nil {
|
||||
println("Gogs: internal error:", err)
|
||||
println("Gogs: internal error:", err.Error())
|
||||
log.GitLogger.Fatal(2, "Fail to check write access:", err)
|
||||
} else if !has {
|
||||
println("You have no right to write this repository")
|
||||
@@ -147,7 +161,7 @@ func runServ(k *cli.Context) {
|
||||
println("Gogs: given repository does not exist")
|
||||
log.GitLogger.Fatal(2, "Repository does not exist: %s/%s", repoUser.Name, repoName)
|
||||
}
|
||||
println("Gogs: internal error:", err)
|
||||
println("Gogs: internal error:", err.Error())
|
||||
log.GitLogger.Fatal(2, "Fail to get repository: %v", err)
|
||||
}
|
||||
|
||||
@@ -157,14 +171,14 @@ func runServ(k *cli.Context) {
|
||||
|
||||
has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.READABLE)
|
||||
if err != nil {
|
||||
println("Gogs: internal error:", err)
|
||||
println("Gogs: internal error:", err.Error())
|
||||
log.GitLogger.Fatal(2, "Fail to check read access:", err)
|
||||
} else if !has {
|
||||
println("You have no right to access this repository")
|
||||
log.GitLogger.Fatal(2, "User %s has no right to read repository %s", user.Name, repoPath)
|
||||
}
|
||||
default:
|
||||
println("Unknown command")
|
||||
println("Unknown command: " + cmd)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var CmdUpdate = cli.Command{
|
||||
@@ -18,10 +19,15 @@ var CmdUpdate = cli.Command{
|
||||
Usage: "This command should only be called by SSH shell",
|
||||
Description: `Update get pushed info and insert into database`,
|
||||
Action: runUpdate,
|
||||
Flags: []cli.Flag{},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""},
|
||||
},
|
||||
}
|
||||
|
||||
func runUpdate(c *cli.Context) {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||
if cmd == "" {
|
||||
return
|
||||
|
||||
464
cmd/web.go
464
cmd/web.go
@@ -5,22 +5,29 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/macaron-contrib/binding"
|
||||
"github.com/macaron-contrib/cache"
|
||||
"github.com/macaron-contrib/captcha"
|
||||
"github.com/macaron-contrib/csrf"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
"github.com/macaron-contrib/oauth2"
|
||||
"github.com/macaron-contrib/session"
|
||||
"github.com/macaron-contrib/toolbox"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
@@ -30,7 +37,6 @@ import (
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/middleware"
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/routers"
|
||||
"github.com/gogits/gogs/routers/admin"
|
||||
@@ -47,7 +53,16 @@ var CmdWeb = cli.Command{
|
||||
Description: `Gogs web server is the only thing you need to run,
|
||||
and it takes care of all the other things for you`,
|
||||
Action: runWeb,
|
||||
Flags: []cli.Flag{},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{"port, p", "3000", "Temporary port number to prevent conflict", ""},
|
||||
cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""},
|
||||
},
|
||||
}
|
||||
|
||||
type VerChecker struct {
|
||||
ImportPath string
|
||||
Version func() string
|
||||
Expected string
|
||||
}
|
||||
|
||||
// checkVersion checks if binary matches the version of templates files.
|
||||
@@ -62,17 +77,20 @@ func checkVersion() {
|
||||
}
|
||||
|
||||
// Check dependency version.
|
||||
macaronVer := git.MustParseVersion(strings.Join(strings.Split(macaron.Version(), ".")[:3], "."))
|
||||
if macaronVer.LessThan(git.MustParseVersion("0.2.0")) {
|
||||
log.Fatal(4, "Package macaron version is too old, did you forget to update?(github.com/Unknwon/macaron)")
|
||||
checkers := []VerChecker{
|
||||
{"github.com/Unknwon/macaron", macaron.Version, "0.5.1"},
|
||||
{"github.com/macaron-contrib/binding", binding.Version, "0.0.4"},
|
||||
{"github.com/macaron-contrib/cache", cache.Version, "0.0.7"},
|
||||
{"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"},
|
||||
{"github.com/macaron-contrib/i18n", i18n.Version, "0.0.5"},
|
||||
{"github.com/macaron-contrib/session", session.Version, "0.1.6"},
|
||||
{"gopkg.in/ini.v1", ini.Version, "1.2.0"},
|
||||
}
|
||||
i18nVer := git.MustParseVersion(i18n.Version())
|
||||
if i18nVer.LessThan(git.MustParseVersion("0.0.2")) {
|
||||
log.Fatal(4, "Package i18n version is too old, did you forget to update?(github.com/macaron-contrib/i18n)")
|
||||
}
|
||||
sessionVer := git.MustParseVersion(session.Version())
|
||||
if sessionVer.LessThan(git.MustParseVersion("0.0.1")) {
|
||||
log.Fatal(4, "Package session version is too old, did you forget to update?(github.com/macaron-contrib/session)")
|
||||
for _, c := range checkers {
|
||||
ver := strings.Join(strings.Split(c.Version(), ".")[:3], ".")
|
||||
if git.MustParseVersion(ver).LessThan(git.MustParseVersion(c.Expected)) {
|
||||
log.Fatal(4, "Package '%s' version is too old(%s -> %s), did you forget to update?", c.ImportPath, ver, c.Expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,15 +99,25 @@ func newMacaron() *macaron.Macaron {
|
||||
m := macaron.New()
|
||||
m.Use(macaron.Logger())
|
||||
m.Use(macaron.Recovery())
|
||||
if setting.EnableGzip {
|
||||
m.Use(macaron.Gziper())
|
||||
}
|
||||
if setting.Protocol == setting.FCGI {
|
||||
m.SetURLPrefix(setting.AppSubUrl)
|
||||
}
|
||||
m.Use(macaron.Static(
|
||||
path.Join(setting.StaticRootPath, "public"),
|
||||
macaron.StaticOptions{
|
||||
SkipLogging: !setting.DisableRouterLog,
|
||||
},
|
||||
))
|
||||
// if setting.EnableGzip {
|
||||
// m.Use(macaron.Gzip())
|
||||
// }
|
||||
m.Use(macaron.Static(
|
||||
setting.AvatarUploadPath,
|
||||
macaron.StaticOptions{
|
||||
Prefix: "avatars",
|
||||
SkipLogging: !setting.DisableRouterLog,
|
||||
},
|
||||
))
|
||||
m.Use(macaron.Renderer(macaron.RenderOptions{
|
||||
Directory: path.Join(setting.StaticRootPath, "templates"),
|
||||
Funcs: []template.FuncMap{base.TemplateFuncs},
|
||||
@@ -104,18 +132,15 @@ func newMacaron() *macaron.Macaron {
|
||||
Redirect: true,
|
||||
}))
|
||||
m.Use(cache.Cacher(cache.Options{
|
||||
Adapter: setting.CacheAdapter,
|
||||
Interval: setting.CacheInternal,
|
||||
Conn: setting.CacheConn,
|
||||
Adapter: setting.CacheAdapter,
|
||||
AdapterConfig: setting.CacheConn,
|
||||
Interval: setting.CacheInternal,
|
||||
}))
|
||||
m.Use(captcha.Captchaer(captcha.Options{
|
||||
SubURL: setting.AppSubUrl,
|
||||
}))
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: setting.SessionProvider,
|
||||
Config: *setting.SessionConfig,
|
||||
}))
|
||||
m.Use(csrf.Generate(csrf.Options{
|
||||
m.Use(session.Sessioner(setting.SessionConfig))
|
||||
m.Use(csrf.Csrfer(csrf.Options{
|
||||
Secret: setting.SecretKey,
|
||||
SetCookie: true,
|
||||
Header: "X-Csrf-Token",
|
||||
@@ -129,14 +154,25 @@ func newMacaron() *macaron.Macaron {
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
// OAuth 2.
|
||||
if setting.OauthService != nil {
|
||||
for _, info := range setting.OauthService.OauthInfos {
|
||||
m.Use(oauth2.NewOAuth2Provider(info.Options, info.AuthUrl, info.TokenUrl))
|
||||
}
|
||||
}
|
||||
m.Use(middleware.Contexter())
|
||||
return m
|
||||
}
|
||||
|
||||
func runWeb(*cli.Context) {
|
||||
routers.GlobalInit()
|
||||
func runWeb(ctx *cli.Context) {
|
||||
checkVersion()
|
||||
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
routers.GlobalInit()
|
||||
|
||||
m := newMacaron()
|
||||
|
||||
reqSignIn := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true})
|
||||
@@ -144,74 +180,95 @@ func runWeb(*cli.Context) {
|
||||
ignSignInAndCsrf := middleware.Toggle(&middleware.ToggleOptions{DisableCsrf: true})
|
||||
reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true})
|
||||
|
||||
bind := binding.Bind
|
||||
bindIgnErr := binding.BindIgnErr
|
||||
|
||||
// Routers.
|
||||
m.Get("/", ignSignIn, routers.Home)
|
||||
m.Get("/explore", ignSignIn, routers.Explore)
|
||||
m.Get("/install", bindIgnErr(auth.InstallForm{}), routers.Install)
|
||||
m.Post("/install", bindIgnErr(auth.InstallForm{}), routers.InstallPost)
|
||||
m.Group("", func(r *macaron.Router) {
|
||||
r.Get("/pulls", user.Pulls)
|
||||
r.Get("/issues", user.Issues)
|
||||
m.Combo("/install", routers.InstallInit).
|
||||
Get(routers.Install).
|
||||
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
|
||||
m.Group("", func() {
|
||||
m.Get("/pulls", user.Pulls)
|
||||
m.Get("/issues", user.Issues)
|
||||
}, reqSignIn)
|
||||
|
||||
// API routers.
|
||||
m.Group("/api", func(_ *macaron.Router) {
|
||||
m.Group("/v1", func(r *macaron.Router) {
|
||||
// API.
|
||||
// FIXME: custom form error response.
|
||||
m.Group("/api", func() {
|
||||
m.Group("/v1", func() {
|
||||
// Miscellaneous.
|
||||
r.Post("/markdown", bindIgnErr(apiv1.MarkdownForm{}), v1.Markdown)
|
||||
r.Post("/markdown/raw", v1.MarkdownRaw)
|
||||
m.Post("/markdown", bindIgnErr(apiv1.MarkdownForm{}), v1.Markdown)
|
||||
m.Post("/markdown/raw", v1.MarkdownRaw)
|
||||
|
||||
// Users.
|
||||
m.Group("/users", func(r *macaron.Router) {
|
||||
r.Get("/search", v1.SearchUsers)
|
||||
m.Group("/users", func() {
|
||||
m.Get("/search", v1.SearchUsers)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Get("", v1.GetUserInfo)
|
||||
|
||||
m.Group("/tokens", func() {
|
||||
m.Combo("").Get(v1.ListAccessTokens).Post(bind(v1.CreateAccessTokenForm{}), v1.CreateAccessToken)
|
||||
}, middleware.ApiReqBasicAuth())
|
||||
})
|
||||
})
|
||||
|
||||
// Repositories.
|
||||
m.Group("/repos", func(r *macaron.Router) {
|
||||
r.Get("/search", v1.SearchRepos)
|
||||
r.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), v1.Migrate)
|
||||
m.Combo("/user/repos", middleware.ApiReqToken()).Get(v1.ListMyRepos).Post(bind(api.CreateRepoOption{}), v1.CreateRepo)
|
||||
m.Post("/org/:org/repos", middleware.ApiReqToken(), bind(api.CreateRepoOption{}), v1.CreateOrgRepo)
|
||||
m.Group("/repos", func() {
|
||||
m.Get("/search", v1.SearchRepos)
|
||||
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), v1.MigrateRepo)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Combo("/hooks").Get(v1.ListRepoHooks).Post(bind(api.CreateHookOption{}), v1.CreateRepoHook)
|
||||
m.Patch("/hooks/:id:int", bind(api.EditHookOption{}), v1.EditRepoHook)
|
||||
m.Get("/raw/*", middleware.RepoRef(), v1.GetRepoRawFile)
|
||||
}, middleware.ApiRepoAssignment(), middleware.ApiReqToken())
|
||||
})
|
||||
|
||||
r.Any("/*", func(ctx *middleware.Context) {
|
||||
ctx.JSON(404, &base.ApiJsonErr{"Not Found", v1.DOC_URL})
|
||||
m.Any("/*", func(ctx *middleware.Context) {
|
||||
ctx.JSON(404, &base.ApiJsonErr{"Not Found", base.DOC_URL})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// User routers.
|
||||
m.Group("/user", func(r *macaron.Router) {
|
||||
r.Get("/login", user.SignIn)
|
||||
r.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
|
||||
r.Get("/login/:name", user.SocialSignIn)
|
||||
r.Get("/sign_up", user.SignUp)
|
||||
r.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
|
||||
r.Get("/reset_password", user.ResetPasswd)
|
||||
r.Post("/reset_password", user.ResetPasswdPost)
|
||||
// User.
|
||||
m.Group("/user", func() {
|
||||
m.Get("/login", user.SignIn)
|
||||
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
|
||||
m.Get("/info/:name", user.SocialSignIn)
|
||||
m.Get("/sign_up", user.SignUp)
|
||||
m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
|
||||
m.Get("/reset_password", user.ResetPasswd)
|
||||
m.Post("/reset_password", user.ResetPasswdPost)
|
||||
}, reqSignOut)
|
||||
m.Group("/user/settings", func(r *macaron.Router) {
|
||||
r.Get("", user.Settings)
|
||||
r.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
|
||||
r.Get("/password", user.SettingsPassword)
|
||||
r.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
|
||||
r.Get("/ssh", user.SettingsSSHKeys)
|
||||
r.Post("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
|
||||
r.Get("/social", user.SettingsSocial)
|
||||
r.Route("/delete", "GET,POST", user.SettingsDelete)
|
||||
m.Group("/user/settings", func() {
|
||||
m.Get("", user.Settings)
|
||||
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
|
||||
m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), user.SettingsAvatar)
|
||||
m.Get("/email", user.SettingsEmails)
|
||||
m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
|
||||
m.Get("/password", user.SettingsPassword)
|
||||
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
|
||||
m.Get("/ssh", user.SettingsSSHKeys)
|
||||
m.Post("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
|
||||
m.Get("/social", user.SettingsSocial)
|
||||
m.Combo("/applications").Get(user.SettingsApplications).Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
|
||||
m.Route("/delete", "GET,POST", user.SettingsDelete)
|
||||
}, reqSignIn)
|
||||
m.Group("/user", func(r *macaron.Router) {
|
||||
m.Group("/user", func() {
|
||||
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
|
||||
r.Any("/activate", user.Activate)
|
||||
r.Get("/email2user", user.Email2User)
|
||||
r.Get("/forget_password", user.ForgotPasswd)
|
||||
r.Post("/forget_password", user.ForgotPasswdPost)
|
||||
r.Get("/logout", user.SignOut)
|
||||
m.Any("/activate", user.Activate)
|
||||
m.Any("/activate_email", user.ActivateEmail)
|
||||
m.Get("/email2user", user.Email2User)
|
||||
m.Get("/forget_password", user.ForgotPasswd)
|
||||
m.Post("/forget_password", user.ForgotPasswdPost)
|
||||
m.Get("/logout", user.SignOut)
|
||||
})
|
||||
|
||||
// FIXME: Legacy
|
||||
m.Get("/user/:username", ignSignIn, user.Profile)
|
||||
|
||||
// Gravatar service.
|
||||
avt := avatar.CacheServer("public/img/avatar/", "public/img/avatar_default.jpg")
|
||||
os.MkdirAll("public/img/avatar/", os.ModePerm)
|
||||
@@ -219,40 +276,40 @@ func runWeb(*cli.Context) {
|
||||
|
||||
adminReq := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true, AdminRequire: true})
|
||||
|
||||
m.Group("/admin", func(r *macaron.Router) {
|
||||
m.Group("/admin", func() {
|
||||
m.Get("", adminReq, admin.Dashboard)
|
||||
r.Get("/config", admin.Config)
|
||||
r.Get("/monitor", admin.Monitor)
|
||||
m.Get("/config", admin.Config)
|
||||
m.Get("/monitor", admin.Monitor)
|
||||
|
||||
m.Group("/users", func(r *macaron.Router) {
|
||||
r.Get("", admin.Users)
|
||||
r.Get("/new", admin.NewUser)
|
||||
r.Post("/new", bindIgnErr(auth.RegisterForm{}), admin.NewUserPost)
|
||||
r.Get("/:userid", admin.EditUser)
|
||||
r.Post("/:userid", bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
r.Post("/:userid/delete", admin.DeleteUser)
|
||||
m.Group("/users", func() {
|
||||
m.Get("", admin.Users)
|
||||
m.Get("/new", admin.NewUser)
|
||||
m.Post("/new", bindIgnErr(auth.RegisterForm{}), admin.NewUserPost)
|
||||
m.Get("/:userid", admin.EditUser)
|
||||
m.Post("/:userid", bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Post("/:userid/delete", admin.DeleteUser)
|
||||
})
|
||||
|
||||
m.Group("/orgs", func(r *macaron.Router) {
|
||||
r.Get("", admin.Organizations)
|
||||
m.Group("/orgs", func() {
|
||||
m.Get("", admin.Organizations)
|
||||
})
|
||||
|
||||
m.Group("/repos", func(r *macaron.Router) {
|
||||
r.Get("", admin.Repositories)
|
||||
m.Group("/repos", func() {
|
||||
m.Get("", admin.Repositories)
|
||||
})
|
||||
|
||||
m.Group("/auths", func(r *macaron.Router) {
|
||||
r.Get("", admin.Authentications)
|
||||
r.Get("/new", admin.NewAuthSource)
|
||||
r.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
r.Get("/:authid", admin.EditAuthSource)
|
||||
r.Post("/:authid", bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||
r.Post("/:authid/delete", admin.DeleteAuthSource)
|
||||
m.Group("/auths", func() {
|
||||
m.Get("", admin.Authentications)
|
||||
m.Get("/new", admin.NewAuthSource)
|
||||
m.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
m.Get("/:authid", admin.EditAuthSource)
|
||||
m.Post("/:authid", bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||
m.Post("/:authid/delete", admin.DeleteAuthSource)
|
||||
})
|
||||
|
||||
m.Group("/notices", func(r *macaron.Router) {
|
||||
r.Get("", admin.Notices)
|
||||
r.Get("/:id:int/delete", admin.DeleteNotice)
|
||||
m.Group("/notices", func() {
|
||||
m.Get("", admin.Notices)
|
||||
m.Get("/:id:int/delete", admin.DeleteNotice)
|
||||
})
|
||||
}, adminReq)
|
||||
|
||||
@@ -264,136 +321,138 @@ func runWeb(*cli.Context) {
|
||||
|
||||
reqTrueOwner := middleware.RequireTrueOwner()
|
||||
|
||||
// Organization routers.
|
||||
m.Group("/org", func(r *macaron.Router) {
|
||||
r.Get("/create", org.Create)
|
||||
r.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
|
||||
// Organization.
|
||||
m.Group("/org", func() {
|
||||
m.Get("/create", org.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
|
||||
|
||||
m.Group("/:org", func(r *macaron.Router) {
|
||||
r.Get("/dashboard", user.Dashboard)
|
||||
r.Get("/members", org.Members)
|
||||
r.Get("/members/action/:action", org.MembersAction)
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/dashboard", user.Dashboard)
|
||||
m.Get("/members", org.Members)
|
||||
m.Get("/members/action/:action", org.MembersAction)
|
||||
|
||||
r.Get("/teams", org.Teams)
|
||||
r.Get("/teams/:team", org.TeamMembers)
|
||||
r.Get("/teams/:team/repositories", org.TeamRepositories)
|
||||
r.Get("/teams/:team/action/:action", org.TeamsAction)
|
||||
r.Get("/teams/:team/action/repo/:action", org.TeamsRepoAction)
|
||||
m.Get("/teams", org.Teams)
|
||||
m.Get("/teams/:team", org.TeamMembers)
|
||||
m.Get("/teams/:team/repositories", org.TeamRepositories)
|
||||
m.Get("/teams/:team/action/:action", org.TeamsAction)
|
||||
m.Get("/teams/:team/action/repo/:action", org.TeamsRepoAction)
|
||||
}, middleware.OrgAssignment(true, true))
|
||||
|
||||
m.Group("/:org", func(r *macaron.Router) {
|
||||
r.Get("/teams/new", org.NewTeam)
|
||||
r.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
|
||||
r.Get("/teams/:team/edit", org.EditTeam)
|
||||
r.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
|
||||
r.Post("/teams/:team/delete", org.DeleteTeam)
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/teams/new", org.NewTeam)
|
||||
m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
|
||||
m.Get("/teams/:team/edit", org.EditTeam)
|
||||
m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
|
||||
m.Post("/teams/:team/delete", org.DeleteTeam)
|
||||
|
||||
m.Group("/settings", func(r *macaron.Router) {
|
||||
r.Get("", org.Settings)
|
||||
r.Post("", bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
|
||||
r.Get("/hooks", org.SettingsHooks)
|
||||
r.Get("/hooks/new", repo.WebHooksNew)
|
||||
r.Post("/hooks/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
r.Post("/hooks/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
r.Get("/hooks/:id", repo.WebHooksEdit)
|
||||
r.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
r.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
r.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||
m.Group("/settings", func() {
|
||||
m.Get("", org.Settings)
|
||||
m.Post("", bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
|
||||
m.Get("/hooks", org.SettingsHooks)
|
||||
m.Get("/hooks/new", repo.WebHooksNew)
|
||||
m.Post("/hooks/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/hooks/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Get("/hooks/:id", repo.WebHooksEdit)
|
||||
m.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||
})
|
||||
|
||||
r.Route("/invitations/new", "GET,POST", org.Invitation)
|
||||
m.Route("/invitations/new", "GET,POST", org.Invitation)
|
||||
}, middleware.OrgAssignment(true, true, true))
|
||||
}, reqSignIn)
|
||||
m.Group("/org", func(r *macaron.Router) {
|
||||
r.Get("/:org", org.Home)
|
||||
m.Group("/org", func() {
|
||||
m.Get("/:org", org.Home)
|
||||
}, middleware.OrgAssignment(true))
|
||||
|
||||
// Repository routers.
|
||||
m.Group("/repo", func(r *macaron.Router) {
|
||||
r.Get("/create", repo.Create)
|
||||
r.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||
r.Get("/migrate", repo.Migrate)
|
||||
r.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||
// Repository.
|
||||
m.Group("/repo", func() {
|
||||
m.Get("/create", repo.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||
m.Get("/migrate", repo.Migrate)
|
||||
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||
m.Get("/fork", repo.Fork)
|
||||
m.Post("/fork", bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
|
||||
}, reqSignIn)
|
||||
|
||||
m.Group("/:username/:reponame", func(r *macaron.Router) {
|
||||
r.Get("/settings", repo.Settings)
|
||||
r.Post("/settings", bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
|
||||
m.Group("/settings", func(r *macaron.Router) {
|
||||
r.Route("/collaboration", "GET,POST", repo.SettingsCollaboration)
|
||||
r.Get("/hooks", repo.Webhooks)
|
||||
r.Get("/hooks/new", repo.WebHooksNew)
|
||||
r.Post("/hooks/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
r.Post("/hooks/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
r.Get("/hooks/:id", repo.WebHooksEdit)
|
||||
r.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
r.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Get("/settings", repo.Settings)
|
||||
m.Post("/settings", bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
|
||||
m.Group("/settings", func() {
|
||||
m.Route("/collaboration", "GET,POST", repo.SettingsCollaboration)
|
||||
m.Get("/hooks", repo.Webhooks)
|
||||
m.Get("/hooks/new", repo.WebHooksNew)
|
||||
m.Post("/hooks/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/hooks/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Get("/hooks/:id", repo.WebHooksEdit)
|
||||
m.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
|
||||
m.Group("/hooks/git", func(r *macaron.Router) {
|
||||
r.Get("", repo.GitHooks)
|
||||
r.Get("/:name", repo.GitHooksEdit)
|
||||
r.Post("/:name", repo.GitHooksEditPost)
|
||||
m.Group("/hooks/git", func() {
|
||||
m.Get("", repo.GitHooks)
|
||||
m.Get("/:name", repo.GitHooksEdit)
|
||||
m.Post("/:name", repo.GitHooksEditPost)
|
||||
}, middleware.GitHookService())
|
||||
})
|
||||
}, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner)
|
||||
|
||||
m.Group("/:username/:reponame", func(r *macaron.Router) {
|
||||
r.Get("/action/:action", repo.Action)
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Get("/action/:action", repo.Action)
|
||||
|
||||
m.Group("/issues", func(r *macaron.Router) {
|
||||
r.Get("/new", repo.CreateIssue)
|
||||
r.Post("/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
||||
r.Post("/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
||||
r.Post("/:index/label", repo.UpdateIssueLabel)
|
||||
r.Post("/:index/milestone", repo.UpdateIssueMilestone)
|
||||
r.Post("/:index/assignee", repo.UpdateAssignee)
|
||||
r.Get("/:index/attachment/:id", repo.IssueGetAttachment)
|
||||
r.Post("/labels/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||
r.Post("/labels/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||
r.Post("/labels/delete", repo.DeleteLabel)
|
||||
r.Get("/milestones", repo.Milestones)
|
||||
r.Get("/milestones/new", repo.NewMilestone)
|
||||
r.Post("/milestones/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||
r.Get("/milestones/:index/edit", repo.UpdateMilestone)
|
||||
r.Post("/milestones/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost)
|
||||
r.Get("/milestones/:index/:action", repo.UpdateMilestone)
|
||||
m.Group("/issues", func() {
|
||||
m.Get("/new", repo.CreateIssue)
|
||||
m.Post("/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
||||
m.Post("/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
||||
m.Post("/:index/label", repo.UpdateIssueLabel)
|
||||
m.Post("/:index/milestone", repo.UpdateIssueMilestone)
|
||||
m.Post("/:index/assignee", repo.UpdateAssignee)
|
||||
m.Get("/:index/attachment/:id", repo.IssueGetAttachment)
|
||||
m.Post("/labels/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||
m.Post("/labels/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||
m.Post("/labels/delete", repo.DeleteLabel)
|
||||
m.Get("/milestones/new", repo.NewMilestone)
|
||||
m.Post("/milestones/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||
m.Get("/milestones/:index/edit", repo.UpdateMilestone)
|
||||
m.Post("/milestones/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost)
|
||||
m.Get("/milestones/:index/:action", repo.UpdateMilestone)
|
||||
})
|
||||
|
||||
r.Post("/comment/:action", repo.Comment)
|
||||
r.Get("/releases/new", repo.NewRelease)
|
||||
r.Get("/releases/edit/:tagname", repo.EditRelease)
|
||||
m.Post("/comment/:action", repo.Comment)
|
||||
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/new", repo.NewRelease)
|
||||
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||
m.Get("/edit/:tagname", repo.EditRelease)
|
||||
m.Post("/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
||||
}, middleware.RepoRef())
|
||||
}, reqSignIn, middleware.RepoAssignment(true))
|
||||
|
||||
m.Group("/:username/:reponame", func(r *macaron.Router) {
|
||||
r.Post("/releases/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||
r.Post("/releases/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
||||
}, reqSignIn, middleware.RepoAssignment(true, true))
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Get("/releases", middleware.RepoRef(), repo.Releases)
|
||||
m.Get("/issues", repo.Issues)
|
||||
m.Get("/issues/:index", repo.ViewIssue)
|
||||
m.Get("/issues/milestones", repo.Milestones)
|
||||
m.Get("/pulls", repo.Pulls)
|
||||
m.Get("/branches", repo.Branches)
|
||||
m.Get("/archive/*", repo.Download)
|
||||
m.Get("/issues2/", repo.Issues2)
|
||||
m.Get("/pulls2/", repo.PullRequest2)
|
||||
m.Get("/labels2/", repo.Labels2)
|
||||
m.Get("/milestone2/", repo.Milestones2)
|
||||
|
||||
m.Group("/:username/:reponame", func(r *macaron.Router) {
|
||||
r.Get("/issues", repo.Issues)
|
||||
r.Get("/issues/:index", repo.ViewIssue)
|
||||
r.Get("/pulls", repo.Pulls)
|
||||
r.Get("/branches", repo.Branches)
|
||||
r.Get("/archive/*", repo.Download)
|
||||
r.Get("/issues2/", repo.Issues2)
|
||||
m.Group("", func() {
|
||||
m.Get("/src/*", repo.Home)
|
||||
m.Get("/raw/*", repo.SingleDownload)
|
||||
m.Get("/commits/*", repo.RefCommits)
|
||||
m.Get("/commit/*", repo.Diff)
|
||||
}, middleware.RepoRef())
|
||||
|
||||
m.Get("/compare/:before([a-z0-9]+)...:after([a-z0-9]+)", repo.CompareDiff)
|
||||
}, ignSignIn, middleware.RepoAssignment(true))
|
||||
|
||||
m.Group("/:username/:reponame", func(r *macaron.Router) {
|
||||
r.Get("/src/:branchname", repo.Home)
|
||||
r.Get("/src/:branchname/*", repo.Home)
|
||||
r.Get("/raw/:branchname/*", repo.SingleDownload)
|
||||
r.Get("/commits/:branchname", repo.Commits)
|
||||
r.Get("/commits/:branchname/search", repo.SearchCommits)
|
||||
r.Get("/commits/:branchname/*", repo.FileHistory)
|
||||
r.Get("/commit/:branchname", repo.Diff)
|
||||
r.Get("/commit/:branchname/*", repo.Diff)
|
||||
r.Get("/releases", repo.Releases)
|
||||
r.Get("/compare/:before([a-z0-9]+)...:after([a-z0-9]+)", repo.CompareDiff)
|
||||
}, ignSignIn, middleware.RepoAssignment(true, true))
|
||||
|
||||
m.Group("/:username", func(r *macaron.Router) {
|
||||
r.Get("/:reponame", ignSignIn, middleware.RepoAssignment(true, true, true), repo.Home)
|
||||
r.Any("/:reponame/*", ignSignInAndCsrf, repo.Http)
|
||||
m.Group("/:username", func() {
|
||||
m.Get("/:reponame", ignSignIn, middleware.RepoAssignment(true, true), middleware.RepoRef(), repo.Home)
|
||||
m.Any("/:reponame/*", ignSignInAndCsrf, repo.Http)
|
||||
})
|
||||
|
||||
// robots.txt
|
||||
@@ -408,6 +467,12 @@ func runWeb(*cli.Context) {
|
||||
// Not found handler.
|
||||
m.NotFound(routers.NotFound)
|
||||
|
||||
// Flag for port number in case first time run conflict.
|
||||
if ctx.IsSet("port") {
|
||||
setting.AppUrl = strings.Replace(setting.AppUrl, setting.HttpPort, ctx.String("port"), 1)
|
||||
setting.HttpPort = ctx.String("port")
|
||||
}
|
||||
|
||||
var err error
|
||||
listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubUrl)
|
||||
@@ -415,7 +480,10 @@ func runWeb(*cli.Context) {
|
||||
case setting.HTTP:
|
||||
err = http.ListenAndServe(listenAddr, m)
|
||||
case setting.HTTPS:
|
||||
err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
|
||||
server := &http.Server{Addr: listenAddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m}
|
||||
err = server.ListenAndServeTLS(setting.CertFile, setting.KeyFile)
|
||||
case setting.FCGI:
|
||||
err = fcgi.Serve(nil, m)
|
||||
default:
|
||||
log.Fatal(4, "Invalid protocol: %s", setting.Protocol)
|
||||
}
|
||||
|
||||
64
conf/app.ini
64
conf/app.ini
@@ -1,3 +1,6 @@
|
||||
# NEVER EVER MODIFY THIS FILE
|
||||
# PLEASE MAKE CHANGES ON CORRESPONDING CUSTOM CONFIG FILE
|
||||
|
||||
; App name that shows on every page title
|
||||
APP_NAME = Gogs: Go Git Service
|
||||
; Change it if you run locally
|
||||
@@ -15,6 +18,8 @@ DOMAIN = localhost
|
||||
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
HTTP_ADDR =
|
||||
HTTP_PORT = 3000
|
||||
; Disable SSH feature when not available
|
||||
DISABLE_SSH = false
|
||||
SSH_PORT = 22
|
||||
; Disable CDN even in "prod" mode
|
||||
OFFLINE_MODE = false
|
||||
@@ -22,13 +27,20 @@ DISABLE_ROUTER_LOG = false
|
||||
; Generate steps:
|
||||
; $ cd path/to/gogs/custom/https
|
||||
; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com
|
||||
;
|
||||
; Or from a .pfx file exported from the Windows certificate store (do
|
||||
; not forget to export the private key):
|
||||
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
|
||||
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
||||
CERT_FILE = custom/https/cert.pem
|
||||
KEY_FILE = custom/https/key.pem
|
||||
; Upper level of template and static file path
|
||||
; default is the path where Gogs is executed
|
||||
STATIC_ROOT_PATH =
|
||||
; Application level GZIP support
|
||||
#ENABLE_GZIP = false
|
||||
ENABLE_GZIP = false
|
||||
; Landing page for non-logged users, can be "home" or "explore"
|
||||
LANDING_PAGE = home
|
||||
|
||||
[database]
|
||||
; Either "mysql", "postgres" or "sqlite3", it's your choice
|
||||
@@ -70,14 +82,15 @@ ENABLE_CACHE_AVATAR = false
|
||||
ENABLE_NOTIFY_MAIL = false
|
||||
; More detail: https://github.com/gogits/gogs/issues/165
|
||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
|
||||
; Repository Git hooks
|
||||
ENABLE_GIT_HOOKS = false
|
||||
ENABLE_REVERSE_PROXY_AUTO_REGISTERATION = false
|
||||
|
||||
[webhook]
|
||||
; Cron task interval in minutes
|
||||
TASK_INTERVAL = 1
|
||||
; Deliver timeout in seconds
|
||||
DELIVER_TIMEOUT = 5
|
||||
; Allow insecure certification
|
||||
SKIP_TLS_VERIFY = false
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
@@ -88,8 +101,11 @@ SUBJECT = %(APP_NAME)s
|
||||
; Mail server
|
||||
; Gmail: smtp.gmail.com:587
|
||||
; QQ: smtp.qq.com:25
|
||||
; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
|
||||
HOST =
|
||||
; Mail from address
|
||||
; Do not verify the certificate of the server. Only use this for self-signed certificates
|
||||
SKIP_VERIFY =
|
||||
; Mail from address, RFC 5322. This can be just an email address, or the "Name" <email@example.com> format
|
||||
FROM =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
@@ -120,13 +136,10 @@ TOKEN_URL = https://accounts.google.com/o/oauth2/token
|
||||
ENABLED = false
|
||||
CLIENT_ID =
|
||||
CLIENT_SECRET =
|
||||
SCOPES = all
|
||||
SCOPES = get_user_info
|
||||
; QQ 互联
|
||||
; AUTH_URL = https://graph.qq.com/oauth2.0/authorize
|
||||
; TOKEN_URL = https://graph.qq.com/oauth2.0/token
|
||||
; Tencent weibo
|
||||
AUTH_URL = https://open.t.qq.com/cgi-bin/oauth2/authorize
|
||||
TOKEN_URL = https://open.t.qq.com/cgi-bin/oauth2/access_token
|
||||
AUTH_URL = https://graph.qq.com/oauth2.0/authorize
|
||||
TOKEN_URL = https://graph.qq.com/oauth2.0/token
|
||||
|
||||
[oauth.weibo]
|
||||
ENABLED = false
|
||||
@@ -142,17 +155,17 @@ ADAPTER = memory
|
||||
; For "memory" only, GC interval in seconds, default is 60
|
||||
INTERVAL = 60
|
||||
; For "redis" and "memcache", connection host address
|
||||
; redis: `:6039`
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; memcache: `127.0.0.1:11211`
|
||||
HOST =
|
||||
|
||||
[session]
|
||||
; Either "memory", "file", "redis" or "mysql", default is "memory"
|
||||
PROVIDER = file
|
||||
PROVIDER = memory
|
||||
; Provider config options
|
||||
; memory: not have any config yet
|
||||
; file: session file path, e.g. `data/sessions`
|
||||
; redis: config like redis server addr, poolSize, password, e.g. `127.0.0.1:6379,100,gogs`
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
PROVIDER_CONFIG = data/sessions
|
||||
; Session cookie name
|
||||
@@ -165,14 +178,13 @@ ENABLE_SET_COOKIE = true
|
||||
GC_INTERVAL_TIME = 86400
|
||||
; Session life time, default is 86400
|
||||
SESSION_LIFE_TIME = 86400
|
||||
; session id hash func, Either "sha1", "sha256" or "md5" default is sha1
|
||||
SESSION_ID_HASHFUNC = sha1
|
||||
; Session hash key, default is use random string
|
||||
SESSION_ID_HASHKEY =
|
||||
|
||||
[picture]
|
||||
; The place to picture data, either "server" or "qiniu", default is "server"
|
||||
SERVICE = server
|
||||
AVATAR_UPLOAD_PATH = data/avatars
|
||||
; Chinese users can choose "duoshuo"
|
||||
GRAVATAR_SOURCE = gravatar
|
||||
DISABLE_GRAVATAR = false
|
||||
|
||||
[attachment]
|
||||
@@ -255,8 +267,20 @@ DRIVER =
|
||||
CONN =
|
||||
|
||||
[git]
|
||||
MAX_GITDIFF_LINES = 10000
|
||||
MAX_GIT_DIFF_LINES = 10000
|
||||
; Arguments for command 'git gc', e.g.: "--aggressive --auto"
|
||||
; see more on http://git-scm.com/docs/git-gc/1.7.5
|
||||
GC_ARGS =
|
||||
|
||||
; Git health check.
|
||||
[git.fsck]
|
||||
ENABLE = true
|
||||
; Execution interval in hours. Default is 24.
|
||||
INTERVAL = 24
|
||||
; Arguments for command 'git fsck', e.g.: "--unreachable --tags"
|
||||
; see more on http://git-scm.com/docs/git-fsck/1.7.5
|
||||
ARGS =
|
||||
|
||||
[i18n]
|
||||
LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL
|
||||
NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands
|
||||
LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL,lv-LV,ru-RU,ja-JP,es-ES
|
||||
NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本语,Español
|
||||
|
||||
10
conf/locale/TRANSLATORS
Normal file
10
conf/locale/TRANSLATORS
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file lists all PUBLIC individuals having contributed content to the translation.
|
||||
# Order of name is meaningless.
|
||||
|
||||
Akihiro YAGASAKI <yaggytter@momiage.com>
|
||||
Christoph Kisfeld <christoph.kisfeld@gmail.com>
|
||||
Huimin Wang <wanghm2009@hotmail.co.jp>
|
||||
Thomas Fanninger <gogs.thomas@fanninger.at>
|
||||
Łukasz Jan Niemier <lukasz@niemier.pl>
|
||||
Lafriks <lafriks@gmail.com>
|
||||
Miguel de la Cruz <miguel@mcrx.me>
|
||||
1302
conf/locale/locale_de-DE.ini
Normal file → Executable file
1302
conf/locale/locale_de-DE.ini
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ organization = Organization
|
||||
mirror = Mirror
|
||||
new_repo = New Repository
|
||||
new_migrate = New Migration
|
||||
new_fork = New Fork Repository
|
||||
new_org = New Organization
|
||||
manage_org = Manage Organizations
|
||||
admin_panel = Admin Panel
|
||||
@@ -41,7 +42,7 @@ cancel = Cancel
|
||||
[install]
|
||||
install = Installation
|
||||
title = Install Steps For First-time Run
|
||||
requite_db_desc = Gogs requires MySQL, PostgreSQL or SQLite3, but SQLite3 is usually available in the official binary version.
|
||||
requite_db_desc = Gogs requires MySQL, PostgreSQL or SQLite3.
|
||||
db_type = Database Type
|
||||
host = Host
|
||||
user = User
|
||||
@@ -58,13 +59,15 @@ run_user = Run User
|
||||
run_user_helper = The user must have access to Repository Root Path and run Gogs.
|
||||
domain = Domain
|
||||
domain_helper = This affects SSH clone URLs.
|
||||
http_port = HTTP Port
|
||||
http_port_helper = Port number which application will listen on.
|
||||
app_url = Application URL
|
||||
app_url_helper = This affects HTTP/HTTPS clone URL and somewhere in e-mail.
|
||||
email_title = Email Service Settings(Optional)
|
||||
email_title = E-mail Service Settings (Optional)
|
||||
smtp_host = SMTP Host
|
||||
mailer_user = Sender E-mail
|
||||
mailer_password = Sender Password
|
||||
notify_title = Notification Settings(Optional)
|
||||
mailer_password = Sender Password
|
||||
notify_title = Notification Settings (Optional)
|
||||
register_confirm = Enable Register Confirmation
|
||||
mail_notify = Enable Mail Notification
|
||||
admin_title = Admin Account Settings
|
||||
@@ -74,7 +77,7 @@ confirm_password = Confirm Password
|
||||
admin_email = E-mail
|
||||
install_gogs = Install Gogs
|
||||
test_git_failed = Fail to test 'git' command: %v
|
||||
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from http://gogs.io/docs/installation/install_from_binary.html, NOT the gobuild version.
|
||||
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from %s, NOT the gobuild version.
|
||||
invalid_db_setting = Database setting is not correct: %v
|
||||
invalid_repo_path = Repository root path is invalid: %v
|
||||
run_user_not_match = Run user isn't the current user: %s -> %s
|
||||
@@ -108,7 +111,7 @@ confirmation_mail_sent_prompt = A new confirmation e-mail has been sent to <b>%s
|
||||
sign_in_email = Sign in to your e-mail
|
||||
active_your_account = Activate Your Account
|
||||
resent_limit_prompt = Sorry, you are sending an activation e-mail too frequently. Please wait 3 minutes.
|
||||
has_unconfirmed_mail = Hi %s, you have an unconfirmed email address(<b>%s</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click on the button below.
|
||||
has_unconfirmed_mail = Hi %s, you have an unconfirmed e-mail address (<b>%s</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click on the button below.
|
||||
resend_mail = Click here to resend your activation e-mail
|
||||
email_not_associate = This e-mail address does not associate to any account.
|
||||
send_reset_mail = Click here to (re)send your password reset e-mail
|
||||
@@ -159,15 +162,20 @@ user_not_exist = Given user does not exist.
|
||||
last_org_owner = The user to remove is the last member in owner team. There must be another owner.
|
||||
|
||||
invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
|
||||
unable_verify_ssh_key = Gogs cannot verify your SSH key, but we assume that is valid, please make sure yourself.
|
||||
auth_failed = Authentication failed: %v
|
||||
|
||||
still_own_repo = Your account still have ownership of repository, you have to delete or transfer them first.
|
||||
still_has_org = Your account still have membership of organization, you have to left or delete them first.
|
||||
org_still_own_repo = This organization still have ownership of repository, you have to delete or transfer them first.
|
||||
|
||||
still_own_user = This authentication still has used by some users, you should move them and then delete again.
|
||||
|
||||
target_branch_not_exist = Target branch does not exist
|
||||
|
||||
[user]
|
||||
change_avatar = Change your avatar at gravatar.com
|
||||
change_custom_avatar = Change your avatar in settings
|
||||
join_on = Joined on
|
||||
repositories = Repositories
|
||||
activity = Public Activity
|
||||
@@ -180,32 +188,51 @@ profile = Profile
|
||||
password = Password
|
||||
ssh_keys = SSH Keys
|
||||
social = Social Accounts
|
||||
applications = Applications
|
||||
orgs = Organizations
|
||||
delete = Delete Account
|
||||
uid = Uid
|
||||
|
||||
public_profile = Public Profile
|
||||
profile_desc = Your Email address is public and will be used for any account related notifications, and any web based operations made via the site.
|
||||
profile_desc = Your E-mail address is public and will be used for any account related notifications, and any web based operations made via the site.
|
||||
full_name = Full Name
|
||||
website = Website
|
||||
location = Location
|
||||
update_profile = Update Profile
|
||||
update_profile_success = Your profile has been successfully updated.
|
||||
update_profile_success = Your profile has been updated successfully.
|
||||
change_username = Username Changed
|
||||
change_username_desc = Username has been changed, do you want to continue? This will affect all links relate to your account.
|
||||
continue = Continue
|
||||
cancel = Cancel
|
||||
|
||||
enable_custom_avatar = Enable Custom Avatar
|
||||
enable_custom_avatar_helper = Enable this to disable fetch from Gravatar
|
||||
choose_new_avatar = Choose new avatar
|
||||
update_avatar = Update Avatar Setting
|
||||
uploaded_avatar_not_a_image = Uploaded file is not a image.
|
||||
no_custom_avatar_available = No custom avatar available, cannot enable it.
|
||||
update_avatar_success = Your avatar setting has been updated successfully.
|
||||
|
||||
change_password = Change Password
|
||||
old_password = Current Password
|
||||
new_password = New Password
|
||||
password_incorrect = Current password is not correct.
|
||||
change_password_success = Password is changed successfully. You can now sign in via new password.
|
||||
|
||||
emails = E-mail Addresses
|
||||
manage_emails = Manage e-mail addresses
|
||||
email_desc = Your primary e-mail address will be used for notifications and other operations.
|
||||
primary = Primary
|
||||
primary_email = Set as primary
|
||||
delete_email = Delete
|
||||
add_new_email = Add new e-mail address
|
||||
add_email = Add e-mail
|
||||
add_email_success = Your new E-mail address was successfully added.
|
||||
|
||||
manage_ssh_keys = Manage SSH Keys
|
||||
add_key = Add Key
|
||||
ssh_desc = This is a list of SSH keys associated with your account. Remove any keys that you do not recognize.
|
||||
ssh_helper = <strong>Need help?</strong> Check out our guide to <a href="https://help.github.com/articles/generating-ssh-keys">generating SSH keys</a> or troubleshoot <a href="https://help.github.com/ssh-issues/">common SSH Problems</a>.
|
||||
ssh_helper = <strong>Need help?</strong> Check out our guide to <a href="%s">generating SSH keys</a> or troubleshoot <a href="%s">common SSH Problems</a>.
|
||||
add_new_key = Add SSH Key
|
||||
key_name = Key Name
|
||||
key_content = Content
|
||||
@@ -220,6 +247,16 @@ social_desc = This is a list of associated social accounts. Remove any binding t
|
||||
unbind = Unbind
|
||||
unbind_success = Social account has been unbound.
|
||||
|
||||
manage_access_token = Manage Personal Access Tokens
|
||||
generate_new_token = Generate New Token
|
||||
tokens_desc = Tokens you have generated that can be used to access the Gogs API.
|
||||
new_token_desc = As for now, every token will have full access to your account.
|
||||
token_name = Token Name
|
||||
generate_token = Generate Token
|
||||
generate_token_succees = New access token has been generated successfully! Make sure to copy your new personal access token now. You won't be able to see it again!
|
||||
delete_token = Delete
|
||||
delete_token_success = Personal access token has been deleted successfully! Don't forget to update your applications as well.
|
||||
|
||||
delete_account = Delete Your Account
|
||||
delete_prompt = The operation will delete your account permanently, and <strong>CANNOT</strong> be undone!
|
||||
confirm_delete_account = Confirm Deletion
|
||||
@@ -232,6 +269,9 @@ repo_name = Repository Name
|
||||
repo_name_helper = Great repository names are short, memorable and <strong>unique</strong>.
|
||||
visibility = Visibility
|
||||
visiblity_helper = This repository is <span class="label label-red label-radius">Private</span>
|
||||
fork_repo = Fork Repository
|
||||
fork_from = Fork From
|
||||
fork_visiblity_helper = Forked repository cannot change its visiblity
|
||||
repo_desc = Description
|
||||
repo_lang = Language
|
||||
repo_lang_helper = Select a .gitignore file
|
||||
@@ -240,7 +280,7 @@ license_helper = Select a license file
|
||||
init_readme = Initialize this repository with a README.md
|
||||
create_repo = Create Repository
|
||||
default_branch = Default Branch
|
||||
mirror_interval = Mirror Interval(hour)
|
||||
mirror_interval = Mirror Interval (hour)
|
||||
goget_meta = Go-Get Meta
|
||||
goget_meta_helper = This repository will be <span class="label label-blue label-radius">Go-Getable</span>
|
||||
|
||||
@@ -252,7 +292,7 @@ migrate_repo = Migrate Repository
|
||||
copy_link = Copy
|
||||
click_to_copy = Copy to clipboard
|
||||
copied = Copied OK
|
||||
clone_helper = Need help cloning? Visit <a target="_blank" href="http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository">Help</a>!
|
||||
clone_helper = Need help cloning? Visit <a target="_blank" href="%s">Help</a>!
|
||||
unwatch = Unwatch
|
||||
watch = Watch
|
||||
unstar = Unstar
|
||||
@@ -273,6 +313,9 @@ tags = Tags
|
||||
issues = Issues
|
||||
commits = Commits
|
||||
releases = Releases
|
||||
file_raw = Raw
|
||||
file_history = History
|
||||
file_view_raw = View Raw
|
||||
|
||||
commits.commits = Commits
|
||||
commits.search = Search commits
|
||||
@@ -301,24 +344,24 @@ settings.new_owner_has_same_repo = New owner already has a repository with same
|
||||
settings.delete = Delete This Repository
|
||||
settings.delete_desc = Once you delete a repository, there is no going back. Please be certain.
|
||||
settings.transfer_notices = <p>- You will lose access if new owner is a individual user.</p><p>- You will remain access if new owner is an organization and you're one of the owners.</p>
|
||||
settings.update_settings_success = Repository options has been successfully updated.
|
||||
settings.update_settings_success = Repository options has been updated successfully.
|
||||
settings.transfer_owner = New Owner
|
||||
settings.make_transfer = Make Transfer
|
||||
settings.transfer_succeed = Repository ownership has been successfully transferred.
|
||||
settings.transfer_succeed = Repository ownership has been transferred successfully.
|
||||
settings.confirm_delete = Confirm Deletion
|
||||
settings.add_collaborator = Add New Collaborator
|
||||
settings.add_collaborator_success = New collaborator has been added.
|
||||
settings.remove_collaborator_success = Collaborator has been removed.
|
||||
settings.user_is_org_member = User is organization member who cannot be added as a collaborator.
|
||||
settings.add_webhook = Add Webhook
|
||||
settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>.
|
||||
settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="%s">Webhooks Guide</a>.
|
||||
settings.githooks_desc = Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations.
|
||||
settings.githook_edit_desc = If hook is not active, sample content will be presented. Leave content to be blank will disable this hook.
|
||||
settings.githook_name = Hook Name
|
||||
settings.githook_content = Hook Content
|
||||
settings.update_githook = Update Hook
|
||||
settings.remove_hook_success = Webhook has been removed.
|
||||
settings.add_webhook_desc = We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>.
|
||||
settings.add_webhook_desc = We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="%s">Webhooks Guide</a>.
|
||||
settings.payload_url = Payload URL
|
||||
settings.content_type = Content Type
|
||||
settings.secret = Secret
|
||||
@@ -332,15 +375,48 @@ settings.update_hook_success = Webhook has been updated.
|
||||
settings.delete_webhook = Delete Webhook
|
||||
settings.recent_deliveries = Recent Deliveries
|
||||
settings.hook_type = Hook Type
|
||||
settings.add_slack_hook_desc = Add <a href="http://slack.com">Slack</a> integration to your repository.
|
||||
settings.add_slack_hook_desc = Add <a href="%s">Slack</a> integration to your repository.
|
||||
settings.slack_token = Token
|
||||
settings.slack_domain = Domain
|
||||
settings.slack_channel = Channel
|
||||
|
||||
diff.browse_source = Browse Source
|
||||
diff.parent = parent
|
||||
diff.commit = commit
|
||||
diff.data_not_available = Diff Data Not Available.
|
||||
diff.show_diff_stats = Show Diff Stats
|
||||
diff.stats_desc = <strong> %d changed files</strong> with <strong>%d additions</strong> and <strong>%d deletions</strong>
|
||||
diff.bin = BIN
|
||||
diff.view_file = View File
|
||||
|
||||
release.releases = Releases
|
||||
release.new_release = New Release
|
||||
release.draft = Draft
|
||||
release.prerelease = Pre-Release
|
||||
release.stable = Stable
|
||||
release.edit = edit
|
||||
release.ahead = <strong>%d</strong> commits to %s since this release
|
||||
release.source_code = Source Code
|
||||
release.tag_name = Tag name
|
||||
release.target = Target
|
||||
release.tag_helper = Choose an existing tag, or create a new tag on publish.
|
||||
release.release_title = Release title
|
||||
release.content_with_md = Content with <a href="%s">Markdown</a>
|
||||
release.write = Write
|
||||
release.preview = Preview
|
||||
release.content_placeholder = Write some content
|
||||
release.loading = Loading...
|
||||
release.prerelease_desc = This is a pre-release
|
||||
release.prerelease_helper = We’ll point out that this release is identified as non-production ready.
|
||||
release.publish = Publish Release
|
||||
release.save_draft = Save Draft
|
||||
release.edit_release = Edit Release
|
||||
release.tag_name_already_exist = Release with this tag name has already existed.
|
||||
|
||||
[org]
|
||||
org_name_holder = Organization Name
|
||||
org_name_helper = Great organization names are short and memorable.
|
||||
org_email_helper = Organization's Email receives all notifications and confirmations.
|
||||
org_email_helper = Organization's E-mail receives all notifications and confirmations.
|
||||
create_org = Create Organization
|
||||
repo_updated = Updated
|
||||
people = People
|
||||
@@ -364,7 +440,7 @@ settings.location = Location
|
||||
settings.update_settings = Update Settings
|
||||
settings.change_orgname = Organization Name Changed
|
||||
settings.change_orgname_desc = Organization name has been changed, do you want to continue? This will affect all links relate to this organization.
|
||||
settings.update_setting_success = Organization setting has been successfully updated.
|
||||
settings.update_setting_success = Organization setting has been updated successfully.
|
||||
settings.delete = Delete Organization
|
||||
settings.delete_account = Delete This Organization
|
||||
settings.delete_prompt = The operation will delete this organization permanently, and <strong>CANNOT</strong> be undone!
|
||||
@@ -402,7 +478,7 @@ teams.delete_team = Delete This Team
|
||||
teams.add_team_member = Add Team Member
|
||||
teams.delete_team_title = Team Deletion
|
||||
teams.delete_team_desc = This team is going to be deleted, do you want to continue? Members of this team may lose access to some repositories.
|
||||
teams.delete_team_success = Given team has been successfully deleted.
|
||||
teams.delete_team_success = Given team has been deleted successfully.
|
||||
teams.read_permission_desc = This team grants <strong>Read</strong> access: members can view and clone the team's repositories.
|
||||
teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to the team's repositories.
|
||||
teams.admin_permission_desc = This team grants <strong>Admin</strong> access: members can read from, push to, and add collaborators to the team's repositories.
|
||||
@@ -431,7 +507,18 @@ dashboard.operation_name = Operation Name
|
||||
dashboard.operation_switch = Switch
|
||||
dashboard.operation_run = Run
|
||||
dashboard.clean_unbind_oauth = Clean unbound OAuthes
|
||||
dashboard.clean_unbind_oauth_success = All unbind OAuthes have been deleted successfully.
|
||||
dashboard.delete_inactivate_accounts = Delete all inactive accounts
|
||||
dashboard.delete_inactivate_accounts_success = All inactivate accounts have been deleted successfully.
|
||||
dashboard.delete_repo_archives = Delete all repositories archives
|
||||
dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully.
|
||||
dashboard.git_gc_repos = Do garbage collection on repositories
|
||||
dashboard.git_gc_repos_success = All repositories have done garbage collection successfully.
|
||||
dashboard.resync_all_sshkeys = Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost)
|
||||
dashboard.resync_all_sshkeys_success = All public keys have been rewritten successfully.
|
||||
dashboard.resync_all_update_hooks = Rewrite all update hook of repositories (needed when custom config path is changed)
|
||||
dashboard.resync_all_update_hooks_success = All repositories' update hook have been rewritten successfully.
|
||||
|
||||
dashboard.server_uptime = Server Uptime
|
||||
dashboard.current_goroutine = Current Goroutines
|
||||
dashboard.current_memory_usage = Current Memory Usage
|
||||
@@ -473,13 +560,15 @@ users.edit = Edit
|
||||
users.auth_source = Authorization Source
|
||||
users.local = Local
|
||||
users.auth_login_name = Authorization Login Name
|
||||
users.update_profile_success = Account profile has been successfully updated.
|
||||
users.update_profile_success = Account profile has been updated successfully.
|
||||
users.edit_account = Edit Account
|
||||
users.is_activated = This account is activated
|
||||
users.is_admin = This account has administrator permissions
|
||||
users.allow_git_hook = This account has permissions to create Git hooks
|
||||
users.update_profile = Update Account Profile
|
||||
users.delete_account = Delete This Account
|
||||
users.still_own_repo = This account still have ownership of repository, you have to delete or transfer them first.
|
||||
users.still_has_org = This account still have membership of organization, you have to left or delete them first.
|
||||
|
||||
orgs.org_manage_panel = Organization Manage Panel
|
||||
orgs.name = Name
|
||||
@@ -517,7 +606,7 @@ auths.enable_auto_register = Enable Auto Registration
|
||||
auths.tips = Tips
|
||||
auths.edit = Edit Authorization Setting
|
||||
auths.activated = This authentication has activated
|
||||
auths.update_success = Authorization setting has been successfully updated.
|
||||
auths.update_success = Authorization setting has been updated successfully.
|
||||
auths.update = Update Authorization Setting
|
||||
auths.delete = Delete This Authorization
|
||||
auths.delete_auth_title = Authorization Deletion
|
||||
@@ -547,8 +636,9 @@ config.db_ssl_mode_helper = (for "postgres" only)
|
||||
config.db_path = Path
|
||||
config.db_path_helper = (for "sqlite3" only)
|
||||
config.service_config = Service Configuration
|
||||
config.register_email_confirm = Register Email Confirmation
|
||||
config.register_email_confirm = Require E-mail Confirmation
|
||||
config.disable_register = Disable Registration
|
||||
config.show_registration_button = Show Register Button
|
||||
config.require_sign_in_view = Require Sign In View
|
||||
config.mail_notify = Mail Notification
|
||||
config.enable_cache_avatar = Enable Cache Avatar
|
||||
@@ -557,6 +647,7 @@ config.reset_password_code_lives = Reset Password Code Lives
|
||||
config.webhook_config = Webhook Configuration
|
||||
config.task_interval = Task Interval
|
||||
config.deliver_timeout = Deliver Timeout
|
||||
config.skip_tls_verify = Skip TLS Verify
|
||||
config.mailer_config = Mailer Configuration
|
||||
config.mailer_enabled = Enabled
|
||||
config.mailer_name = Name
|
||||
@@ -577,8 +668,6 @@ config.gc_interval_time = GC Interval Time
|
||||
config.session_life_time = Session Life Time
|
||||
config.https_only = HTTPS Only
|
||||
config.cookie_life_time = Cookie Life Time
|
||||
config.session_hash_function = Session ID Hash Function
|
||||
config.session_hash_key = Session ID Hash Key
|
||||
config.picture_config = Picture Configuration
|
||||
config.picture_service = Picture Service
|
||||
config.disable_gravatar = Disable Gravatar
|
||||
@@ -601,14 +690,16 @@ notices.type = Type
|
||||
notices.type_1 = Repository
|
||||
notices.desc = Description
|
||||
notices.op = Op.
|
||||
notices.delete_success = System notice has been successfully deleted.
|
||||
notices.delete_success = System notice has been deleted successfully.
|
||||
|
||||
[action]
|
||||
create_repo = created repository <a href="%s/%s">%s</a>
|
||||
commit_repo = pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a>
|
||||
create_issue = opened issue <a href="%s/%s/issues/%s">%s#%s</a>
|
||||
comment_issue = commented on issue <a href="%s/%s/issues/%s">%s#%s</a>
|
||||
create_issue = `opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
comment_issue = `commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
transfer_repo = transfered repository <code>%s</code> to <a href="/%s%s">%s</a>
|
||||
push_tag = pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a>
|
||||
compare_2_commits = View comparison for these 2 commits
|
||||
|
||||
[tool]
|
||||
ago = ago
|
||||
@@ -630,16 +721,3 @@ months = %d months %s
|
||||
years = %d years %s
|
||||
raw_seconds = seconds
|
||||
raw_minutes = minutes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
724
conf/locale/locale_es-ES.ini
Executable file
724
conf/locale/locale_es-ES.ini
Executable file
@@ -0,0 +1,724 @@
|
||||
app_desc=Un servicio de Git auto alojado y sin complicaciones
|
||||
|
||||
home=Incio
|
||||
dashboard=Panel de control
|
||||
explore=Explorar
|
||||
help=Ayuda
|
||||
sign_in=Iniciar sesión
|
||||
social_sign_in=Inicio de sesión social: 2° paso <small>cuenta de asociado</small>
|
||||
sign_out=Cerrar sesión
|
||||
sign_up=Suscripción
|
||||
register=Registro
|
||||
website=Pagina Web
|
||||
version=Versión
|
||||
page=Página
|
||||
template=Plantilla
|
||||
language=Lenguaje
|
||||
|
||||
username=Nombre de usuario
|
||||
email=Correo electrónico
|
||||
password=Contraseña
|
||||
re_type=Ingrese de nuevo
|
||||
captcha=Captcha
|
||||
|
||||
repository=Repositorio
|
||||
organization=Organización
|
||||
mirror=Espejo
|
||||
new_repo=Nuevo repositorio
|
||||
new_migrate=Nueva Migración
|
||||
new_fork=Nuevo Fork del Repositorio
|
||||
new_org=Nueva organización
|
||||
manage_org=Administrar organizaciones
|
||||
admin_panel=Panel de administración
|
||||
account_settings=Configuraciones de la cuenta
|
||||
settings=Configuraciones
|
||||
|
||||
news_feed=entrada de noticias
|
||||
pull_requests=Solicitudes de retiro
|
||||
issues=Publicaciones
|
||||
|
||||
cancel=Cancelar
|
||||
|
||||
[install]
|
||||
install=Instalación
|
||||
title=Pasos de la instalación por primera vez
|
||||
requite_db_desc=Gogs necesita MySQL, PostgreSQL o SQLite3.
|
||||
db_type=Tipo de base de datos
|
||||
host=Anfitrión
|
||||
user=Usuario
|
||||
password=Contraseña
|
||||
db_name=Nombre de la base de datos
|
||||
db_helper=Por favor utilice el motor INNODB con la configuración de caracteres utf8_general_ci para MySQL.
|
||||
ssl_mode=Modo SSL
|
||||
path=Ruta
|
||||
sqlite_helper=Ruta del archivo de la base de datos de SQLite3.
|
||||
general_title=Configuraciones Generales de Gogs
|
||||
repo_path=Ruta del repositorio de Raiz (Root)
|
||||
repo_path_helper=Todos los repositorios remotos de Git se guardarán en este directorio.
|
||||
run_user=Abrir el usuario
|
||||
run_user_helper=El usuario necesita tener acceso a la Ruta Raíz del Repositorio y ejecutar Gogs.
|
||||
domain=Dominio
|
||||
domain_helper=Esto afecta a las URLs para clonar por SSH.
|
||||
http_port=Puerto HTTP
|
||||
http_port_helper=Puerto en el que escuchará la aplicación.
|
||||
app_url=URL de la aplicación
|
||||
app_url_helper=Esto afecta a las URLs para clonar por HTTP/HTTPS y a algunos correos electrónicos.
|
||||
email_title=Configuración del Servicio de Correo (Opcional)
|
||||
smtp_host=SMTP Host
|
||||
mailer_user=Remitente del Correo Electrónico
|
||||
mailer_password=Contraseña del Remitente
|
||||
notify_title=Configuración de Notificaciones (Opcional)
|
||||
register_confirm=Habilitar la Confirmación en el Registro
|
||||
mail_notify=Habilitar las Notificaciones de Correo
|
||||
admin_title=Configuración de la Cuenta de Administrador
|
||||
admin_name=Nombre de usuario
|
||||
admin_password=Contraseña
|
||||
confirm_password=Confirmar Contraseña
|
||||
admin_email=Correo electrónico
|
||||
install_gogs=Instalar Gogs
|
||||
test_git_failed=Fallo al probar el comando 'git': %v
|
||||
sqlite3_not_available=Tu versión no soporta SQLite3, por favor descarga el binario oficial desde %s, NO la versión de gobuild.
|
||||
invalid_db_setting=La configuración de la base de datos no es correcta: %v
|
||||
invalid_repo_path=La ruta de la raíz del repositorio es inválida: %v
|
||||
run_user_not_match=El usuario que está ejecutando la aplicación no es el usuario actual: %s -> %s
|
||||
save_config_failed=Error al guardar la configuración: %v
|
||||
invalid_admin_setting=La configuración de la cuenta de administración es inválida: %v
|
||||
install_success=Bienvenido! Estamos encantados de que hayas escogido Gogs, diviértete y cuídate.
|
||||
|
||||
[home]
|
||||
uname_holder=Nombre de usuario o correo electrónico
|
||||
password_holder=Contraseña
|
||||
switch_dashboard_context=Cambiar el contexto del Dashboard
|
||||
my_repos=Mis Repositorios
|
||||
collaborative_repos=Repositorios Colaborativos
|
||||
my_orgs=Mis Organizaciones
|
||||
my_mirrors=Mis Mirrors
|
||||
|
||||
[explore]
|
||||
repos=Repositorios
|
||||
|
||||
[auth]
|
||||
create_new_account=Crear una Nueva Cuenta
|
||||
register_hepler_msg=¿Ya tienes una cuenta? ¡Inicia sesión!
|
||||
social_register_hepler_msg=¿Ya tienes una cuenta? ¡Enlázala!
|
||||
disable_register_prompt=Lo sentimos, el registro está deshabilitado. Por favor, contacta con el administrador del sitio.
|
||||
disable_register_mail=Lo sentimos. Los correos de Confirmación de Registro están deshabilitados.
|
||||
remember_me=Recuérdame
|
||||
forgot_password=He olvidado mi contraseña
|
||||
forget_password=¿Has olvidado tu contraseña?
|
||||
sign_up_now=¿Necesitas una cuenta? Regístrate ahora.
|
||||
confirmation_mail_sent_prompt=Un nuevo correo de confirmación se ha enviado a <b>%s</b>. Por favor, comprueba tu bandeja de entrada en las siguientes %d horas para completar el proceso de registro.
|
||||
sign_in_email=Inicia sesión con tu correo electrónico
|
||||
active_your_account=Activa tu cuenta
|
||||
resent_limit_prompt=Lo sentimos, estás solicitando el reenvío del mail de activación con demasiada frecuencia. Por favor, espera 3 minutos.
|
||||
has_unconfirmed_mail=Hola %s, tu correo electrónico (<b>%s</b>) no está confirmado. Si no has recibido un correo de confirmación o necesitas que lo enviemos de nuevo, por favor, haz click en el siguiente botón.
|
||||
resend_mail=Haz click aquí para reenviar tu correo electrónico de activación
|
||||
email_not_associate=Esta dirección de correo electrónico no esta asociada a cuenta alguna.
|
||||
send_reset_mail=Haga clic aquí para (re)enviar el correo para el restablecimiento de la contraseña
|
||||
reset_password=Restablecer su contraseña
|
||||
invalid_code=Lo sentimos, su código de confirmación ha expirado o no es valido.
|
||||
reset_password_helper=Haga Clic aquí para restablecer su contraseña
|
||||
password_too_short=La longitud de la contraseña no puede ser menor a 6.
|
||||
|
||||
[form]
|
||||
UserName=Nombre de usuario
|
||||
RepoName=Nombre del repositorio
|
||||
Email=Dirección de correo electrónico
|
||||
Password=Contraseña
|
||||
Retype=Vuelva a escribir la contraseña
|
||||
SSHTitle=Nombre de la Clave de SSH
|
||||
HttpsUrl=HTTPS URL
|
||||
PayloadUrl=URL de carga
|
||||
TeamName=Nombre del equipo
|
||||
AuthName=Nombre de autorización
|
||||
AdminEmail=Correo electrónico del administrador
|
||||
|
||||
require_error=` no puede estar vacío.`
|
||||
alpha_dash_error=` los caracteres deben ser Alfanumericos o dash(-_).`
|
||||
alpha_dash_dot_error=` debe ser un caracter alfanumérivo válido, un guión alto o bajo (-_) o un signo de puntuación.`
|
||||
min_size_error=` debe contener al menos %s caracteres.`
|
||||
max_size_error=` debe contener como máximo %s caracteres.`
|
||||
email_error=` no es una dirección de correo válida.`
|
||||
url_error=` no es una URL válida.`
|
||||
unknown_error=Error desconocido:
|
||||
captcha_incorrect=El captcha no es válido.
|
||||
password_not_match=La contraseña de confirmación no coincide.
|
||||
|
||||
username_been_taken=Ya existe un usuario con este nombre.
|
||||
repo_name_been_taken=Ya existe un repositorio con este nombre.
|
||||
org_name_been_taken=Ya existe una organización con este nombre.
|
||||
team_name_been_taken=Ya existe un equipo con este nombre.
|
||||
email_been_used=Esta dirección de correo electrónico ya está en uso.
|
||||
ssh_key_been_used=Este nombre de clave pública ya está en uso.
|
||||
illegal_username=Tu nombre de usuario contiene caracteres inválidos.
|
||||
illegal_repo_name=El nombre del repositorio contiene caracteres inválidos.
|
||||
illegal_org_name=El nombre de la organización contiene caracteres inválidos.
|
||||
illegal_team_name=El nombre del equipo contiene caracteres inválidos.
|
||||
username_password_incorrect=Nombre de usuario o contraseña incorrectos.
|
||||
enterred_invalid_repo_name=Por favor, asegúrate de que has introducido correctamente el nombre del repositorio.
|
||||
enterred_invalid_owner_name=Por favor, asegúrate de que has introducido correctamente el nombre del propietario.
|
||||
enterred_invalid_password=Por favor, asegúrate de que has introducido correctamente tu contraseña.
|
||||
user_not_exist=El usuario indicado no existe.
|
||||
last_org_owner=El usuario que se intenta eliminar es el último miembro del equipo de propietarios. Debe existir otro propietario.
|
||||
|
||||
invalid_ssh_key=Lo sentimos, no somos capaces de verificar tu clave SSH: %s
|
||||
unable_verify_ssh_key=Gogs no puede velificar tu clave SSH, pero asumimos que es válida. Por favor, asegúrate de que es así.
|
||||
auth_failed=Error de autenticación: %v
|
||||
|
||||
still_own_repo=Tu cuenta es la propietaria de uno o más repositorios, tienes que borrarlos o transferirlos primero.
|
||||
still_has_org=Tu cuenta es miembro de una o más organizaciones, tienes que abandonarlas o eliminarlas primero.
|
||||
org_still_own_repo=Esta organización es dueña de uno o más repositorios, tienes que eliminarlos o transferirlos primero.
|
||||
|
||||
still_own_user=Esta autenticación está en uso por algunos usuarios, debes moverlos y antes de eliminarla.
|
||||
|
||||
target_branch_not_exist=La rama de destino no existe
|
||||
|
||||
[user]
|
||||
change_avatar=Cambia tu avatar en gravatar.com
|
||||
change_custom_avatar=Cambia tu avatar en la configuración
|
||||
join_on=Registrado en
|
||||
repositories=Repositorios
|
||||
activity=Actividad pública
|
||||
followers=Seguidores
|
||||
starred=Destacados
|
||||
following=Siguiendo
|
||||
|
||||
[settings]
|
||||
profile=Perfil
|
||||
password=Contraseña
|
||||
ssh_keys=Claves SSH
|
||||
social=Redes Sociales
|
||||
applications=Aplicaciones
|
||||
orgs=Organizaciones
|
||||
delete=Eliminar Cuenta
|
||||
uid=UUID
|
||||
|
||||
public_profile=Perfil Público
|
||||
profile_desc=Tu correo electrónico es público y será usado para todas las notificaciones relacionadas con cualquier cuenta y cualquier operación hecha a través de la web.
|
||||
full_name=Nombre Completo
|
||||
website=Página Web
|
||||
location=Localización
|
||||
update_profile=Actualizar Perfil
|
||||
update_profile_success=Tu perfil se ha actualizado correctamente.
|
||||
change_username=Nombre de usuario modificado
|
||||
change_username_desc=El nombre de usuario ha sido modificado, ¿quieres continuar? Esta acción afectará a todos los enlaces relacionados con tu cuenta.
|
||||
continue=Continuar
|
||||
cancel=Cancelar
|
||||
|
||||
enable_custom_avatar=Activar Avatar Personalizado
|
||||
enable_custom_avatar_helper=Activa esto para desactivar los avatares de Gravatar
|
||||
choose_new_avatar=Selecciona nuevo avatar
|
||||
update_avatar=Actualizar Configuración del Avatar
|
||||
uploaded_avatar_not_a_image=El archivo enviado no es una imagen.
|
||||
no_custom_avatar_available=No hay ningún avatar personalizado disponible, no se puede habilitar.
|
||||
update_avatar_success=La configuración de tu avatar se ha actualizado correctamente.
|
||||
|
||||
change_password=Cambiar contraseña
|
||||
old_password=Contraseña actual
|
||||
new_password=Nueva contraseña
|
||||
password_incorrect=Contraseña actual incorrecta.
|
||||
change_password_success=La contraseña se ha modificado correctamente. Ya puedes iniciar sesión con tu nueva contraseña.
|
||||
|
||||
emails=Direcciones de correo electrónico
|
||||
manage_emails=Gestionar direcciones de correo electrónico
|
||||
email_desc=Tu dirección de correo principal se utilizará para las notificaciones y otras operaciones.
|
||||
primary=Principal
|
||||
primary_email=Marcar como principal
|
||||
delete_email=Eliminar
|
||||
add_new_email=Añadir nueva dirección de correo electrónico
|
||||
add_email=Añadir correo electrónico
|
||||
add_email_success=Tu nuevo correo electrónico se ha añadido correctamente.
|
||||
|
||||
manage_ssh_keys=Gestionar Claves SSH
|
||||
add_key=Añadir Clave
|
||||
ssh_desc=Esta es la lista de claves SSH asociadas con tu cuenta. Elimina cualquier clave que no reconozcas.
|
||||
ssh_helper=<strong>¿Necesitas ayuda?</strong>. Consulta nuestra guía para <a href="%s">generar claves SSH</a> o solucionar <a href="%s">problemas comunes de SSH</a>.
|
||||
add_new_key=Añadir clave SSH
|
||||
key_name=Nombre de la Clave
|
||||
key_content=Contenido
|
||||
add_key_success=¡Se ha añadido una nueva clave SSH!
|
||||
delete_key=Eliminar
|
||||
add_on=Añadido en
|
||||
last_used=Utilizado por última vez en
|
||||
no_activity=No hay actividad reciente
|
||||
|
||||
manage_social=Gestionar Redes Sociales asociadas
|
||||
social_desc=Esta es una lista de las Redes Sociales asociadas. Elimina cualquier vínculo que no reconozcas.
|
||||
unbind=Desvincular
|
||||
unbind_success=La Red Social ha sido desvinculada.
|
||||
|
||||
manage_access_token=Gestionar los Tokens de Acceso personales
|
||||
generate_new_token=Generar nuevo Token
|
||||
tokens_desc=Tokens generados que pueden ser usados para acceder al API de Gogs.
|
||||
new_token_desc=Desde ahora, todos los tokens tendrán acceso completo a tu cuenta.
|
||||
token_name=Nombre del Token
|
||||
generate_token=Generar Token
|
||||
generate_token_succees=¡Los nuevos tokens de acceso se han generado correctamente! Asegúrate de copiar tu nuevo token de acceso personal. ¡No podrás verlo de nuevo!
|
||||
delete_token=Eliminar
|
||||
delete_token_success=¡Los tokens de acceso personales se han eliminado correctamente! No olvides actualizar las aplicaciones que los usasen.
|
||||
|
||||
delete_account=Elimina tu cuenta
|
||||
delete_prompt=La operación eliminará tu cuenta de forma permanente y ¡<strong>NO</strong> se puede deshacer!
|
||||
confirm_delete_account=Confirmar Eliminación
|
||||
delete_account_title=Eliminación de Cuenta
|
||||
delete_account_desc=Esta cuenta se va a eliminar permanentemente, ¿quieres continuar?
|
||||
|
||||
[repo]
|
||||
owner=Propietario
|
||||
repo_name=Nombre del Repositorio
|
||||
repo_name_helper=Los grandes nombres de repositorios son cortos, memorables y <strong>únicos</strong>.
|
||||
visibility=Visibilidad
|
||||
visiblity_helper=Este repositorio es <span class="label label-red label-radius">Privado</span>
|
||||
fork_repo=Hacer Fork del repositorio
|
||||
fork_from=Crear un Fork desde
|
||||
fork_visiblity_helper=No es posible cambiar la visibilidad de un Fork
|
||||
repo_desc=Descripción
|
||||
repo_lang=Idioma
|
||||
repo_lang_helper=Selecciona un fichero .gitignore
|
||||
license=Licencia
|
||||
license_helper=Selecciona un fichero de licencia
|
||||
init_readme=Crear este repositorio con un fichero README.md
|
||||
create_repo=Crear Repositorio
|
||||
default_branch=Rama por defecto
|
||||
mirror_interval=Intervalo de mirror(en horas)
|
||||
goget_meta=Go-Get Meta
|
||||
goget_meta_helper=Este repositorio será <span class="label label-blue label-radius">Go-Getable</span>
|
||||
|
||||
need_auth=Requiere Autorización
|
||||
migrate_type=Tipo de Migración
|
||||
migrate_type_helper=Este repositorio será un <span class="label label-blue label-radius">Mirror</span>
|
||||
migrate_repo=Migrar Repositorio
|
||||
|
||||
copy_link=Copiar
|
||||
click_to_copy=Copiar al portapapeles
|
||||
copied=Copiado correctamente
|
||||
clone_helper=¿Necesitas ayuda con el clone? ¡Consulta la <a target="_blank" href="%s">Ayuda</a>!
|
||||
unwatch=Dejar de vigilar
|
||||
watch=Vigilar
|
||||
unstar=Eliminar destacado
|
||||
star=Destacar
|
||||
fork=Fork
|
||||
|
||||
no_desc=Sin Descripción
|
||||
quick_guide=Guía Rápida
|
||||
clone_this_repo=Clonar este repositorio
|
||||
create_new_repo_command=Crear un nuevo repositorio desde línea de comandos
|
||||
push_exist_repo=Hacer Push de un repositorio existente desde línea de comandos
|
||||
|
||||
branch=Rama
|
||||
tree=Árbol
|
||||
branch_and_tags=Ramas y Etiquetas
|
||||
branches=Ramas
|
||||
tags=Etiquetas
|
||||
issues=Incidencias
|
||||
commits=Commits
|
||||
releases=Releases
|
||||
file_raw=Raw
|
||||
file_history=Histórico
|
||||
file_view_raw=Ver Raw
|
||||
|
||||
commits.commits=Commits
|
||||
commits.search=Buscar Commits
|
||||
commits.find=Buscar
|
||||
commits.author=Autor
|
||||
commits.message=Mensaje
|
||||
commits.date=Fecha
|
||||
commits.older=Anterior
|
||||
commits.newer=Posterior
|
||||
|
||||
settings=Configuración
|
||||
settings.options=Opciones
|
||||
settings.collaboration=Colaboración
|
||||
settings.hooks=Webhooks
|
||||
settings.githooks=Git Hooks
|
||||
settings.deploy_keys=Claves de Despliegue
|
||||
settings.basic_settings=Configuración Básica
|
||||
settings.danger_zone=Zona de Peligro
|
||||
settings.site=Sitio Oficial
|
||||
settings.update_settings=Actualizar Configuración
|
||||
settings.change_reponame=Nombre del Repositorio Modificado
|
||||
settings.change_reponame_desc=El nombre del repositorio ha sido modificado, ¿quieres continuar? Esto afectará a todos los enlaces relacionados con este repositorio.
|
||||
settings.transfer=Transferir la Propiedad
|
||||
settings.transfer_desc=Transferir este repositorio a otro usuario u organización donde tengas permisos de administración.
|
||||
settings.new_owner_has_same_repo=El nuevo propietario tiene un repositorio con el mismo nombre.
|
||||
settings.delete=Eliminar este Repositorio
|
||||
settings.delete_desc=Una vez has eliminado un repositorio, no hay vuelta atrás. Por favor, asegúrate de que es lo que quieres.
|
||||
settings.transfer_notices=<p>- Perderás acceso si el nuevo propietario es un usuario individual.</p><p>- Seguirás teniendo acceso si el nuevo propietario es una organización y estás en el grupo de los propietarios.</p>
|
||||
settings.update_settings_success=Las opciones del repositorio se han actualizado correctamente.
|
||||
settings.transfer_owner=Nuevo Propietario
|
||||
settings.make_transfer=Transferir
|
||||
settings.transfer_succeed=La propiedad del repositorio ha sido transferida exitosamente.
|
||||
settings.confirm_delete=Confirmar Eliminación
|
||||
settings.add_collaborator=Añadir Nuevo Colaborador
|
||||
settings.add_collaborator_success=Se ha añadido el nuevo colaborador.
|
||||
settings.remove_collaborator_success=Se ha eliminado el colaborador.
|
||||
settings.user_is_org_member=El usuario es miembro de la organización, no puede ser añadido como colaborador.
|
||||
settings.add_webhook=Añadir Webhook
|
||||
settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificaciones cuando sucedan ciertos eventos en Gogs. Cuando sucedan los eventos especificados, enviaremos una petición POST a cada una de las URLs indicadas. Para obtener más información, consulta nuestra <a target="_blank" href="%s">Guía de Webhooks</a>.
|
||||
settings.githooks_desc=Los Git Hooks son una funcionalidad del propio Git, puedes editar los ficheros de los hooks soportados en la siguiente lista para aplicar operaciones personalizadas.
|
||||
settings.githook_edit_desc=Si el hook no está activo, se mostrará contenido de ejemplo. Dejar el contenido vacío deshabilitará este hook.
|
||||
settings.githook_name=Nombre del Hook
|
||||
settings.githook_content=Contenido del Hook
|
||||
settings.update_githook=Actualizar Hook
|
||||
settings.remove_hook_success=El Webhook ha sido eliminado.
|
||||
settings.add_webhook_desc=Enviaremos una petición <code>POST</code> a la siguiente URL con los detalles de cualquier evento suscrito. También puedes especificar qué formato de datos te gustaría recibir (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). Puedes encontrar más información en la <a target="_blank" href="%s">Guía de Webhooks</a>.
|
||||
settings.payload_url=URL de Payload
|
||||
settings.content_type=Tipo de Contenido
|
||||
settings.secret=Secreto
|
||||
settings.event_desc=¿Qué eventos te gustaría que desencadenasen este webhook?
|
||||
settings.event_push_only=Solo el evento <code>push</code>.
|
||||
settings.active=Activo
|
||||
settings.active_helper=Enviaremos detalles del evento cuando este hook se dispare.
|
||||
settings.add_hook_success=Se ha añadido un nuevo webhook.
|
||||
settings.update_webhook=Actualizar Webhook
|
||||
settings.update_hook_success=Se ha actualizado el Webhook.
|
||||
settings.delete_webhook=Borrar Webhook
|
||||
settings.recent_deliveries=Envíos Recientes
|
||||
settings.hook_type=Tipo de Hook
|
||||
settings.add_slack_hook_desc=Añade integración con <a href="%s">Slack</a> a tu repositorio.
|
||||
settings.slack_token=Token
|
||||
settings.slack_domain=Dominio
|
||||
settings.slack_channel=Canal
|
||||
|
||||
diff.browse_source=Explorar el Código
|
||||
diff.parent=padre
|
||||
diff.commit=commit
|
||||
diff.data_not_available=Los datos del Diff no están disponibles.
|
||||
diff.show_diff_stats=Mostrar Estadísticas de Diff
|
||||
diff.stats_desc=Se han <strong>modificado %d ficheros</strong> con <strong>%d adiciones</strong> y <strong>%d borrados</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Ver Fichero
|
||||
|
||||
release.releases=Releases
|
||||
release.new_release=Nueva Release
|
||||
release.draft=Borrador
|
||||
release.prerelease=Pre-Release
|
||||
release.stable=Estable
|
||||
release.edit=editar
|
||||
release.ahead=<strong>%d</strong> commits en %s desde esta release
|
||||
release.source_code=Código Fuente
|
||||
release.tag_name=Nombre de la etiqueta
|
||||
release.target=Destino
|
||||
release.tag_helper=Escoge una etiqueta o crea una nueva al publicar.
|
||||
release.release_title=Título de la Release
|
||||
release.content_with_md=Contenido con formato <a href="%s">Markdown</a>
|
||||
release.write=Escribir
|
||||
release.preview=Vista Previa
|
||||
release.content_placeholder=Escribe algo de contenido
|
||||
release.loading=Cargando...
|
||||
release.prerelease_desc=Esta es una pre-release
|
||||
release.prerelease_helper=Esta release está marcada como no apta para producción.
|
||||
release.publish=Publicar Release
|
||||
release.save_draft=Guardar Borrador
|
||||
release.edit_release=Editar Release
|
||||
release.tag_name_already_exist=Ya existe una Release con esta etiqueta.
|
||||
|
||||
[org]
|
||||
org_name_holder=Nombre de la Organización
|
||||
org_name_helper=Los grandes nombres de organizaciones son cortos y memorables.
|
||||
org_email_helper=Los correos electrónicos de las organizaciones reciben todas las notificaciones y confirmaciones.
|
||||
create_org=Crear Organización
|
||||
repo_updated=Actualizado
|
||||
people=Personas
|
||||
invite_someone=Invitar a alguien
|
||||
teams=Equipos
|
||||
lower_members=miembros
|
||||
lower_repositories=repositorios
|
||||
create_new_team=Crear un Nuevo Equipo
|
||||
org_desc=Descripción
|
||||
team_name=Nombre del Equipo
|
||||
team_desc=Descripción
|
||||
team_name_helper=Utiliza este nombre para mencionar a este equipo en las conversaciones.
|
||||
team_desc_helper=¿En qué consiste este equipo?
|
||||
team_permission_desc=¿Qué nivel de permisos debería tener este equipo?
|
||||
|
||||
settings=Configuración
|
||||
settings.options=Opciones
|
||||
settings.full_name=Nombre Completo
|
||||
settings.website=Sitio Web
|
||||
settings.location=Localización
|
||||
settings.update_settings=Actualizar Configuración
|
||||
settings.change_orgname=Nombre de la Organización Modificado
|
||||
settings.change_orgname_desc=El nombre de la organización ha sido modificado, ¿quieres continuar? Esta acción afectará a todos los enlaces relacionados con esta organización.
|
||||
settings.update_setting_success=La configuración de la Organización se ha actualizado correctamente.
|
||||
settings.delete=Eliminar Organización
|
||||
settings.delete_account=Eliminar esta Organización
|
||||
settings.delete_prompt=Esta operación eliminará esta organización de manera permanente, y ¡<strong>NO PUEDE</strong> deshacerse!
|
||||
settings.confirm_delete_account=Confirmar Eliminación
|
||||
settings.delete_org_title=Eliminación de la Organización
|
||||
settings.delete_org_desc=Esta organización se va a eliminar permanentemente, ¿quieres continuar?
|
||||
settings.hooks_desc=Añadir webhooks que serán ejecutados para <strong>todos los repositorios</strong> de esta organización.
|
||||
|
||||
members.public=Público
|
||||
members.public_helper=convertir en privado
|
||||
members.private=Privado
|
||||
members.private_helper=convertir en público
|
||||
members.owner=Propietario
|
||||
members.member=Miembro
|
||||
members.conceal=Ocultar
|
||||
members.remove=Eliminar
|
||||
members.leave=Abandonar
|
||||
members.invite_desc=Comienza a teclear un nombre de usuario para invitar a un nuevo miembro a %s:
|
||||
members.invite_now=Invitar
|
||||
|
||||
teams.join=Unirse
|
||||
teams.leave=Abandonar
|
||||
teams.read_access=Acceso de Lectura
|
||||
teams.read_access_helper=Este equipo podrá ver y clonar sus repositorios.
|
||||
teams.write_access=Acceso de Escritura
|
||||
teams.write_access_helper=Este equipo podrá leer sus repositorios, así como hacer push en ellos.
|
||||
teams.admin_access=Acceso de Administrador
|
||||
teams.admin_access_helper=Este equipo podrá hacer push/pull en sus repositorios, así como añadir colaboradores a ellos.
|
||||
teams.no_desc=Este equipo no tiene descripción
|
||||
teams.settings=Configuración
|
||||
teams.owners_permission_desc=Los propietarios tienen acceso completo a <strong>todos los repositorios</strong> y tienen <strong>derechos de administración</strong> en la organización.
|
||||
teams.members=Miembros del Equipo
|
||||
teams.update_settings=Actualizar Configuración
|
||||
teams.delete_team=Borrar este Equipo
|
||||
teams.add_team_member=Añadir Miembro al Equipo
|
||||
teams.delete_team_title=Eliminar Equipo
|
||||
teams.delete_team_desc=Este equipo va a ser eliminado, ¿seguro que quieres continuar? Los miembros de este equipo pueden perder acceso a algunos repositorios.
|
||||
teams.delete_team_success=El Equipo se ha eliminado correctamente.
|
||||
teams.read_permission_desc=Este equipo tiene permisos de <strong>Lectura</strong>: sus miembros pueden ver y clonar los repositorios del equipo.
|
||||
teams.write_permission_desc=Este equipo tiene permisos de <strong>Escritura</strong>: sus miembros pueden leer y hacer push a los repositorios del equipo.
|
||||
teams.admin_permission_desc=Este equipo tiene permisos de <strong>Administración</strong>: sus miembros pueden leer, hacer push y añadir colaboradores a los repositorios del equipo.
|
||||
teams.repositories=Repositorios del Equipo
|
||||
teams.add_team_repository=Añadir Repositorio al Equipo
|
||||
teams.remove_repo=Eliminar
|
||||
teams.add_nonexistent_repo=El repositorio que estás intentando añadir no existe, por favor, créalo primero.
|
||||
|
||||
[admin]
|
||||
dashboard=Dashboard
|
||||
users=Usuarios
|
||||
organizations=Organizaciones
|
||||
repositories=Repositorios
|
||||
authentication=Autenticaciones
|
||||
config=Configuración
|
||||
notices=Avisos del Sistema
|
||||
monitor=Monitorización
|
||||
prev=Anterior
|
||||
next=Siguiente
|
||||
|
||||
dashboard.statistic=Estadísticas
|
||||
dashboard.operations=Operaciones
|
||||
dashboard.system_status=Estado del Monitor del Sistema
|
||||
dashboard.statistic_info=La base de datos de Gogs contiene <b>%d</b> usuarios, <b>%d</b> organizaciones, <b>%d</b> claves públicas, <b>%d</b> repositorios, <b>%d</b> vigilados, <b>%d</b> destacados, <b>%d</b> acciones, <b>%d</b> accesos, <b>%d</b> incidencias, <b>%d</b> comentarios, <b>%d</b> cuentas de redes sociales, <b>%d</b> seguidores, <b>%d</b> mirrors, <b>%d</b> releases, <b>%d</b> fuentes de login, <b>%d</b> webhooks, <b>%d</b> milestones, <b>%d</b> etiquetas, <b>%d</b> hooks, <b>%d</b> equipos, <b>%d</b> tareas actualizadas, <b>%d</b> adjuntos.
|
||||
dashboard.operation_name=Nombre de la Operación
|
||||
dashboard.operation_switch=Interruptor
|
||||
dashboard.operation_run=Ejecutar
|
||||
dashboard.clean_unbind_oauth=Limpiar solicitudes de OAuth sin confirmar
|
||||
dashboard.clean_unbind_oauth_success=Las solicitudes de OAuth sin confirmar se han eliminado correctamente.
|
||||
dashboard.delete_inactivate_accounts=Eliminar todas las cuentas inactivas
|
||||
dashboard.delete_inactivate_accounts_success=Todas las cuentas inactivas se han eliminado correctamente.
|
||||
dashboard.delete_repo_archives=Eliminar todos los archivos de repositorios
|
||||
dashboard.delete_repo_archives_success=Todos los archivos de repositorios se han eliminado correctamente.
|
||||
dashboard.git_gc_repos=Ejecutar la recolección de basura en los repositorios
|
||||
dashboard.git_gc_repos_success=Todos los repositorios han ejecutado correctamente el recolector de basuras.
|
||||
dashboard.resync_all_sshkeys=Reescribir el fichero '.ssh/authorized_key'(atención: se perderán las claves que no pertenezcan a Gogs)
|
||||
dashboard.resync_all_sshkeys_success=Todas las claves públicas se han reescrito correctamente.
|
||||
dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
|
||||
dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
|
||||
|
||||
dashboard.server_uptime=Uptime del Servidor
|
||||
dashboard.current_goroutine=Gorutinas Actuales
|
||||
dashboard.current_memory_usage=Uso de Memoria Actual
|
||||
dashboard.total_memory_allocated=Total de Memoria Reservada
|
||||
dashboard.memory_obtained=Memoria Obtenida
|
||||
dashboard.pointer_lookup_times=Tiempos de Búsqueda de Punteros
|
||||
dashboard.memory_allocate_times=Tiempos de Reserva de Memoria
|
||||
dashboard.memory_free_times=Tiempos de Liberado de Memoria
|
||||
dashboard.current_heap_usage=Uso de Heap Actual
|
||||
dashboard.heap_memory_obtained=Memoria de Heap Obtenida
|
||||
dashboard.heap_memory_idle=Memoria de Heap Inactiva
|
||||
dashboard.heap_memory_in_use=Memoria de Heap en Uso
|
||||
dashboard.heap_memory_released=Memoria de Heap Liberada
|
||||
dashboard.heap_objects=Objetos en el Heap
|
||||
dashboard.bootstrap_stack_usage=Uso de la Pila de Bootstrap
|
||||
dashboard.stack_memory_obtained=Memoria de Pila Obtenida
|
||||
dashboard.mspan_structures_usage=Uso de Estructuras MSpan
|
||||
dashboard.mspan_structures_obtained=Estructuras MSpan Obtenidas
|
||||
dashboard.mcache_structures_usage=Uso de estructuras MCache
|
||||
dashboard.mcache_structures_obtained=Estructuras MCache Obtenidas
|
||||
dashboard.profiling_bucket_hash_table_obtained=Profiling Bucket Hash Table Obtenido
|
||||
dashboard.gc_metadata_obtained=Metadatos del Recolector de Basuras Obtenidos
|
||||
dashboard.other_system_allocation_obtained=Otros Recursos del Sistema Asignados
|
||||
dashboard.next_gc_recycle=Siguiente Reciclado del Recolector de Basuras
|
||||
dashboard.last_gc_time=Tiempo desde el Último GC
|
||||
dashboard.total_gc_time=Pausa Total por GC
|
||||
dashboard.total_gc_pause=Pausa Total por GC
|
||||
dashboard.last_gc_pause=Última Pausa por GC
|
||||
dashboard.gc_times=GC Times
|
||||
|
||||
users.user_manage_panel=User Manage Panel
|
||||
users.new_account=Create New Account
|
||||
users.name=Name
|
||||
users.activated=Activated
|
||||
users.admin=Admin
|
||||
users.repos=Repos
|
||||
users.created=Created
|
||||
users.edit=Edit
|
||||
users.auth_source=Authorization Source
|
||||
users.local=Local
|
||||
users.auth_login_name=Authorization Login Name
|
||||
users.update_profile_success=Account profile has been updated successfully.
|
||||
users.edit_account=Editar Cuenta
|
||||
users.is_activated=Esta cuenta está activada
|
||||
users.is_admin=This account has administrator permissions
|
||||
users.allow_git_hook=This account has permissions to create Git hooks
|
||||
users.update_profile=Update Account Profile
|
||||
users.delete_account=Delete This Account
|
||||
users.still_own_repo=This account still have ownership of repository, you have to delete or transfer them first.
|
||||
users.still_has_org=This account still have membership of organization, you have to left or delete them first.
|
||||
|
||||
orgs.org_manage_panel=Organization Manage Panel
|
||||
orgs.name=Name
|
||||
orgs.teams=Teams
|
||||
orgs.members=Members
|
||||
|
||||
repos.repo_manage_panel=Repository Manage Panel
|
||||
repos.owner=Owner
|
||||
repos.name=Name
|
||||
repos.private=Private
|
||||
repos.watches=Watches
|
||||
repos.stars=Stars
|
||||
repos.issues=Issues
|
||||
|
||||
auths.auth_manage_panel=Authorization Manage Panel
|
||||
auths.new=Add New Authorization Source
|
||||
auths.name=Name
|
||||
auths.type=Type
|
||||
auths.enabled=Enabled
|
||||
auths.updated=Updated
|
||||
auths.auth_type=Authorization Type
|
||||
auths.auth_name=Authorization Name
|
||||
auths.domain=Domain
|
||||
auths.host=Host
|
||||
auths.port=Port
|
||||
auths.base_dn=Base DN
|
||||
auths.attributes=Search Attributes
|
||||
auths.filter=Search Filter
|
||||
auths.ms_ad_sa=Ms Ad SA
|
||||
auths.smtp_auth=SMTP Authorization Type
|
||||
auths.smtphost=SMTP Host
|
||||
auths.smtpport=SMTP Port
|
||||
auths.enable_tls=Enable TLS Encryption
|
||||
auths.enable_auto_register=Enable Auto Registration
|
||||
auths.tips=Consejos
|
||||
auths.edit=Editar la Configuración de Autorización
|
||||
auths.activated=Esta autenticación ha sido activada
|
||||
auths.update_success=La Configuración de Autorización ha sido actualizada correctamente.
|
||||
auths.update=Actualizar la Configuración de Autorización
|
||||
auths.delete=Eliminar esta Autorización
|
||||
auths.delete_auth_title=Eliminación de Autorización
|
||||
auths.delete_auth_desc=Se va a eliminar esta autorización, ¿quieres continuar?
|
||||
|
||||
config.server_config=Configuración del Servidor
|
||||
config.app_name=Nombre de la Aplicación
|
||||
config.app_ver=Versión de la Aplicación
|
||||
config.app_url=URL de la Aplicación
|
||||
config.domain=Dominio
|
||||
config.offline_mode=Modo Sin Conexión
|
||||
config.disable_router_log=Deshabilitar Log del Router
|
||||
config.run_user=Usuario de Ejecución
|
||||
config.run_mode=Modo de Ejecución
|
||||
config.repo_root_path=Ruta del Repositorio
|
||||
config.static_file_root_path=Ruta de los Ficheros Estáticos
|
||||
config.log_file_root_path=Ruta de los Ficheros de Log
|
||||
config.script_type=Tipo de Script
|
||||
config.reverse_auth_user=Reverse Authentication User
|
||||
config.db_config=Configuración de la Base de Datos
|
||||
config.db_type=Tipo
|
||||
config.db_host=Host
|
||||
config.db_name=Nombre
|
||||
config.db_user=Usuario
|
||||
config.db_ssl_mode=Modo SSL
|
||||
config.db_ssl_mode_helper=(solo para "postgres")
|
||||
config.db_path=Ruta
|
||||
config.db_path_helper=(solo para "sqlite3")
|
||||
config.service_config=Configuración del Servicio
|
||||
config.register_email_confirm=Solicitar Confirmación por Correo Electrónico
|
||||
config.disable_register=Deshabilitar el Registro
|
||||
config.show_registration_button=Mostrar Botón de Registro
|
||||
config.require_sign_in_view=Solicitar la Vista de Inicio de Sesión
|
||||
config.mail_notify=Notificación por Correo Electrónico
|
||||
config.enable_cache_avatar=Activar la Caché de Avatar
|
||||
config.active_code_lives=Active Code Lives
|
||||
config.reset_password_code_lives=Reset Password Code Lives
|
||||
config.webhook_config=Webhook Configuration
|
||||
config.task_interval=Task Interval
|
||||
config.deliver_timeout=Deliver Timeout
|
||||
config.skip_tls_verify=Skip TLS Verify
|
||||
config.mailer_config=Mailer Configuration
|
||||
config.mailer_enabled=Enabled
|
||||
config.mailer_name=Name
|
||||
config.mailer_host=Host
|
||||
config.mailer_user=User
|
||||
config.oauth_config=OAuth Configuration
|
||||
config.oauth_enabled=Enabled
|
||||
config.cache_config=Cache Configuration
|
||||
config.cache_adapter=Cache Adapter
|
||||
config.cache_interval=Cache Interval
|
||||
config.cache_conn=Cache Connection
|
||||
config.session_config=Session Configuration
|
||||
config.session_provider=Session Provider
|
||||
config.provider_config=Provider Config
|
||||
config.cookie_name=Cookie Name
|
||||
config.enable_set_cookie=Enable Set Cookie
|
||||
config.gc_interval_time=GC Interval Time
|
||||
config.session_life_time=Session Life Time
|
||||
config.https_only=HTTPS Only
|
||||
config.cookie_life_time=Cookie Life Time
|
||||
config.picture_config=Picture Configuration
|
||||
config.picture_service=Picture Service
|
||||
config.disable_gravatar=Disable Gravatar
|
||||
config.log_config=Log Configuration
|
||||
config.log_mode=Log Mode
|
||||
|
||||
monitor.cron=Cron Tasks
|
||||
monitor.name=Name
|
||||
monitor.schedule=Schedule
|
||||
monitor.next=Next Time
|
||||
monitor.previous=Previous Time
|
||||
monitor.execute_times=Execute Times
|
||||
monitor.process=Running Processes
|
||||
monitor.desc=Description
|
||||
monitor.start=Start Time
|
||||
monitor.execute_time=Execution Time
|
||||
|
||||
notices.system_notice_list=System Notices
|
||||
notices.type=Type
|
||||
notices.type_1=Repository
|
||||
notices.desc=Description
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notice has been deleted successfully.
|
||||
|
||||
[action]
|
||||
create_repo=created repository <a href="%s/%s">%s</a>
|
||||
commit_repo=pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a>
|
||||
create_issue=`opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
comment_issue=`commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
transfer_repo=transfered repository <code>%s</code> to <a href="/%s%s">%s</a>
|
||||
push_tag=pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a>
|
||||
compare_2_commits=View comparison for these 2 commits
|
||||
|
||||
[tool]
|
||||
ago=ago
|
||||
from_now=from now
|
||||
now=now
|
||||
1s=1 second %s
|
||||
1m=1 minute %s
|
||||
1h=1 hour %s
|
||||
1d=1 day %s
|
||||
1w=1 week %s
|
||||
1mon=1 month %s
|
||||
1y=1 year %s
|
||||
seconds=%d seconds %s
|
||||
minutes=%d minutes %s
|
||||
hours=%d hours %s
|
||||
days=%d days %s
|
||||
weeks=%d weeks %s
|
||||
months=%d months %s
|
||||
years=%d years %s
|
||||
raw_seconds=seconds
|
||||
raw_minutes=minutes
|
||||
|
||||
1240
conf/locale/locale_fr-CA.ini
Normal file → Executable file
1240
conf/locale/locale_fr-CA.ini
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
724
conf/locale/locale_ja-JP.ini
Executable file
724
conf/locale/locale_ja-JP.ini
Executable file
@@ -0,0 +1,724 @@
|
||||
app_desc=Go言語で実装したセルフホストGitサーバ
|
||||
|
||||
home=ホーム
|
||||
dashboard=ダッシュボード
|
||||
explore=エスクプローラ
|
||||
help=ヘルプ
|
||||
sign_in=サインイン
|
||||
social_sign_in=SNSでサインイン: ステップ2 <small>アカウント連携</small>
|
||||
sign_out=サインアウト
|
||||
sign_up=サインアップ
|
||||
register=登録
|
||||
website=WEBサイト
|
||||
version=バージョン
|
||||
page=ページ
|
||||
template=テンプレート
|
||||
language=言語
|
||||
|
||||
username=ユーザ名
|
||||
email=E-mail
|
||||
password=パスワード
|
||||
re_type=再入力
|
||||
captcha=キャプチャ
|
||||
|
||||
repository=リポジトリ
|
||||
organization=組織
|
||||
mirror=ミラー
|
||||
new_repo=新しいリポジトリ
|
||||
new_migrate=新しい移行
|
||||
new_fork=新しいフォークのリポジトリ
|
||||
new_org=新しい組織
|
||||
manage_org=組織を管理
|
||||
admin_panel=管理者パネル
|
||||
account_settings=アカウント設定
|
||||
settings=設定
|
||||
|
||||
news_feed=ニュースのフィード
|
||||
pull_requests=プルリクエスト
|
||||
issues=課題
|
||||
|
||||
cancel=キャンセル
|
||||
|
||||
[install]
|
||||
install=インストール
|
||||
title=初回実行のインストール手順
|
||||
requite_db_desc=Gogs には、MySQL や PostgreSQL 、SQLite3 が必要です。
|
||||
db_type=データベースの種類
|
||||
host=ホスト
|
||||
user=ユーザ
|
||||
password=パスワード
|
||||
db_name=データベース名
|
||||
db_helper=Mysql INNODB エンジン utf8_general_ci の文字セットを使用してください。
|
||||
ssl_mode=SSL モード
|
||||
path=パス
|
||||
sqlite_helper=SQLite3 データベースのファイル パス
|
||||
general_title=Gogs の全般設定
|
||||
repo_path=リポジトリのルートパス
|
||||
repo_path_helper=すべての Git リモート リポジトリはこのディレクトリに保存されます。
|
||||
run_user=実行ユーザ
|
||||
run_user_helper=ユーザーはリポジトリ ルートパスへのアクセス、及びGogs を実行する権限を所有する必要があります。
|
||||
domain=ドメイン
|
||||
domain_helper=これはSSHクローンURLに影響する。
|
||||
http_port=HTTP ポート
|
||||
http_port_helper=アプリケーションが待ち受けするポート番号。
|
||||
app_url=アプリケーションの URL
|
||||
app_url_helper=この設定は、HTTP / HTTPSのクローンURLおよび、一部のメールボックスへのリンクに影響を与えます。
|
||||
email_title=E-mailサービス設定(Optional)
|
||||
smtp_host=SMTP ホスト
|
||||
mailer_user=送信者の電子メール
|
||||
mailer_password=送信者のパスワード
|
||||
notify_title=通知 Settings(Optional)
|
||||
register_confirm=登録の確認を有効にする
|
||||
mail_notify=メール通知を有効にする
|
||||
admin_title=管理者アカウントの設定
|
||||
admin_name=ユーザ名
|
||||
admin_password=パスワード
|
||||
confirm_password=パスワード確認
|
||||
admin_email=E-mail
|
||||
install_gogs=Gogs をインストール
|
||||
test_git_failed='Git' コマンドテストに失敗: %v
|
||||
sqlite3_not_available=このリリース バージョンは SQLite3 をサポートしていません。gobuild バージョンではない、公式のバイナリ バージョンを %s からダウンロードしてください。
|
||||
invalid_db_setting=データベースの設定が正しくありません: %v
|
||||
invalid_repo_path=リポジトリのルート パスが無効です: %v
|
||||
run_user_not_match=実行ユーザーは、現在のユーザーではない: %s-> %s
|
||||
save_config_failed=構成の保存に失敗した: %v
|
||||
invalid_admin_setting=管理者アカウントの設定が無効です: %v
|
||||
install_success=ようこそ!我々はあなたが Gogs を選んでくれて嬉しいです!楽しみましょう!
|
||||
|
||||
[home]
|
||||
uname_holder=ユーザー名またはEメール
|
||||
password_holder=パスワード
|
||||
switch_dashboard_context=ダッシュ ボードのコンテキストを切替
|
||||
my_repos=私のリポジトリ
|
||||
collaborative_repos=共同リポジトリ
|
||||
my_orgs=私の組織
|
||||
my_mirrors=私のミラー
|
||||
|
||||
[explore]
|
||||
repos=リポジトリ
|
||||
|
||||
[auth]
|
||||
create_new_account=新規アカウントを作成
|
||||
register_hepler_msg=すでにアカウントをお持ちですか?今すぐログイン !
|
||||
social_register_hepler_msg=すでにアカウントをお持ちですか?今すぐバインド !
|
||||
disable_register_prompt=申し訳ありませんが、登録が無効になっています。サイト管理者に問い合わせてください。
|
||||
disable_register_mail=申し訳ありませんが、登録メールの確認機能が無効になっています。
|
||||
remember_me=ログイン状態を保持する
|
||||
forgot_password=パスワードを忘れた
|
||||
forget_password=パスワードを忘れた?
|
||||
sign_up_now=アカウントが必要ですか?今すぐサインアップ
|
||||
confirmation_mail_sent_prompt=新しい確認メールを <b>%s</b> に送りました。登録を完了させるために、%d時間以内にあなたのメールボックスを確認してください。
|
||||
sign_in_email=E-mailでサイイン
|
||||
active_your_account=アカウントをアクティブ
|
||||
resent_limit_prompt=申し訳ありませんが、アクティベーションメールは頻繁に送信しています。3 分お待ちください。
|
||||
has_unconfirmed_mail=こんにちは %s さん、あなたの電子メール アドレス (<b>%s</b>) は未確認です。もし確認メールをまだ確認できていないか、改めて再送信する場合は、下のボタンをクリックしてください。
|
||||
resend_mail=アクティベーションメールを再送信するにはここをクリック
|
||||
email_not_associate=この電子メール アドレスは、アカウントには関連付けられません。
|
||||
send_reset_mail=パスワードリセットのメールを再送するにはここをクリック
|
||||
reset_password=パスワードリセット
|
||||
invalid_code=申し訳ありませんが、確認用コードが期限切れまたは無効です。
|
||||
reset_password_helper=パスワードをリセットするにはここをクリック
|
||||
password_too_short=6文字未満のパスワードは設定できません。
|
||||
|
||||
[form]
|
||||
UserName=ユーザ名
|
||||
RepoName=リポジトリ名
|
||||
Email=Eメールアドレス
|
||||
Password=パスワード
|
||||
Retype=パスワードを再入力
|
||||
SSHTitle=SSH キーの名前
|
||||
HttpsUrl=HTTPS URL
|
||||
PayloadUrl=ペイロードの URL
|
||||
TeamName=チーム名
|
||||
AuthName=承認名
|
||||
AdminEmail=管理者の電子メール
|
||||
|
||||
require_error=空にできません
|
||||
alpha_dash_error=アルファベット、数字、ハイフン"-"、アンダースコア"_"のいずれかの必要があります
|
||||
alpha_dash_dot_error=' アルファベット、数値、ダッシュ(-)、アンダースコア(_) 、ドット(.)のいずれかを入力する必要があります。 '
|
||||
min_size_error=' 少なくとも %s 文字の必要があります '
|
||||
max_size_error=' %s 文字以下の必要があります '
|
||||
email_error=' は有効な電子メール アドレスではない '
|
||||
url_error=' は有効な URL はありません。 '
|
||||
unknown_error=不明なエラー:
|
||||
captcha_incorrect=Captcha が一致しませんでした。
|
||||
password_not_match=パスワードと確認用パスワードが一致同していません。
|
||||
|
||||
username_been_taken=ユーザー名は既に使用されています。
|
||||
repo_name_been_taken=リポジトリ名は既に使用されています。
|
||||
org_name_been_taken=組織名は既に使用されています。
|
||||
team_name_been_taken=チーム名は既に使用されています。
|
||||
email_been_used=電子メール アドレスは既に使用されています。
|
||||
ssh_key_been_used=パブリック キー名が使用されています。
|
||||
illegal_username=あなたのユーザ名に無効な文字が含まれます。
|
||||
illegal_repo_name=リポジトリ名には無効な文字が含まれています。
|
||||
illegal_org_name=組織名に無効な文字が含まれています。
|
||||
illegal_team_name=チーム名に無効な文字が含まれています。
|
||||
username_password_incorrect=ユーザー名またはパスワードが正しくありません。
|
||||
enterred_invalid_repo_name=入力したリポジトリの名前が正しいかどうかを確認してください。
|
||||
enterred_invalid_owner_name=入力された所有者名が正しいかどうかを確認してください。
|
||||
enterred_invalid_password=入力したパスワードが正しいかを確認してください。
|
||||
user_not_exist=指定されたユーザーは存在しません。
|
||||
last_org_owner=削除するユーザーはチームの最後のメンバーです。別の所有者設定が必要です。
|
||||
|
||||
invalid_ssh_key=SSHを確認できません:%s
|
||||
unable_verify_ssh_key=GogsはあなたのSSH keyを確認できません。しかし、我々は有効とみなしますので、自分自身で確認してください。
|
||||
auth_failed=認証に失敗しました: %v
|
||||
|
||||
still_own_repo=アカウント所有のリポジトリがあり、リポジトリの削除または所有者の移譲が必要です。
|
||||
still_has_org=アカウントはまだ組織のメンバーであり、組織から退出するか削除する必要があります。
|
||||
org_still_own_repo=この組織はまだリポジトリの所有しています、リポジトリを削除または転送する必要があります。
|
||||
|
||||
still_own_user=この認証はまだ一部のユーザーによって使用されています。一部のユーザを移動させてから、もう一度削除してください。
|
||||
|
||||
target_branch_not_exist=ターゲットブランチが存在しない
|
||||
|
||||
[user]
|
||||
change_avatar=gravatar.com で自分のアバターを変更
|
||||
change_custom_avatar=設定で自分のアバターを変更
|
||||
join_on=参加しました
|
||||
repositories=リポジトリ
|
||||
activity=パブリック・アクティビティ
|
||||
followers=フォロワー
|
||||
starred=スター
|
||||
following=フォロー
|
||||
|
||||
[settings]
|
||||
profile=プロフィール
|
||||
password=パスワード
|
||||
ssh_keys=SSH キー
|
||||
social=SNSアカウント
|
||||
applications=アプリケーション
|
||||
orgs=組織
|
||||
delete=アカウントを削除
|
||||
uid=Uid
|
||||
|
||||
public_profile=パブリック プロフィール
|
||||
profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。
|
||||
full_name=フルネーム
|
||||
website=WEBサイト
|
||||
location=ロケーション
|
||||
update_profile=プロファイル更新
|
||||
update_profile_success=あなたのプロフィールが更新されました。
|
||||
change_username=ユーザー名が変更されました
|
||||
change_username_desc=ユーザー名が変更されている、継続したいですか?これはあなたのアカウントに関連するすべてのリンクに影響を与える。
|
||||
continue=続行
|
||||
cancel=キャンセル
|
||||
|
||||
enable_custom_avatar=カスタムのアバターを有効にする
|
||||
enable_custom_avatar_helper=Gravatarからのフェッチを無効にするのを、有効にします
|
||||
choose_new_avatar=新しいアバターを選択
|
||||
update_avatar=アバターの設定を更新
|
||||
uploaded_avatar_not_a_image=アップロードされたファイルは画像ではない。
|
||||
no_custom_avatar_available=利用可能なカスタム アバターがないため、有効にできません。
|
||||
update_avatar_success=あなたのアバターの設定が更新されました。
|
||||
|
||||
change_password=パスワードを変更
|
||||
old_password=現在のパスワード
|
||||
new_password=新しいパスワード
|
||||
password_incorrect=現在のパスワードが正しくありません。
|
||||
change_password_success=パスワードが正常に変更されました。今すぐ新しいパスワード経由でサインインすることができます。
|
||||
|
||||
emails=E-mail アドレス
|
||||
manage_emails=E-mail アドレスを管理
|
||||
email_desc=あなたのプライマリメールアドレスは、通知やその他の操作に使用されます。
|
||||
primary=プライマリー
|
||||
primary_email=プライマリに設定
|
||||
delete_email=削除
|
||||
add_new_email=新しいe-mailアドレスを追加
|
||||
add_email=電子メールを追加します。
|
||||
add_email_success=新しいe-mail アドレスが追加されました。
|
||||
|
||||
manage_ssh_keys=SSH キーを管理
|
||||
add_key=キーを追加
|
||||
ssh_desc=これはあなたのアカウントに関連付けられている SSH キーの一覧です。あなたが認識していないキーを削除します。
|
||||
ssh_helper=<strong>ヘルプが必要ですか?</strong> 我々のガイドをご覧ください。 <a href="%s"> SSH キーを生成</a> <a href="%s"> SSH の一般的な問題</a>
|
||||
add_new_key=SSH キーを追加
|
||||
key_name=キーの名前
|
||||
key_content=コンテンツ
|
||||
add_key_success=新しい SSH キーが追加されました !
|
||||
delete_key=削除
|
||||
add_on=追加された
|
||||
last_used=最終使用日
|
||||
no_activity=最近の活動なし
|
||||
|
||||
manage_social=関連付けられているSNSアカウントを管理
|
||||
social_desc=これは関連付けられたソーシャルアカウントのリストです。あなたが認識していない結び付けを削除します。
|
||||
unbind=バインド解除
|
||||
unbind_success=SNSアカウントがバインドされていない。
|
||||
|
||||
manage_access_token=個人のアクセス トークンを管理
|
||||
generate_new_token=新しいトークンを生成
|
||||
tokens_desc=生成したトークンを利用して Gogs の API にアクセスすることができます。
|
||||
new_token_desc=今のところ、全てのトークンはあなたのアカウントにフルアクセスできます。
|
||||
token_name=トークン名
|
||||
generate_token=トークンを生成
|
||||
generate_token_succees=新しいアクセス トークンは正常に生成されました !今すぐあなたの新しいアクセス トークンをコピーしておいてください。二度と見ることはできませんので確認してください!
|
||||
delete_token=削除
|
||||
delete_token_success=個人のアクセス トークンは正常に削除されました!同時にあなたのアプリケーションを更新することを忘れないでください。
|
||||
|
||||
delete_account=アカウントを削除
|
||||
delete_prompt=この操作はあなたのアカウントを完全に削除し、復旧<strong>できない</strong> !
|
||||
confirm_delete_account=削除の確認
|
||||
delete_account_title=アカウントの削除
|
||||
delete_account_desc=このアカウントは永久に削除しようとしている、継続しますか?
|
||||
|
||||
[repo]
|
||||
owner=オーナー
|
||||
repo_name=リポジトリ名
|
||||
repo_name_helper=偉大なリポジトリ名は短い。思い出に残り、そして<strong>一意</strong>だ。
|
||||
visibility=ビジビリティ
|
||||
visiblity_helper=このリポジトリは <span class="label label-red label-radius"> プライベート</span> です。
|
||||
fork_repo=フォークのリポジトリ
|
||||
fork_from=フォーク元
|
||||
fork_visiblity_helper=フォークされたリポジトリは可視状態を変更できません
|
||||
repo_desc=説明
|
||||
repo_lang=言語
|
||||
repo_lang_helper=.gitignore ファイルを選択
|
||||
license=ライセンス
|
||||
license_helper=ライセンス ファイルを選択
|
||||
init_readme=README.md 付きでリポジトリを初期化
|
||||
create_repo=リポジトリを作成
|
||||
default_branch=デフォルトのブランチ
|
||||
mirror_interval=ミラー 間隔(時)
|
||||
goget_meta=Go-Get メタ
|
||||
goget_meta_helper=このリポジトリは <span class="label label-blue label-radius"> Go-Getable </span> になります
|
||||
|
||||
need_auth=認証が必要
|
||||
migrate_type=マイグレーションの種類
|
||||
migrate_type_helper=このリポジトリは <span class="label label-blue label-radius"> ミラー</span> になります
|
||||
migrate_repo=リポジトリを移行
|
||||
|
||||
copy_link=コピー
|
||||
click_to_copy=クリップボードにコピー
|
||||
copied=コピー成功
|
||||
clone_helper=クローニングのヘルプが必要ですか?<a target="_blank"href="%s"> ヘルプ</a> を参照してください!
|
||||
unwatch=Unwatch
|
||||
watch=Watch
|
||||
unstar=Unstar
|
||||
star=Star
|
||||
fork=Fork
|
||||
|
||||
no_desc=説明なし
|
||||
quick_guide=クイック ガイド
|
||||
clone_this_repo=このリポジトリのクローンを作成
|
||||
create_new_repo_command=コマンドラインで新しいリポジトリを作成します。
|
||||
push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ
|
||||
|
||||
branch=ブランチ
|
||||
tree=ツリー
|
||||
branch_and_tags=ブランチ& タグ
|
||||
branches=ブランチ
|
||||
tags=タグ
|
||||
issues=課題
|
||||
commits=コミット
|
||||
releases=リリース
|
||||
file_raw=生データ
|
||||
file_history=履歴
|
||||
file_view_raw=生データを見る
|
||||
|
||||
commits.commits=コミット
|
||||
commits.search=コミットの検索
|
||||
commits.find=検索
|
||||
commits.author=作者
|
||||
commits.message=メッセージ
|
||||
commits.date=日付
|
||||
commits.older=古い
|
||||
commits.newer=新しい
|
||||
|
||||
settings=設定
|
||||
settings.options=オプション
|
||||
settings.collaboration=コラボレーション
|
||||
settings.hooks=Webhooks
|
||||
settings.githooks=Git のフック
|
||||
settings.deploy_keys=デプロイキー
|
||||
settings.basic_settings=基本設定
|
||||
settings.danger_zone=危険地帯
|
||||
settings.site=公式サイト
|
||||
settings.update_settings=設定の更新
|
||||
settings.change_reponame=リポジトリ名が変更されました
|
||||
settings.change_reponame_desc=リポジトリの名前が変更されています、継続しますか?このリポジトリ関連すべてのリンクに影響を与えます。
|
||||
settings.transfer=オーナー移転
|
||||
settings.transfer_desc=リポジトリをあなたが管理者権限を持っている別のユーザーまた組織に移譲します。
|
||||
settings.new_owner_has_same_repo=新しいオーナーは、既に同じ名前のリポジトリを持っています。
|
||||
settings.delete=このリポジトリを削除
|
||||
settings.delete_desc=リポジトリを削除すると元に戻せません。確実に確認してください。
|
||||
settings.transfer_notices=<p>-新オーナーは個人ユーザの場合、あなたはにアクセスできなくなります。</p><p>-新オーナーは組織であり、かつあなたが組織のオーナーに所属する場合、あなたはアクセス権を維持します。</p>
|
||||
settings.update_settings_success=リポジトリ オプションが更新されました。
|
||||
settings.transfer_owner=新しいオーナー
|
||||
settings.make_transfer=転送
|
||||
settings.transfer_succeed=リポジトリの所有権は正常に転送されました。
|
||||
settings.confirm_delete=削除の確認
|
||||
settings.add_collaborator=新しい共同編集者を追加
|
||||
settings.add_collaborator_success=新しい共同編集者が追加されました。
|
||||
settings.remove_collaborator_success=共同編集者が削除されました。
|
||||
settings.user_is_org_member=ユーザーは組織の一員なので、共同編集者として追加することはできません。
|
||||
settings.add_webhook=Webhook を追加
|
||||
settings.hooks_desc=Webhooksは、Gogsで特定のイベントの発生時に指定された外部サービスに通知を許可します。イベントが発生すると、それぞれ指定されたUrlに、POSTリクエストが送られます。詳細はこちらのの <a target="_blank"href="%s"> Webhooks ガイド</a>をご覧ください。
|
||||
settings.githooks_desc=Git のフックは Git 自体によって提供されています。以下のリストのファイルを編集して、サポートされているフックのカスタム操作を適用することができます。
|
||||
settings.githook_edit_desc=もしフックがアクティブではない場合は、サンプルコンテンツが表示されます。コンテンツを空白にするにはこのフックを無効にします。
|
||||
settings.githook_name=フックの名前
|
||||
settings.githook_content=コンテンツをフック
|
||||
settings.update_githook=フックを更新
|
||||
settings.remove_hook_success=Webhookが削除されました。
|
||||
settings.add_webhook_desc=私たちは、指定されたURLに購読されたイベントの詳細を <code>POST</code>リクエストとして送信します。あなたは、異なるデータ受信モード(JSONまたは, <code>x-www-form-urlencoded</code>, <em>その他</em>) を設定することができます。詳細については、<a target="_blank" href="%s">Webhookガイド</a>を参照してください。
|
||||
settings.payload_url=ペイロードの URL
|
||||
settings.content_type=コンテンツ タイプ
|
||||
settings.secret=秘密
|
||||
settings.event_desc=どのイベントをこのWEBフックのトリガーにしますか?
|
||||
settings.event_push_only=<code>push</code> イベントのみ
|
||||
settings.active=アクティブ
|
||||
settings.active_helper=このフックのトリガーが引かれた時に、イベントの詳細を配信します。
|
||||
settings.add_hook_success=新しい webhook が追加されました。
|
||||
settings.update_webhook=Webhookを更新
|
||||
settings.update_hook_success=Webhook を更新しました。
|
||||
settings.delete_webhook=Webhook を削除
|
||||
settings.recent_deliveries=最近のデリバリー
|
||||
settings.hook_type=フックタイプ
|
||||
settings.add_slack_hook_desc=<a href="%s"> Slack</a> インテグレーションをリポジトリに追加します。
|
||||
settings.slack_token=トークン
|
||||
settings.slack_domain=ドメイン
|
||||
settings.slack_channel=チャンネル
|
||||
|
||||
diff.browse_source=ソースを参照
|
||||
diff.parent=親
|
||||
diff.commit=コミット
|
||||
diff.data_not_available=差分データは利用できません。
|
||||
diff.show_diff_stats=差分情報を表示
|
||||
diff.stats_desc=共有<strong>%d 個のファイルを変更した</strong>、<strong>%d 個の追加</strong> と <strong>%d 個の削除</strong>を含む
|
||||
diff.bin=BIN
|
||||
diff.view_file=ファイルの表示
|
||||
|
||||
release.releases=リリース
|
||||
release.new_release=新しいリリース
|
||||
release.draft=ドラフト
|
||||
release.prerelease=プレリリース
|
||||
release.stable=安定
|
||||
release.edit=編集
|
||||
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
|
||||
release.source_code=ソース コード
|
||||
release.tag_name=タグ名
|
||||
release.target=ターゲット
|
||||
release.tag_helper=既存のタグを選択するか、新しいタグを作成し発行します。
|
||||
release.release_title=リリース タイトル
|
||||
release.content_with_md=<a href="%s"> Markdown</a> コンテンツ
|
||||
release.write=書込み
|
||||
release.preview=プレビュー
|
||||
release.content_placeholder=コンテンツを書く
|
||||
release.loading=読み込み中…
|
||||
release.prerelease_desc=これはリリース前のものです
|
||||
release.prerelease_helper=このリリースは非プロダクション利用として識別します。
|
||||
release.publish=リリースを発行
|
||||
release.save_draft=下書きを保存
|
||||
release.edit_release=リリースを編集
|
||||
release.tag_name_already_exist=このタグ名には既にリリースが存在します。
|
||||
|
||||
[org]
|
||||
org_name_holder=組織名
|
||||
org_name_helper=偉大な組織の名は短く覚えやすいです。
|
||||
org_email_helper=組織の電子メールはすべての通知や確認を受け取ります。
|
||||
create_org=組織を作成
|
||||
repo_updated=更新した
|
||||
people=人々
|
||||
invite_someone=誰かを招待
|
||||
teams=チーム
|
||||
lower_members=メンバー
|
||||
lower_repositories=リポジトリ
|
||||
create_new_team=新しいチームを作成
|
||||
org_desc=説明
|
||||
team_name=チーム名
|
||||
team_desc=説明
|
||||
team_name_helper=会話の時、この名前を使用しチーム名を表明します。
|
||||
team_desc_helper=このチームに関する全ての情報は?
|
||||
team_permission_desc=このチームに必要な権限レベルは?
|
||||
|
||||
settings=設定
|
||||
settings.options=オプション
|
||||
settings.full_name=フルネーム
|
||||
settings.website=WEBサイト
|
||||
settings.location=ロケーション
|
||||
settings.update_settings=設定の更新
|
||||
settings.change_orgname=組織名が変更されました
|
||||
settings.change_orgname_desc=組織名が変更されています、継続しますか?これはすべての関連リンクに影響を与えます。
|
||||
settings.update_setting_success=組織の設定が更新されました。
|
||||
settings.delete=組織を削除
|
||||
settings.delete_account=この組織を削除
|
||||
settings.delete_prompt=操作はこの組織を完全に削除し、復旧<strong>できない</strong>!
|
||||
settings.confirm_delete_account=削除の確認
|
||||
settings.delete_org_title=組織の削除
|
||||
settings.delete_org_desc=この組織は完全に削除されます、継続しますか?
|
||||
settings.hooks_desc=この組織のもとで <strong>すべてのリポジトリ</strong> に対してトリガーされる webhook を追加します。
|
||||
|
||||
members.public=パブリック
|
||||
members.public_helper=プライベートにする
|
||||
members.private=プライベート
|
||||
members.private_helper=公開する
|
||||
members.owner=オーナー
|
||||
members.member=メンバー
|
||||
members.conceal=隠す
|
||||
members.remove=削除
|
||||
members.leave=退出
|
||||
members.invite_desc=%s に招待する新しいメンバーをユーザ名を入力してください:
|
||||
members.invite_now=今すぐ招待
|
||||
|
||||
teams.join=参加
|
||||
teams.leave=退出
|
||||
teams.read_access=読み取りアクセス権
|
||||
teams.read_access_helper=このチームはリポジトリの閲覧とクローンをすることができます。
|
||||
teams.write_access=書き込みアクセス権
|
||||
teams.write_access_helper=このチームはリポジトリを読むだけではなく、プッシュすることもできます。
|
||||
teams.admin_access=管理者のアクセス権
|
||||
teams.admin_access_helper=このチームはリポジトリにプッシュ/プル、及び他の共同編集者を追加することができます。
|
||||
teams.no_desc=このチームは説明がありません。
|
||||
teams.settings=設定
|
||||
teams.owners_permission_desc=オーナーは<strong>すべてのリポジトリ</strong> へのフルアクセス権、組織の <strong>管理権限</strong>を持ちます。
|
||||
teams.members=チーム メンバー
|
||||
teams.update_settings=設定の更新
|
||||
teams.delete_team=このチームを削除
|
||||
teams.add_team_member=チーム メンバーを追加
|
||||
teams.delete_team_title=チームの削除
|
||||
teams.delete_team_desc=このチームを削除します、継続しますか?このチームのメンバーはいくつかのリポジトリへのアクセスを失う可能性があります。
|
||||
teams.delete_team_success=指定のチームが正常に削除されました。
|
||||
teams.read_permission_desc=このチームは<strong>読み取り</strong>権限を持ち: メンバーはリポジトリの表示及びクローンの作成ができます。
|
||||
teams.write_permission_desc=このチームは<strong>書き込み</strong>権限を持ち: メンバーはリポジトリの表示及リポジトリへのプッシュができます。
|
||||
teams.admin_permission_desc=このチームは<strong>管理者</strong>の権限を持ち: メンバーはチームのリポジトリに対して、読み取り、プッシュや共同編集者の追加ができます。
|
||||
teams.repositories=チームのリポジトリ
|
||||
teams.add_team_repository=チームのリポジトリを追加
|
||||
teams.remove_repo=削除(Remove)
|
||||
teams.add_nonexistent_repo=追加しようとしているリポジトリは存在しません。まずはじめに作成してください。
|
||||
|
||||
[admin]
|
||||
dashboard=ダッシュボード
|
||||
users=ユーザ
|
||||
organizations=組織
|
||||
repositories=リポジトリ
|
||||
authentication=認証
|
||||
config=コンフィギュレーション
|
||||
notices=システム通知
|
||||
monitor=モニタリング
|
||||
prev=前へ
|
||||
next=次へ
|
||||
|
||||
dashboard.statistic=統計
|
||||
dashboard.operations=操作
|
||||
dashboard.system_status=システム モニターのステータス
|
||||
dashboard.statistic_info=Gogs データベースは <b>%d</b> ユーザ, <b>%d</b> 組織, <b>%d</b> 公開鍵, <b>%d</b> リポジトリ, <b>%d</b> ウォッチ, <b>%d</b> スター, <b>%d</b> 行動, <b>%d</b> アクセス, <b>%d</b> 問題, <b>%d</b> コメント, <b>%d</b> ソーシャルアカウント, <b>%d</b> フォロー, <b>%d</b> ミラー, <b>%d</b> リリース, <b>%d</b> ログイン元, <b>%d</b> webhook, <b>%d</b> マイルストーン, <b>%d</b> ラベル, <b>%d</b> フックタスク, <b>%d</b> チーム, <b>%d</b> アップデートタスク, <b>%d</b> 添付ファイル の情報を持っています。
|
||||
dashboard.operation_name=操作の名前
|
||||
dashboard.operation_switch=スイッチ
|
||||
dashboard.operation_run=実行
|
||||
dashboard.clean_unbind_oauth=結び付けられていない OAuth をクリーン
|
||||
dashboard.clean_unbind_oauth_success=結び付けられていない全ての OAuth を正常に削除しました。
|
||||
dashboard.delete_inactivate_accounts=非アクティブのアカウントをすべて削除
|
||||
dashboard.delete_inactivate_accounts_success=すべての非アクティブアカウントは正常に削除されました。
|
||||
dashboard.delete_repo_archives=リポジトリのすべてのアーカイブを削除
|
||||
dashboard.delete_repo_archives_success=リポジトリのすべてのアーカイブが正常に削除されました。
|
||||
dashboard.git_gc_repos=リポジトリでのガベージコレクションを実行します。
|
||||
dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。
|
||||
dashboard.resync_all_sshkeys='.ssh/ autorized_key' ファイルを再生成します。(警告:Gogsキー以外は失われます)
|
||||
dashboard.resync_all_sshkeys_success=すべての公開鍵が正常に書き換えられました。
|
||||
dashboard.resync_all_update_hooks=リポジトリの update フックをすべて再更新する(カスタムの設定パスが変更されたときに必要)
|
||||
dashboard.resync_all_update_hooks_success=リポジトリの update フックがすべて正常に再更新されました。
|
||||
|
||||
dashboard.server_uptime=サーバーの稼働時間
|
||||
dashboard.current_goroutine=現在のGoroutine
|
||||
dashboard.current_memory_usage=現在のメモリ使用量
|
||||
dashboard.total_memory_allocated=割り当てられたメモリの合計
|
||||
dashboard.memory_obtained=配分されたメモリ量
|
||||
dashboard.pointer_lookup_times=ポインタ参照回数
|
||||
dashboard.memory_allocate_times=メモリ割当回数
|
||||
dashboard.memory_free_times=メモリ解放回数
|
||||
dashboard.current_heap_usage=現在のヒープ使用量
|
||||
dashboard.heap_memory_obtained=配分されたヒープ メモリ量
|
||||
dashboard.heap_memory_idle=アイドルのヒープ メモリ量
|
||||
dashboard.heap_memory_in_use=使用中のヒープ メモリ
|
||||
dashboard.heap_memory_released=ヒープ メモリが解放されました
|
||||
dashboard.heap_objects=ヒープ オブジェクト
|
||||
dashboard.bootstrap_stack_usage=ブートストラップスタック使用量
|
||||
dashboard.stack_memory_obtained=配分されたスタック メモリ量
|
||||
dashboard.mspan_structures_usage=MSpan 構造体の使用量
|
||||
dashboard.mspan_structures_obtained=配分されたMSpan 構造体
|
||||
dashboard.mcache_structures_usage=MCache 構造体の使用量
|
||||
dashboard.mcache_structures_obtained=分配されたMCache 構造体
|
||||
dashboard.profiling_bucket_hash_table_obtained=ハッシュテーブル分析に割り当てられたメモリ
|
||||
dashboard.gc_metadata_obtained=GCメタデータ取得
|
||||
dashboard.other_system_allocation_obtained=他のシステムに割り当てられたメモリ
|
||||
dashboard.next_gc_recycle=次回のGCリサイクル
|
||||
dashboard.last_gc_time=前回GCからの時間
|
||||
dashboard.total_gc_time=GC一時停止の合計
|
||||
dashboard.total_gc_pause=GC一時停止の合計
|
||||
dashboard.last_gc_pause=直近のGC一時停止
|
||||
dashboard.gc_times=GC実行回数
|
||||
|
||||
users.user_manage_panel=ユーザー管理パネル
|
||||
users.new_account=新規アカウントを作成
|
||||
users.name=名前
|
||||
users.activated=アクティブ化
|
||||
users.admin=アドミン
|
||||
users.repos=リポジトリ
|
||||
users.created=作成されました
|
||||
users.edit=編集
|
||||
users.auth_source=認証元
|
||||
users.local=ローカル
|
||||
users.auth_login_name=認証ログイン名
|
||||
users.update_profile_success=アカウントのプロファイルが更新されました。
|
||||
users.edit_account=アカウントの編集
|
||||
users.is_activated=アカウントがアクティブされました
|
||||
users.is_admin=このアカウントには管理者の権限を持つ
|
||||
users.allow_git_hook=このアカウントには Git のフックを作成する権限を持つ
|
||||
users.update_profile=アカウント ・ プロファイルを更新
|
||||
users.delete_account=このアカウントを削除
|
||||
users.still_own_repo=アカウント所有のリポジトリがあり、リポジトリの削除または所有者の移譲が必要です。
|
||||
users.still_has_org=アカウントはまだ組織のメンバーであり、組織から退出するか削除する必要があります。
|
||||
|
||||
orgs.org_manage_panel=組織の管理パネル
|
||||
orgs.name=名前
|
||||
orgs.teams=チーム
|
||||
orgs.members=メンバー
|
||||
|
||||
repos.repo_manage_panel=リポジトリの管理パネル
|
||||
repos.owner=オーナー
|
||||
repos.name=名前
|
||||
repos.private=プライベート
|
||||
repos.watches=Watches
|
||||
repos.stars=Stars
|
||||
repos.issues=課題
|
||||
|
||||
auths.auth_manage_panel=承認の管理パネル
|
||||
auths.new=新しい認証元を追加
|
||||
auths.name=名前
|
||||
auths.type=タイプ
|
||||
auths.enabled=Enabled
|
||||
auths.updated=Updated
|
||||
auths.auth_type=認証の種類
|
||||
auths.auth_name=認証名
|
||||
auths.domain=ドメイン
|
||||
auths.host=ホスト
|
||||
auths.port=ポート
|
||||
auths.base_dn=ベースのドメイン名
|
||||
auths.attributes=属性検索
|
||||
auths.filter=検索フィルター
|
||||
auths.ms_ad_sa=Ms Ad SA
|
||||
auths.smtp_auth=SMTP 認証の種類
|
||||
auths.smtphost=SMTP ホスト
|
||||
auths.smtpport=SMTP ポート
|
||||
auths.enable_tls=TLS 暗号化を有効にする
|
||||
auths.enable_auto_register=自動登録を有効にする
|
||||
auths.tips=ヒント
|
||||
auths.edit=認証設定を編集
|
||||
auths.activated=認証がアクティブされました
|
||||
auths.update_success=認証の設定が正常に更新されました。
|
||||
auths.update=認証設定の更新
|
||||
auths.delete=この権限を削除
|
||||
auths.delete_auth_title=認証の削除
|
||||
auths.delete_auth_desc=認証を削除します、継続しますか?
|
||||
|
||||
config.server_config=サーバーの構成
|
||||
config.app_name=アプリケーション名
|
||||
config.app_ver=アプリケーションのバージョン
|
||||
config.app_url=アプリケーションの URL
|
||||
config.domain=ドメイン
|
||||
config.offline_mode=オフラインモード
|
||||
config.disable_router_log=ルーターのログを無効にする
|
||||
config.run_user=実行ユーザ
|
||||
config.run_mode=実行モード
|
||||
config.repo_root_path=リポジトリのルートパス
|
||||
config.static_file_root_path=静的ファイルのルートパス
|
||||
config.log_file_root_path=ログ ファイルのルート パス
|
||||
config.script_type=スクリプトの種類
|
||||
config.reverse_auth_user=リバース認証ユーザ
|
||||
config.db_config=データベースの構成
|
||||
config.db_type=タイプ
|
||||
config.db_host=ホスト
|
||||
config.db_name=名前
|
||||
config.db_user=ユーザ
|
||||
config.db_ssl_mode=SSL モード
|
||||
config.db_ssl_mode_helper=(「postgres」のみ)
|
||||
config.db_path=パス
|
||||
config.db_path_helper=(「sqlite3」のみ)
|
||||
config.service_config=サービスの構成
|
||||
config.register_email_confirm=電子メールの確認を必要
|
||||
config.disable_register=登録を無効にする
|
||||
config.show_registration_button=登録ボタンを表示します。
|
||||
config.require_sign_in_view=サインインを要求
|
||||
config.mail_notify=メール通知
|
||||
config.enable_cache_avatar=アバターのキャッシュを有効にします。
|
||||
config.active_code_lives=コードリンクの有効期限をアクティブ
|
||||
config.reset_password_code_lives=パスワードリンクの有効期限をリセット
|
||||
config.webhook_config=Webhook設定
|
||||
config.task_interval=タスクの間隔
|
||||
config.deliver_timeout=送信タイムアウト
|
||||
config.skip_tls_verify=TLSの確認を省略
|
||||
config.mailer_config=メーラーの構成
|
||||
config.mailer_enabled=有効にした
|
||||
config.mailer_name=名前
|
||||
config.mailer_host=ホスト
|
||||
config.mailer_user=ユーザ
|
||||
config.oauth_config=OAuth 構成
|
||||
config.oauth_enabled=Enabled
|
||||
config.cache_config=キャッシュの構成
|
||||
config.cache_adapter=キャッシュ アダプター
|
||||
config.cache_interval=キャッシュ間隔
|
||||
config.cache_conn=キャッシュ接続
|
||||
config.session_config=セッションの構成
|
||||
config.session_provider=セッション プロバイダー
|
||||
config.provider_config=プロバイダーの構成
|
||||
config.cookie_name=クッキー名
|
||||
config.enable_set_cookie=クッキーの設定を有効にする
|
||||
config.gc_interval_time=GC 間隔
|
||||
config.session_life_time=セッションのライフタイム
|
||||
config.https_only=HTTPS のみ
|
||||
config.cookie_life_time=クッキーのライフタイム
|
||||
config.picture_config=画像構成
|
||||
config.picture_service=画像サービス
|
||||
config.disable_gravatar=グラバターを無効にする
|
||||
config.log_config=ログの構成
|
||||
config.log_mode=ログ モード
|
||||
|
||||
monitor.cron=Cron タスク
|
||||
monitor.name=名前
|
||||
monitor.schedule=スケジュール
|
||||
monitor.next=次回
|
||||
monitor.previous=前回
|
||||
monitor.execute_times=実行回数
|
||||
monitor.process=実行中のプロセス
|
||||
monitor.desc=説明
|
||||
monitor.start=開始日時
|
||||
monitor.execute_time=実行時間:
|
||||
|
||||
notices.system_notice_list=システム通知
|
||||
notices.type=タイプ
|
||||
notices.type_1=リポジトリ
|
||||
notices.desc=説明
|
||||
notices.op=Op。
|
||||
notices.delete_success=システム通知が正常に削除されました。
|
||||
|
||||
[action]
|
||||
create_repo=リポジトリ <a href="%s/%s"> %s</a>を作成しました
|
||||
commit_repo=<a href="%s/%s">%s</a>を<a href="%s/%s/src/%s">%s</a>にプッシュしました
|
||||
create_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> を開きました`
|
||||
comment_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> のコメント`
|
||||
transfer_repo=リポジトリ <code>%s</code> を <a href="/%s%s">%s</a> へ転送しました
|
||||
push_tag=<a href="%s/%s">%s</a> に タグ <a href="%s/%s/src/%s">%s</a> をプッシュしました
|
||||
compare_2_commits=これら 2 のコミットの比較を閲覧する
|
||||
|
||||
[tool]
|
||||
ago=前
|
||||
from_now=今から
|
||||
now=今
|
||||
1s=1 秒 %s
|
||||
1m=1 分 %s
|
||||
1h=1 時間 %s
|
||||
1d=1 日 %s
|
||||
1w=1 週間 %s
|
||||
1mon=1 ヶ月 %s
|
||||
1y=1 年間 %s
|
||||
seconds=%d 秒 %s
|
||||
minutes=%d 分の %s
|
||||
hours=%d 時間 %s
|
||||
days=%d 日 %s
|
||||
weeks=%d 週間 %s
|
||||
months=%d ヶ月 %s
|
||||
years=%d 年 %s
|
||||
raw_seconds=秒
|
||||
raw_minutes=分
|
||||
|
||||
724
conf/locale/locale_lv-LV.ini
Executable file
724
conf/locale/locale_lv-LV.ini
Executable file
@@ -0,0 +1,724 @@
|
||||
app_desc=Viegli uzstādāms Git serviss, kas rakstīts valodā Go
|
||||
|
||||
home=Sākums
|
||||
dashboard=Infopanelis
|
||||
explore=Izpētīt
|
||||
help=Palīdzība
|
||||
sign_in=Pierakstīties
|
||||
social_sign_in=Sociālā pieteikšanās: 2. solis <small>piesaistīt kontu</small>
|
||||
sign_out=Izrakstīties
|
||||
sign_up=Pieteikties
|
||||
register=Reģistrēties
|
||||
website=Mājas lapa
|
||||
version=Versija
|
||||
page=Lapa
|
||||
template=Sagatave
|
||||
language=Valoda
|
||||
|
||||
username=Lietotājvārds
|
||||
email=E-pasts
|
||||
password=Parole
|
||||
re_type=Parole atkārtoti
|
||||
captcha=Pārbaudes kods
|
||||
|
||||
repository=Repozitorijs
|
||||
organization=Organizācija
|
||||
mirror=Spogulis
|
||||
new_repo=Jauns repozitorijs
|
||||
new_migrate=Jauna migrācija
|
||||
new_fork=Jauns atdalītais repozitorijs
|
||||
new_org=Jauna organizācija
|
||||
manage_org=Pārvaldīt organizācijas
|
||||
admin_panel=Admin panelis
|
||||
account_settings=Konta iestatījumi
|
||||
settings=Iestatījumi
|
||||
|
||||
news_feed=Jaunumu plūsma
|
||||
pull_requests=Izmaiņu pieprasījumi
|
||||
issues=Problēmas
|
||||
|
||||
cancel=Atcelt
|
||||
|
||||
[install]
|
||||
install=Instalācija
|
||||
title=Instalācijas soļi pirmo reizi palaižot
|
||||
requite_db_desc=Gogs ir nepieciešama MySQL, PostgreSQL vai SQLite3 datu bāze.
|
||||
db_type=Datu bāzes veids
|
||||
host=Resursdators
|
||||
user=Lietotājs
|
||||
password=Parole
|
||||
db_name=Datu bāzes nosaukums
|
||||
db_helper=Nepieciešams izmantot MySQL INNODB dzini ar rakstzīmju kopu utf8_general_ci.
|
||||
ssl_mode=SSL režīms
|
||||
path=Ceļš
|
||||
sqlite_helper=SQLite 3 datu bāzes faila atrašanās vieta.
|
||||
general_title=Gogs vispārīgie iestatījumi
|
||||
repo_path=Repozitoriju glabāšanas vieta
|
||||
repo_path_helper=Visi Git attālinātie repozitoriji tiks glabāti šajā direktorijā.
|
||||
run_user=Izpildes lietotājs
|
||||
run_user_helper=Lietotājam ir jābūt rakstīšanas tiesībām repozitorija saknes direktorijai un Gogs jābūt palaistam zem šī lietotāja.
|
||||
domain=Domēns
|
||||
domain_helper=Tas ietekmē SSH klonēšanas URL.
|
||||
http_port=HTTP ports
|
||||
http_port_helper=Porta numurs pēc kura lietojumprogrammai būs iespējams pieslēgties.
|
||||
app_url=Lietotnes URL
|
||||
app_url_helper=Tas ietekmē HTTP/HTTPS klonēšanas URL un e-pasta saturā izsūtītās saites.
|
||||
email_title=E-pasta pakalpojuma iestatījumi (neobligāti)
|
||||
smtp_host=SMTP resursdators
|
||||
mailer_user=Sūtītāja e-pasta adrese
|
||||
mailer_password=Sūtītāja parole
|
||||
notify_title=Paziņojumu iestatījumi (neobligāti)
|
||||
register_confirm=Iespējot reģistrēšanās apstiprināšanu
|
||||
mail_notify=Iespējot e-pasta paziņojumus
|
||||
admin_title=Admin konta iestatījumi
|
||||
admin_name=Lietotājvārds
|
||||
admin_password=Parole
|
||||
confirm_password=Apstipriniet paroli
|
||||
admin_email=E-pasts
|
||||
install_gogs=Instalēt Gogs
|
||||
test_git_failed=Kļūda pārbaudot 'git' komandu: %v
|
||||
sqlite3_not_available=Jūsu versija neatbalsta SQLite3, lūdzu lejupielādējiet oficiālo bināro versiju no %s, NEVIS gobuild versiju.
|
||||
invalid_db_setting=Datu bāzes iestatījums nav pareizs: %v
|
||||
invalid_repo_path=Repozitorija atrašanās vieta ir nekorekta: %v
|
||||
run_user_not_match=Izpildes lietotājs nav pašreizējais lietotājs: %s -> %s
|
||||
save_config_failed=Neizdevās saglabāt konfigurāciju: %v
|
||||
invalid_admin_setting=Nekorekts admin konta iestatījums: %v
|
||||
install_success=Laipni lūdzam! Mēs priecājamies, ka Jūs izvēlaties Gogs, patīkamu lietošanu!
|
||||
|
||||
[home]
|
||||
uname_holder=Lietotājvārds vai e-pasts
|
||||
password_holder=Parole
|
||||
switch_dashboard_context=Mainīt infopaneļa kontekstu
|
||||
my_repos=Mani repozitoriji
|
||||
collaborative_repos=Sadarbības repozitoriji
|
||||
my_orgs=Manas organizācijas
|
||||
my_mirrors=Mani spoguļi
|
||||
|
||||
[explore]
|
||||
repos=Repozitoriji
|
||||
|
||||
[auth]
|
||||
create_new_account=Izveidot jaunu kontu
|
||||
register_hepler_msg=Jau ir konts? Pieraksties tagad!
|
||||
social_register_hepler_msg=Jau ir konts? Sasaisti tagad!
|
||||
disable_register_prompt=Atvainojiet, reģistrācija ir atspējota. Lūdzu, sazinieties ar vietnes administratoru.
|
||||
disable_register_mail=Atvainojiet, reģistrācijas e-pasta apstiprināšana ir atspējota.
|
||||
remember_me=Atcerēties mani
|
||||
forgot_password=Aizmirsu paroli
|
||||
forget_password=Aizmirsi paroli?
|
||||
sign_up_now=Nepieciešams konts? Reģistrējies tagad.
|
||||
confirmation_mail_sent_prompt=Jauns apstiprināšanas e-pasts ir nosūtīts uz <b>%s</b>, lūdzu, pārbaudies savu e-pasta kontu tuvāko %d stundu laikā, lai pabeigtu reģistrācijas procesu.
|
||||
sign_in_email=Atvērt savu e-pasta kontu
|
||||
active_your_account=Aktivizēt savu kontu
|
||||
resent_limit_prompt=Atvainojiet, Jūs sūtījāt aktivizācijas e-pastu pārāk bieži. Lūdzu, gaidiet 3 minūtes.
|
||||
has_unconfirmed_mail=Sveiki %s, Jums ir neapstiprināta e-pasta adrese (<b>%s</b>). Ja neesat saņēmis apstiprināšanas e-pastu vai Jums ir nepieciešams nosūtīt jaunu, lūdzu, nospiediet pogu, kas atrodas zemāk.
|
||||
resend_mail=Nospiediet šeit, lai vēlreiz nosūtītu aktivizācijas e-pastu
|
||||
email_not_associate=Šī e-pasta adrese nav saistīta ar Jūsu kontu.
|
||||
send_reset_mail=Spiediet šeit, lai nosūtītu paroles maiņas vēstuli uz Jūsu e-pastu
|
||||
reset_password=Atjaunot savu paroli
|
||||
invalid_code=Atvainojiet, Jūsu apstiprināšanas kodam ir beidzies derīguma termiņš vai arī tas ir nepareizs.
|
||||
reset_password_helper=Nospiediet šeit, lai atjaunotu paroli
|
||||
password_too_short=Paroles garums nedrīkst būt mazāks par 6.
|
||||
|
||||
[form]
|
||||
UserName=Lietotājvārds
|
||||
RepoName=Repozitorija nosaukums
|
||||
Email=E-pasta adrese
|
||||
Password=Parole
|
||||
Retype=Parole atkārtoti
|
||||
SSHTitle=SSH atslēgas nosaukums
|
||||
HttpsUrl=HTTPS URL
|
||||
PayloadUrl=Vērtuma URL
|
||||
TeamName=Komandas nosaukums
|
||||
AuthName=Autorizācijas nosaukums
|
||||
AdminEmail=Admin e-pasta adrese
|
||||
|
||||
require_error=` nedrīkst būt tukšs.`
|
||||
alpha_dash_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus vai domuzīmes (-_).`
|
||||
alpha_dash_dot_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus, domuzīmes (-_) vai punktu.`
|
||||
min_size_error=` jabūt vismaz %s simbolu garumā.`
|
||||
max_size_error=` jabūt ne mazāk kā %s simbolu garumā.`
|
||||
email_error=` nav derīga e-pasta adrese.`
|
||||
url_error=` nav korekts URL.`
|
||||
unknown_error=Nezināma kļūda:
|
||||
captcha_incorrect=Pārbaudes kods nesakrīt ar attēlā redzamo.
|
||||
password_not_match=Parole un atkārtoti ievadītā parole nav vienādas.
|
||||
|
||||
username_been_taken=Lietotājvārds ir jau aizņemts.
|
||||
repo_name_been_taken=Repozitorija vārds ir jau aizņemts.
|
||||
org_name_been_taken=Organizācijas nosaukums ir jau aizņemts.
|
||||
team_name_been_taken=Komandas nosaukums ir jau aizņemts.
|
||||
email_been_used=E-pasta adrese jau tiek izmantota.
|
||||
ssh_key_been_used=Publiskās atslēgas nosaukums jau tiek izmantos.
|
||||
illegal_username=Jūsu lietotājvārds satur neatļautas rakstzīmes.
|
||||
illegal_repo_name=Krātuves nosaukums satur neatļautas rakstzīmes.
|
||||
illegal_org_name=Organizācijas nosaukums satur neatļautas rakstzīmes.
|
||||
illegal_team_name=Grupas nosaukums satur neatļautas rakstzīmes.
|
||||
username_password_incorrect=Lietotājvārds vai parole nav pareiza.
|
||||
enterred_invalid_repo_name=Lūdzu, pārliecinieties, vai ievadītā repozitorija nosaukums ir pareizs.
|
||||
enterred_invalid_owner_name=Lūdzu, pārliecinieties, vai ievadītā īpašnieka vārds ir pareizs.
|
||||
enterred_invalid_password=Lūdzu pārliecinieties, vai Jūsu ievadītā parole ir pareiza.
|
||||
user_not_exist=Šāds lietotājs neeksistē.
|
||||
last_org_owner=Nav iespējams noņemt vienīgo komandas īpašnieku. Pirms tam ir nepieciešams norādīt jauno īpašnieku.
|
||||
|
||||
invalid_ssh_key=Atvainojiet, nav iespējams pārbaudīt Jūsu SSH atslēgu: %s
|
||||
unable_verify_ssh_key=Nav iespējams pārbaudīt jūsu SSH atslēgu, bet tiks pieņemts, ka tā ir derīga, lūdzu, pārliecinieties par to pats.
|
||||
auth_failed=Autentifikācija neizdevās: %v
|
||||
|
||||
still_own_repo=Jūsu esat vismaz viena repozitorija īpašnieks, tos sākumā ir nepieciešams izdzēst vai nomainīt to īpašnieku.
|
||||
still_has_org=Jūsu esat vismaz vienas organizācijas biedrs, sākumā nepieciešams pamest vai izdzēst šo organizāciju.
|
||||
org_still_own_repo=Šī organizācija ir vismaz viena repozitorija īpašnieks, tos sākumā ir nepieciešams izdzēst vai nomainīt to īpašnieku.
|
||||
|
||||
still_own_user=Šo autentifikāciju joprojām izmanto vismaz viens lietotājs, nepieciešams šiem lietotājiem nomainīt autentifikācijas veidu vai tos izdzēst.
|
||||
|
||||
target_branch_not_exist=Mērķa atzars neeksistē
|
||||
|
||||
[user]
|
||||
change_avatar=Mainīt savu profila attēlu vietnē gravatar.com
|
||||
change_custom_avatar=Mainīt savu profila attēlu iestatījumos
|
||||
join_on=Pievienojās
|
||||
repositories=Repozitoriji
|
||||
activity=Publiskā aktivitāte
|
||||
followers=Sekotāji
|
||||
starred=Atzīmēti ar zvaigznīti
|
||||
following=Seko
|
||||
|
||||
[settings]
|
||||
profile=Profils
|
||||
password=Parole
|
||||
ssh_keys=SSH atslēgas
|
||||
social=Sociālie konti
|
||||
applications=Lietotnes
|
||||
orgs=Organizācijas
|
||||
delete=Dzēst kontu
|
||||
uid=Lietotāja ID
|
||||
|
||||
public_profile=Publiskais profils
|
||||
profile_desc=Jūsu e-pasta adrese ir publiska un tiks izmantota, lai nosūtītju Jums paziņojumus, kas saistīti ar Jūsu kontu vai darbībām veiktām caur šo mājas lapu.
|
||||
full_name=Pilns vārds
|
||||
website=Mājas lapa
|
||||
location=Atrašanās vieta
|
||||
update_profile=Mainīt profilu
|
||||
update_profile_success=Jūsu profila dati ir veiksmīgi saglabāti.
|
||||
change_username=Lietotāja vārds mainīts
|
||||
change_username_desc=Lietotājvārds tiks mainīts, vai vēlaties turpināt? Tas ietekmēs visas saites, kas attiecas uz Jūsu kontu.
|
||||
continue=Turpināt
|
||||
cancel=Atcelt
|
||||
|
||||
enable_custom_avatar=Iespējot maināmu profila attēlu
|
||||
enable_custom_avatar_helper=Iespējojiet šo, lai atslēgtu profilu attēlu ņemšanu no gravatar.com
|
||||
choose_new_avatar=Izvēlēties jaunu profila attēlu
|
||||
update_avatar=Saglabāt profila bildi
|
||||
uploaded_avatar_not_a_image=Augšupielādētais fails nav attēls.
|
||||
no_custom_avatar_available=Nav iespējams mainīt profila bildi.
|
||||
update_avatar_success=Jūsu profila bilde tika veiksmīgi saglabāta.
|
||||
|
||||
change_password=Mainīt paroli
|
||||
old_password=Pašreizējā parole
|
||||
new_password=Jauna parole
|
||||
password_incorrect=Ievadīta nepareiza pašreizējā parole.
|
||||
change_password_success=Parole tika veiksmīgi nomainīta. Tagad jūs varat pieraksītites, izmantojot jauno paroli.
|
||||
|
||||
emails=E-pasta adreses
|
||||
manage_emails=Pārvaldīt e-pasta adreses
|
||||
email_desc=Primārā e-pasta adrese tiks izmantota sūtot notifikācijas un citām dabībām.
|
||||
primary=Primārā
|
||||
primary_email=Iestatīt kā primāro
|
||||
delete_email=Dzēst
|
||||
add_new_email=Pievienot jaunu e-pasta adresi
|
||||
add_email=Pievienot e-pastu
|
||||
add_email_success=Jūsu jaunā e-pasta adrese tika veiksmīgi pievienota.
|
||||
|
||||
manage_ssh_keys=Pārvaldīt SSH atslēgas
|
||||
add_key=Pievienot atslēgu
|
||||
ssh_desc=Šis ir saraksts ar Jūsu kontam piesaistītajām SSH atslēgām. Dzēsiet visas, kuras Jūs neatpazīstat.
|
||||
ssh_helper=<strong>Vajadzīga palīdzība?</strong> Apskatieties pamācību kā <a href="%s">ģenerēt SSH atslēgas</a> vai kā novērst <a href="%s">biežāk sastopamās SSH problēmas</a>.
|
||||
add_new_key=Pievienot SSH atslēgu
|
||||
key_name=Atslēgas nosaukums
|
||||
key_content=Saturs
|
||||
add_key_success=Pievienota jauna SSH atslēga!
|
||||
delete_key=Dzēst
|
||||
add_on=Pievienota
|
||||
last_used=Pēdējo reizi izmantota
|
||||
no_activity=Nav nesenas aktivitātes
|
||||
|
||||
manage_social=Pārvaldīt piesaistītos sociālos kontus
|
||||
social_desc=Šeit tiek attēloti visi sociālie konti, kas ir piesaistīti Jūsu kontam. Dzēsiet visus, kurus Jūs neatpazīstat.
|
||||
unbind=Atsaistīt
|
||||
unbind_success=Sociālais konts tika atsaistīts.
|
||||
|
||||
manage_access_token=Pārvaldīt personīgos piekļuves talonus
|
||||
generate_new_token=Ģenerēt jaunu talonu
|
||||
tokens_desc=Talons tika uzģēnerēts, tagad varat to izmantot, lai piekļūtu Gogs API.
|
||||
new_token_desc=Pašlaik visiem taloniem ir pilna piekļuve Jūsu kontam.
|
||||
token_name=Talona nosaukums
|
||||
generate_token=Ģenerēt talonu
|
||||
generate_token_succees=Jauns piekļuves talons tika veiksmīgi uzģenerēts! Pārliecinieties, ka esat to nokopējis, jo to Jums vairāk nebūs iespēja izdarīt!
|
||||
delete_token=Dzēst
|
||||
delete_token_success=Jūsu personīgās piekļuves talons tika veiksmīgi izdzēsts! Neazimistiet veikt nepieciešamos labojumus savās lietojumprogrammās, kas to izmantoja.
|
||||
|
||||
delete_account=Dzēst savu kontu
|
||||
delete_prompt=Šī darbība pilnībā izdzēsīs Jūsu kontu, kā arī tā ir <strong>NEATGRIEZENISKA</strong>!
|
||||
confirm_delete_account=Apstiprināt dzēšanu
|
||||
delete_account_title=Konta dzēšana
|
||||
delete_account_desc=Šis konts tiks neatgriezeniski dzēsts, vai vēlaties turpināt?
|
||||
|
||||
[repo]
|
||||
owner=Īpašnieks
|
||||
repo_name=Repozitorija nosaukums
|
||||
repo_name_helper=Labi repzotoriju nosaukumi ir īsi, tādi kurus viegli atcerēties un <strong>unikāli</strong>.
|
||||
visibility=Redzamība
|
||||
visiblity_helper=Šis repozitorijs ir <span class="label label-red label-radius">Privāts</span>
|
||||
fork_repo=Atdalīt repozitoriju
|
||||
fork_from=Atdalīt no
|
||||
fork_visiblity_helper=Atdalītam repozitorijam nav iespējams nomainīt tā redzamību
|
||||
repo_desc=Apraksts
|
||||
repo_lang=Valoda
|
||||
repo_lang_helper=Izvēlieties .gitignore failu
|
||||
license=Licence
|
||||
license_helper=Izvēlieties licences failu
|
||||
init_readme=Inicializēt šo repozitoriju ar README.md failu
|
||||
create_repo=Izveidot repozitoriju
|
||||
default_branch=Noklusējuma atzars
|
||||
mirror_interval=Spoguļošanas intervāls (stundās)
|
||||
goget_meta=Go-Get metadati
|
||||
goget_meta_helper=Šis repozitorijs saturēs <span class="label label-blue label-radius">Go-Get</span> metadatus
|
||||
|
||||
need_auth=Nepieciešama autorizācija
|
||||
migrate_type=Migrācijas veids
|
||||
migrate_type_helper=Šis repozitorijs būs <span class="label label-blue label-radius">Spoguļots</span>
|
||||
migrate_repo=Migrēt repozitoriju
|
||||
|
||||
copy_link=Kopēt
|
||||
click_to_copy=Kopēt uz starpliktuvi
|
||||
copied=Kopēšana notikusi veiksmīgi
|
||||
clone_helper=Nepieciešama palīdzība kā veikt klonēšana? Apmeklējiet <a target="_blank" href="%s">Palīdzība</a> lapu!
|
||||
unwatch=Nevērot
|
||||
watch=Vērot
|
||||
unstar=Noņemt zvaigznīti
|
||||
star=Pievienot zvaigznīti
|
||||
fork=Atdalīts
|
||||
|
||||
no_desc=Nav apraksta
|
||||
quick_guide=Īsa pamācība
|
||||
clone_this_repo=Klonēt šo repozitoriju
|
||||
create_new_repo_command=Izveidot jaunu repozitoriju komandrindā
|
||||
push_exist_repo=Nosūtīt izmaiņas no komandrindas eksistējošam repozitorijam
|
||||
|
||||
branch=Atzars
|
||||
tree=Koks
|
||||
branch_and_tags=Atzari un tagi
|
||||
branches=Atzari
|
||||
tags=Tagi
|
||||
issues=Problēmas
|
||||
commits=Revīzijas
|
||||
releases=Laidieni
|
||||
file_raw=Neapstrādāts
|
||||
file_history=Vēsture
|
||||
file_view_raw=Rādīt neapstrādātu
|
||||
|
||||
commits.commits=Revīzijas
|
||||
commits.search=Meklēt revīzijas
|
||||
commits.find=Meklēt
|
||||
commits.author=Autors
|
||||
commits.message=Ziņojums
|
||||
commits.date=Datums
|
||||
commits.older=Vecāki
|
||||
commits.newer=Jaunāki
|
||||
|
||||
settings=Iestatījumi
|
||||
settings.options=Opcijas
|
||||
settings.collaboration=Sadarbība
|
||||
settings.hooks=Tīmekļa āķi
|
||||
settings.githooks=Git āķi
|
||||
settings.deploy_keys=Izvietot atslēgas
|
||||
settings.basic_settings=Pamatiestatījumi
|
||||
settings.danger_zone=Bīstamā zona
|
||||
settings.site=Oficiālā mājas lapa
|
||||
settings.update_settings=Mainīt iestatījumus
|
||||
settings.change_reponame=Mainīts repozitorija nosaukums
|
||||
settings.change_reponame_desc=Repozitorija nosaukums tiks mainīts, vai vēlaties turpināt? Tas ietekmēs visas saites, kas saistītas ar šo repozitoriju.
|
||||
settings.transfer=Mainīt īpašnieku
|
||||
settings.transfer_desc=Mainīt šī repozitorija īpašnieku uz citu lietotāju vai organizāciju, kurai Jums ir administratora tiesībs.
|
||||
settings.new_owner_has_same_repo=Jaunajam īpašniekam jau ir repozitorijs ar šādu nosaukumu.
|
||||
settings.delete=Dzēst šo repozitoriju
|
||||
settings.delete_desc=Dzēšot repozitoriju, tā datus vairs nebūs iespējams atgūt. Pirms dzēšanas pārliecinieites vai patiešām vēlaties to darīt.
|
||||
settings.transfer_notices=<p>- Jūs zaudēsiet piekļuvi repozitorijam, ja jaunais īpašnieks ir individuāls lietotājs.</p><p>- Jūs saglabāsiet piekļuvi repzitorijam, ja jaunais īpašneiks ir organizācija un Jūs esat viens no tās īpašniekiem.</p>
|
||||
settings.update_settings_success=Repozitorija opcijas ir veiksmīgi saglabātas.
|
||||
settings.transfer_owner=Jaunais īpašnieks
|
||||
settings.make_transfer=Mainīt
|
||||
settings.transfer_succeed=Repozitorija īpašnieks ir veiksmīgi nomainīts.
|
||||
settings.confirm_delete=Apstiprināt dzēšanu
|
||||
settings.add_collaborator=Pievienot jaunu līdzstrādnieku
|
||||
settings.add_collaborator_success=Jauns līdzstrādnieks ir pievienots.
|
||||
settings.remove_collaborator_success=Līdzstrādnieks tika noņemts.
|
||||
settings.user_is_org_member=Lietotājs ir organizācijas biedrs, kas nevar tikt pievienots kā līdzstrādnieks.
|
||||
settings.add_webhook=Pievienot tīmekļa āķi
|
||||
settings.hooks_desc=Tīmekļa āķi ļauj paziņot ārējiem servisiem par noteiktiem notikomiem, kas notiek Git servisā. Kad iestāsies kāds notikums, katram ārējā servisa URL tiks nosūtīts POST pieprasījums. Lai uzzinātu sīkāk skatieties <a target="_blank" href="%s">Tīmekļa āķu rokasgrāmatā</a>.
|
||||
settings.githooks_desc=Git āķus apstrādā pats Git. Jūs varat labot atbalsīto āku failus sarakstā zemāk, lai veiktu pielāgotas darbības.
|
||||
settings.githook_edit_desc=Ja āķis nav aktīvs, tiks attēlots piemērs kā to izmantot. Atstājot āķa saturu tukšu, tas tiks atspējots.
|
||||
settings.githook_name=Āķa nosaukums
|
||||
settings.githook_content=Āķa saturs
|
||||
settings.update_githook=Labot āķi
|
||||
settings.remove_hook_success=Tīmekļa āķis tika noņemts.
|
||||
settings.add_webhook_desc=Uz norādīto URL tiks nosūtīts <code>POST</code> pieprasījums ar notikuma datiem. Jūs varat norādīt arī datu formātu, kādā datus vēlaties saņemt (JSON, <code>x-www-form-urlencoded</code> <em>utt.</em>). Detalizētāku informāciju ir iespējams uzzināt <a target="_blank" href="%s">Tīmekļa āķu rokasgrāmatā</a>.
|
||||
settings.payload_url=Vērtuma URL
|
||||
settings.content_type=Satura tips
|
||||
settings.secret=Noslēpums
|
||||
settings.event_desc=Kādu notikumu rezultātā tiktu izsaukts tīmekļā āķis?
|
||||
settings.event_push_only=Tikai izmaiņu nosūtīšanas notikumiem.
|
||||
settings.active=Aktīvs
|
||||
settings.active_helper=Tiks nosūtīti notikuma dati, kad nostrādās šis āķis.
|
||||
settings.add_hook_success=Jauns tīmekļa āķis tika veiksmīgi pievienots.
|
||||
settings.update_webhook=Mainīt tīmekļa āķi
|
||||
settings.update_hook_success=Tīmekļa āķist tika veiksmīgi saglabāts.
|
||||
settings.delete_webhook=Dzēst tīmekļa āķi
|
||||
settings.recent_deliveries=Pēdējās piegādes
|
||||
settings.hook_type=Āķa veids
|
||||
settings.add_slack_hook_desc=PIevienot <a href="%s">Slack</a> integrāciju Jūsu repozitorijā.
|
||||
settings.slack_token=Talons
|
||||
settings.slack_domain=Domēns
|
||||
settings.slack_channel=Kanāls
|
||||
|
||||
diff.browse_source=Pārlūkot izejas kodu
|
||||
diff.parent=vecāks
|
||||
diff.commit=revīzija
|
||||
diff.data_not_available=Salīdzināšanas dati nav pieejami.
|
||||
diff.show_diff_stats=Rādīt salīdzināšanas statistiku
|
||||
diff.stats_desc=<strong>%d mainītis faili</strong> ar <strong>%d papildinājumiem</strong> un <strong>%d dzēšanām</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Parādīt failu
|
||||
|
||||
release.releases=Laidieni
|
||||
release.new_release=Jauns laidiens
|
||||
release.draft=Melnraksts
|
||||
release.prerelease=Pirmsizlaides versija
|
||||
release.stable=Stabila
|
||||
release.edit=labot
|
||||
release.ahead=<strong>%d</strong> revīzijas atzarā %s kopš šī laidiena
|
||||
release.source_code=Izejas kods
|
||||
release.tag_name=Taga nosaukums
|
||||
release.target=Mērķis
|
||||
release.tag_helper=Publicējot, izvēlieties esošu vai izveidojiet jaunu tagu.
|
||||
release.release_title=Laidiena virsraksts
|
||||
release.content_with_md=Saturs ar <a href="%s">Markdown</a>
|
||||
release.write=Rakstīt
|
||||
release.preview=Priekšskatītījums
|
||||
release.content_placeholder=Uzrakstiet kādu aprakstu
|
||||
release.loading=Notiek ielāde...
|
||||
release.prerelease_desc=Šī ir pirmslaidiena versija
|
||||
release.prerelease_helper=Tiks norādīts, ka šis laidiens nav gatavs lietošanai produkcijas režīmā.
|
||||
release.publish=Publicēt laidienu
|
||||
release.save_draft=Saglabāt melnrakstu
|
||||
release.edit_release=Labot laidienu
|
||||
release.tag_name_already_exist=Laidiens ar šādu taga nosaukumu jau eksistē.
|
||||
|
||||
[org]
|
||||
org_name_holder=Organizācijas nosaukums
|
||||
org_name_helper=Labi organizāciju nosaukumi ir īsi un tādi, kurus viegli atcerēties.
|
||||
org_email_helper=Uz organizācijas e-pastu tiks sūtītas visas notifikācias un apstiprinājumi.
|
||||
create_org=Izveidot organizāciju
|
||||
repo_updated=Atjaunināts
|
||||
people=Personas
|
||||
invite_someone=Uzaicināt kādu
|
||||
teams=Komandas
|
||||
lower_members=dalībnieki
|
||||
lower_repositories=repozitoriji
|
||||
create_new_team=Izveidot jaunu komandu
|
||||
org_desc=Apraksts
|
||||
team_name=Komandas nosaukums
|
||||
team_desc=Apraksts
|
||||
team_name_helper=Šo nosaukumu varēs izmantot, lai pieminētu komandu sarunās.
|
||||
team_desc_helper=Komandas apraksts
|
||||
team_permission_desc=Kādām tiesībām šai komandai būtu jābūt?
|
||||
|
||||
settings=Iestatījumi
|
||||
settings.options=Opcijas
|
||||
settings.full_name=Pilns vārds, uzvārds
|
||||
settings.website=Mājas lapa
|
||||
settings.location=Atrašanās vieta
|
||||
settings.update_settings=Mainīt iestatījumus
|
||||
settings.change_orgname=Mainīts organizācijas nosaukums
|
||||
settings.change_orgname_desc=Organizācijas nosaukums tiks mainīts, vai vēlaties turpinat? Tas ietekmēs saites, kas attiecas uz šo organizāciju.
|
||||
settings.update_setting_success=Organizācijas iestatījumi tika veiksmīgi saglabāti.
|
||||
settings.delete=Dzēst organizāciju
|
||||
settings.delete_account=Dzēst šo organizāciju
|
||||
settings.delete_prompt=Šī darbība pilnībā dzēsīs šo organizāciju, kā arī tā ir <strong>NEATGRIEZENISKA</strong>!
|
||||
settings.confirm_delete_account=Apstiprināt dzēšanu
|
||||
settings.delete_org_title=Organizācijas dzēšana
|
||||
settings.delete_org_desc=Šī organizācija tiks pilnībā izdzēsta, vai vēlaties turpināt?
|
||||
settings.hooks_desc=Pievienot tīmekļa āķus, kas nostrādās <strong>visiem repozitorijiem</strong> šajā organizācijā.
|
||||
|
||||
members.public=Publisks
|
||||
members.public_helper=padarīt privātu
|
||||
members.private=Privāts
|
||||
members.private_helper=padarīt publisku
|
||||
members.owner=Īpašnieks
|
||||
members.member=Biedri
|
||||
members.conceal=Noslēpt
|
||||
members.remove=Noņemt
|
||||
members.leave=Atstāt
|
||||
members.invite_desc=Sāciet rakstīt lietotājvārdu, lai uzaicinātu jaunu biedru organizācijā %s:
|
||||
members.invite_now=Uzaicināt tagad
|
||||
|
||||
teams.join=Pievienoties
|
||||
teams.leave=Atstāt
|
||||
teams.read_access=Lasīšanas piekļuve
|
||||
teams.read_access_helper=Komanda varēs skatīties un klonēt šīs organizācijas repozitorijus.
|
||||
teams.write_access=Rakstīšanas piekļuve
|
||||
teams.write_access_helper=Komanda varēs skatīties un klonēt, kā arī nosūtīt izmaiņas šīs organizācijas repozitorijiem.
|
||||
teams.admin_access=Administratora piekļuve
|
||||
teams.admin_access_helper=Šī komanda varēs veikt push/pull komandas tās repozitorijiem, kā arī tiem pievienot citus līdzstrādniekus.
|
||||
teams.no_desc=Komandai nav apraksta
|
||||
teams.settings=Iestatījumi
|
||||
teams.owners_permission_desc=Īpašniekiem ir pilna piekļuve <strong>visiem repozitorijiem</strong> un ir organizācijas <strong>administratora tiesības</strong>.
|
||||
teams.members=Komandas biedri
|
||||
teams.update_settings=Saglabāt iestatījumus
|
||||
teams.delete_team=Dzēst komandu
|
||||
teams.add_team_member=Pievienot komandas biedru
|
||||
teams.delete_team_title=Komandas dzēšana
|
||||
teams.delete_team_desc=Komanda tiks dzēsta, vai vēlaties turpināt? Komandas biedri var zaudēt piekļuvi dažiem vai pat visiem repozitorijiem.
|
||||
teams.delete_team_success=Komanda tika veiksmīgi izdzēsta.
|
||||
teams.read_permission_desc=Šai komandai ir <strong>lasīšanas</strong> tiesības: dalībnieki var skatīties un klonēt komandas repozitorijus.
|
||||
teams.write_permission_desc=Šai komandai ir <strong>rakstīšanas</strong> tiesības: dalībnieki var lasīt un nosūtīt izmaiņas repozitorijiem.
|
||||
teams.admin_permission_desc=Šai komandai ir <strong>administratora</strong> tiesības: dalībnieki var lasīt, rakstīt un pievienot citus dalībniekus komandas repozitorijiem.
|
||||
teams.repositories=Komandas repozitoriji
|
||||
teams.add_team_repository=Pievienot komandas repozitoriju
|
||||
teams.remove_repo=Noņemt
|
||||
teams.add_nonexistent_repo=Repozitorijs, kuram Jūs mēģinat pievienot neeksistē, sākumā izveidojiet to.
|
||||
|
||||
[admin]
|
||||
dashboard=Infopanelis
|
||||
users=Lietotāji
|
||||
organizations=Organizācijas
|
||||
repositories=Repozitoriji
|
||||
authentication=Autentifikācijas
|
||||
config=Konfigurācija
|
||||
notices=Sistēmas paziņojumi
|
||||
monitor=Uzraudzība
|
||||
prev=Iepr.
|
||||
next=Tālāk
|
||||
|
||||
dashboard.statistic=Statistika
|
||||
dashboard.operations=Darbības
|
||||
dashboard.system_status=Sistēmas uzraudzības statuss
|
||||
dashboard.statistic_info=Gogs datu bāze satur <b>%d</b> lietotājus, <b>%d</b> organizācijas, <b>%d</b> publiskās atslēgas, <b>%d</b> repozitorijus, <b>%d</b> vērošanas, <b>%d</b> atzīmētas zvaigznītes, <b>%d</b> darbības, <b>%d</b> piekļuves, <b>%d</b> problēmas, <b>%d</b> komentārus, <b>%d</b> sociālos kontus, <b>%d</b> sekošanas, <b>%d</b> spoguļošanas, <b>%d</b> izlaides, <b>%d</b> login sources, <b>%d</b> tīmekļa āķus, <b>%d</b> starpposmus, <b>%d</b> etiķetes, <b>%d</b> āķu uzdevumus, <b>%d</b> komandas, <b>%d</b> labotus uzdevumus, <b>%d</b> pielikumus.
|
||||
dashboard.operation_name=Darbības nosaukums
|
||||
dashboard.operation_switch=Pārslēgt
|
||||
dashboard.operation_run=Palaist
|
||||
dashboard.clean_unbind_oauth=Notīrīt nesaistītās OAuth biļetes
|
||||
dashboard.clean_unbind_oauth_success=Visas nesaistītās OAuth biļetes tika veiksmīgi izdzēstas.
|
||||
dashboard.delete_inactivate_accounts=Dzēst visus neaktīvos kontus
|
||||
dashboard.delete_inactivate_accounts_success=Visi neaktīvie kotni tika veiksmīgi izdzēsti.
|
||||
dashboard.delete_repo_archives=Dzēst visu repozitoriju arhīvus
|
||||
dashboard.delete_repo_archives_success=Visu repozitoriju arhīvi tika veiksmīgi izdzēsti.
|
||||
dashboard.git_gc_repos=Veikt repozitoriju datu sakārtošānu (git gc)
|
||||
dashboard.git_gc_repos_success=Datu sakārtošana visiem repozitorijiem veiksmīgi pabeigta.
|
||||
dashboard.resync_all_sshkeys=Pārrakstīt '.ssh/authorized_key' failu (brīdinājums: ne-Git atslēgas tiks pazaudētas)
|
||||
dashboard.resync_all_sshkeys_success=Visas publiskās atslēgas tika veiksmīgi pārrakstītas.
|
||||
dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
|
||||
dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
|
||||
|
||||
dashboard.server_uptime=Servera darbības laiks
|
||||
dashboard.current_goroutine=Izmantotās Gorutīnas
|
||||
dashboard.current_memory_usage=Pašreiz izmantotā atmiņa
|
||||
dashboard.total_memory_allocated=Kopējā piešķirtā atmiņa
|
||||
dashboard.memory_obtained=Iegūtā atmiņa
|
||||
dashboard.pointer_lookup_times=Rādītāju meklēšanas reizes
|
||||
dashboard.memory_allocate_times=Atmiņas piešķiršanas reizes
|
||||
dashboard.memory_free_times=Atmiņas atbrīvošanas reizes
|
||||
dashboard.current_heap_usage=Pašreizējā kaudzes izmantošana
|
||||
dashboard.heap_memory_obtained=Iegūtā kaudzes atmiņa
|
||||
dashboard.heap_memory_idle=Neizmantotā kaudzes atmiņa
|
||||
dashboard.heap_memory_in_use=Izmantotā kaudzes atmiņa
|
||||
dashboard.heap_memory_released=Atbrīvotā kaudzes atmiņa
|
||||
dashboard.heap_objects=Kaudzes atmiņas objekti
|
||||
dashboard.bootstrap_stack_usage=Izmantotais sāknēšanas steka lielums
|
||||
dashboard.stack_memory_obtained=Iegūtā steka atmiņa
|
||||
dashboard.mspan_structures_usage=Izmantotās MSpan struktūras
|
||||
dashboard.mspan_structures_obtained=Iegūtās MSpan struktūras
|
||||
dashboard.mcache_structures_usage=Izmantotās MCache struktūras
|
||||
dashboard.mcache_structures_obtained=Iegūtās MCache struktūras
|
||||
dashboard.profiling_bucket_hash_table_obtained=Iegūtā profilēšanas kausa jaucējtabula
|
||||
dashboard.gc_metadata_obtained=Iegūtie GC metadati
|
||||
dashboard.other_system_allocation_obtained=Iegūtās citas sistēmas sadales
|
||||
dashboard.next_gc_recycle=Nākošā GC atkritne
|
||||
dashboard.last_gc_time=Laiks kopš pēdējās GC
|
||||
dashboard.total_gc_time=Kopējais GC izpildes laiks
|
||||
dashboard.total_gc_pause=Kopējais GC izpildes laiks
|
||||
dashboard.last_gc_pause=Pedējās GC izpildes laiks
|
||||
dashboard.gc_times=GC reizes
|
||||
|
||||
users.user_manage_panel=Lietotāju pārvaldības panelis
|
||||
users.new_account=Izveidot jaunu kontu
|
||||
users.name=Vārds
|
||||
users.activated=Aktivizēts
|
||||
users.admin=Administrators
|
||||
users.repos=Repozitoriji
|
||||
users.created=Izveidots
|
||||
users.edit=Labot
|
||||
users.auth_source=Autorizācijas avots
|
||||
users.local=Iebūvētā
|
||||
users.auth_login_name=Autorizāciju, pietiekšanās vārds
|
||||
users.update_profile_success=Konta profils tika veiksmīgi saglabāts.
|
||||
users.edit_account=Labot kontu
|
||||
users.is_activated=Konts ir aktivizēts
|
||||
users.is_admin=Šim kontam ir administratora piekļuves tiesības
|
||||
users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus
|
||||
users.update_profile=Mainīt konta profilu
|
||||
users.delete_account=Dzēst šo kontu
|
||||
users.still_own_repo=Šis konts ir vismaz viena repozitorija īpašnieks, tos sākumā ir nepieciešams izdzēst vai nomainīt to īpašnieku.
|
||||
users.still_has_org=Šis konts ir vismaz vienas organizācijas biedrs, sākumā nepieciešams pamest vai izdzēst šo organizāciju.
|
||||
|
||||
orgs.org_manage_panel=Organizāciju pārvaldības panelis
|
||||
orgs.name=Nosaukums
|
||||
orgs.teams=Komandas
|
||||
orgs.members=Dalībnieki
|
||||
|
||||
repos.repo_manage_panel=Repozitoriju pārvaldības panelis
|
||||
repos.owner=Īpašnieks
|
||||
repos.name=Vārds
|
||||
repos.private=Privāts
|
||||
repos.watches=Vērošana
|
||||
repos.stars=Atzīmētās zvaigznītes
|
||||
repos.issues=Problēmas
|
||||
|
||||
auths.auth_manage_panel=Autorizāciju pārvaldības panelis
|
||||
auths.new=Pievienot jaunu autorizācijas veidu
|
||||
auths.name=Nosaukums
|
||||
auths.type=Veids
|
||||
auths.enabled=Iespējota
|
||||
auths.updated=Atjaunināta
|
||||
auths.auth_type=Autorizācijas veids
|
||||
auths.auth_name=Autorizācijas nosaukums
|
||||
auths.domain=Domēns
|
||||
auths.host=Resursdators
|
||||
auths.port=Ports
|
||||
auths.base_dn=Pamata DN
|
||||
auths.attributes=Meklēšanas atribūti
|
||||
auths.filter=Meklēšanas filtrs
|
||||
auths.ms_ad_sa=MS Ad SA
|
||||
auths.smtp_auth=SMTP autorizācijas veids
|
||||
auths.smtphost=SMTP resursdators
|
||||
auths.smtpport=SMTP ports
|
||||
auths.enable_tls=Iespējot TLS šifrēšanu
|
||||
auths.enable_auto_register=Iespējot automātisko reģistrāciju
|
||||
auths.tips=Padomi
|
||||
auths.edit=Labot autorizācijas iestatījumus
|
||||
auths.activated=Autentifikācija ir aktivizēta
|
||||
auths.update_success=Autorizācijas iestatījumi tika veiksmīgi saglabāti.
|
||||
auths.update=Mainīt autorizācijas iestatījumus
|
||||
auths.delete=Dzēst šo autorizāciju
|
||||
auths.delete_auth_title=Autorizācijas dzēšana
|
||||
auths.delete_auth_desc=Šī autorizācija tiks dzēsta, vai vēlaties turpināt?
|
||||
|
||||
config.server_config=Servera konfigurācija
|
||||
config.app_name=Lietotnes nosaukums
|
||||
config.app_ver=Lietotnes versija
|
||||
config.app_url=Lietotnes URL
|
||||
config.domain=Domēns
|
||||
config.offline_mode=Bezsaistes režīms
|
||||
config.disable_router_log=Atspējot maršrutētāja žurnalizēšanu
|
||||
config.run_user=Izpildes lietotājs
|
||||
config.run_mode=Izpildes režīms
|
||||
config.repo_root_path=Repozitoriju glabāšanas vieta
|
||||
config.static_file_root_path=Statisko failu atrašanās vieta
|
||||
config.log_file_root_path=Žurnalizēšanas failu glabāšanas vieta
|
||||
config.script_type=Skripta veids
|
||||
config.reverse_auth_user=Reversā lietotāja autentifikācija
|
||||
config.db_config=Datu bāzes konfigurācija
|
||||
config.db_type=Veids
|
||||
config.db_host=Resursdators
|
||||
config.db_name=Nosaukums
|
||||
config.db_user=Lietotājs
|
||||
config.db_ssl_mode=SSL režīms
|
||||
config.db_ssl_mode_helper=(tikai PostgreSQL datu bāzei)
|
||||
config.db_path=Ceļš
|
||||
config.db_path_helper=(tikai Sqlite3 datu bāzei)
|
||||
config.service_config=Pakalpojuma konfigurācija
|
||||
config.register_email_confirm=Pieprasīt e-pasta apstiprināšanu
|
||||
config.disable_register=Atspējot jaunu lietotāju reģistrāciju
|
||||
config.show_registration_button=Rādīt reģistrēšanās pogu
|
||||
config.require_sign_in_view=Nepieciešama autorizācija
|
||||
config.mail_notify=Pasta paziņojumi
|
||||
config.enable_cache_avatar=Glabāt profila attēlus kešatmiņā
|
||||
config.active_code_lives=Aktīvā koda ilgums
|
||||
config.reset_password_code_lives=Paroles atiestatīšanas koda ilgums
|
||||
config.webhook_config=Tīkla āķu konfigurācija
|
||||
config.task_interval=Uzdevuma intervāls
|
||||
config.deliver_timeout=Piegādes noildze
|
||||
config.skip_tls_verify=Skip TLS Verify
|
||||
config.mailer_config=Sūtītāja konfigurācija
|
||||
config.mailer_enabled=Iespējots
|
||||
config.mailer_name=Nosaukums
|
||||
config.mailer_host=Resursdators
|
||||
config.mailer_user=Lietotājs
|
||||
config.oauth_config=OAuth konfigurācija
|
||||
config.oauth_enabled=Iespējota
|
||||
config.cache_config=Kešatmiņas konfigurācija
|
||||
config.cache_adapter=Kešatmiņas adapteris
|
||||
config.cache_interval=Kešatmiņas intervāls
|
||||
config.cache_conn=Kešatmiņas pieslēguma parametri
|
||||
config.session_config=Sesijas konfigurācja
|
||||
config.session_provider=Sesijas nodrošinātājs
|
||||
config.provider_config=Pakalpojumu sniedzēja konfigurācija
|
||||
config.cookie_name=Sīkdatnes nosaukums
|
||||
config.enable_set_cookie=Ļaut izmantot sīkdatnes
|
||||
config.gc_interval_time=GC laika intervāls
|
||||
config.session_life_time=Sesijas ilgums
|
||||
config.https_only=Tikai HTTPS
|
||||
config.cookie_life_time=Sīkdatņu glabāšanas ilgums
|
||||
config.picture_config=Attēlu konfigurācija
|
||||
config.picture_service=Lokāli attēli
|
||||
config.disable_gravatar=Atspējot Gravatar
|
||||
config.log_config=Žurnalizēšanas konfigurācija
|
||||
config.log_mode=Žurnalizēšanas veids
|
||||
|
||||
monitor.cron=Cron uzdevumi
|
||||
monitor.name=Nosaukums
|
||||
monitor.schedule=Grafiks
|
||||
monitor.next=Nākošās izpildes laiks
|
||||
monitor.previous=Pēdējās izpildes laiks
|
||||
monitor.execute_times=Izpilžu skaits
|
||||
monitor.process=Darbojošies procesi
|
||||
monitor.desc=Apraksts
|
||||
monitor.start=Sākuma laiks
|
||||
monitor.execute_time=Izpildes laiks
|
||||
|
||||
notices.system_notice_list=Sistēmas paziņojumi
|
||||
notices.type=Veids
|
||||
notices.type_1=Repozitorijs
|
||||
notices.desc=Apraksts
|
||||
notices.op=Op.
|
||||
notices.delete_success=Sistēmas paziņojums tika veiksmīgi izdzēsts.
|
||||
|
||||
[action]
|
||||
create_repo=izveidoja repozitoriju <a href="%s/%s">%s</a>
|
||||
commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%s/%s/src/%s">%s</a> repozitorijā <a href="%s/%s">%s</a>
|
||||
create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="/%s%s">%s</a>
|
||||
push_tag=pievienoja tagu <a href="%s/%s/src/%s">%s</a> repozitorijam <a href="%s/%s">%s</a>
|
||||
compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām
|
||||
|
||||
[tool]
|
||||
ago=atpakaļ
|
||||
from_now=no šī brīža
|
||||
now=tagad
|
||||
1s=1 sekundi %s
|
||||
1m=1 minūti %s
|
||||
1h=1 stundu %s
|
||||
1d=1 dienu %s
|
||||
1w=1 nedēļu %s
|
||||
1mon=1 mēnesi %s
|
||||
1y=1 gadu %s
|
||||
seconds=%d sekundes %s
|
||||
minutes=%d minūtes %s
|
||||
hours=%d stundas %s
|
||||
days=%d dienas %s
|
||||
weeks=%d nedēļas %s
|
||||
months=%d mēneši %s
|
||||
years=%d gadi %s
|
||||
raw_seconds=sekundes
|
||||
raw_minutes=minūtes
|
||||
|
||||
1309
conf/locale/locale_nl-NL.ini
Normal file → Executable file
1309
conf/locale/locale_nl-NL.ini
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
724
conf/locale/locale_ru-RU.ini
Executable file
724
conf/locale/locale_ru-RU.ini
Executable file
@@ -0,0 +1,724 @@
|
||||
app_desc=Удобная служба для собственного Git-репозитория, написанная на языке Go
|
||||
|
||||
home=Главная
|
||||
dashboard=Панель мониторинга
|
||||
explore=Обзор
|
||||
help=Помощь
|
||||
sign_in=Войти
|
||||
social_sign_in=Вход через соцсеть: 2-й шаг <small>свяжите учетную запись</small>
|
||||
sign_out=Выход
|
||||
sign_up=Регистрация
|
||||
register=Зарегистрироваться
|
||||
website=Веб-сайт
|
||||
version=Версия
|
||||
page=Страница
|
||||
template=Шаблон
|
||||
language=Язык
|
||||
|
||||
username=Имя пользователя
|
||||
email=Эл. почта
|
||||
password=Пароль
|
||||
re_type=Повтор
|
||||
captcha=Captcha
|
||||
|
||||
repository=Репозиторий
|
||||
organization=Организация
|
||||
mirror=Зеркало
|
||||
new_repo=Новый репозиторий
|
||||
new_migrate=Новая Миграция
|
||||
new_fork=Новый проект из репозитория
|
||||
new_org=Новая Организация
|
||||
manage_org=Управление Организацией
|
||||
admin_panel=Панель администратора
|
||||
account_settings=Настройки аккаунта
|
||||
settings=Настройки
|
||||
|
||||
news_feed=Лента новостей
|
||||
pull_requests=Pull Requests
|
||||
issues=Вопросы
|
||||
|
||||
cancel=Отмена
|
||||
|
||||
[install]
|
||||
install=Установка
|
||||
title=Установочные шаги для первого запуска
|
||||
requite_db_desc=Для Gogs требуется MySQL, PostgreSQL или SQLite3.
|
||||
db_type=Тип базы данных
|
||||
host=Хост
|
||||
user=Пользователь
|
||||
password=Пароль
|
||||
db_name=Имя базы данных
|
||||
db_helper=Для MySQL используйте тип таблиц InnoDB с кодировкой utf8_general_ci.
|
||||
ssl_mode=Режим SSL
|
||||
path=Путь
|
||||
sqlite_helper=Путь к файлу базы данных SQLite3.
|
||||
general_title=Общие параметры Gogs
|
||||
repo_path=Путь корня репозитория
|
||||
repo_path_helper=Всех удаленные репозитории Git будет сохранены в этой директории.
|
||||
run_user=Пользователь
|
||||
run_user_helper=У пользователя должен быть доступ к пути к корню репозитория и к запуску Gogs.
|
||||
domain=Домен
|
||||
domain_helper=Влияет на URL-адреса для клонирования по SSH.
|
||||
http_port=Порт HTTP
|
||||
http_port_helper=Номер порта, который приложение будет слушать.
|
||||
app_url=URL приложения
|
||||
app_url_helper=Этот параметр влияет на URL для клонирования по HTTP/HTTPS и на адреса в электронной почте.
|
||||
email_title=Настройки службы электронной почты (опционально)
|
||||
smtp_host=Узел SMTP
|
||||
mailer_user=Электронная почта отправителя
|
||||
mailer_password=Пароль отправителя
|
||||
notify_title=Настройки уведомлений(опционально)
|
||||
register_confirm=Включить подтверждение регистрации
|
||||
mail_notify=Разрешить почтовые уведомления
|
||||
admin_title=Настройки учётной записи администратора
|
||||
admin_name=Имя пользователя
|
||||
admin_password=Пароль
|
||||
confirm_password=Подтвердить пароль
|
||||
admin_email=Эл. почта
|
||||
install_gogs=Установить Gogs
|
||||
test_git_failed=Не удалось проверить 'git' команду: %v
|
||||
sqlite3_not_available=Ваша версия не поддерживает SQLite3, пожалуйста скачайте официальную бинарную версию от %s, а не версию gobuild.
|
||||
invalid_db_setting=Настройки базы данных не правильные: %v
|
||||
invalid_repo_path=Недопустимый путь к корню репозитория: %v
|
||||
run_user_not_match=Текущий пользователь не является пользователем для запуска: %s -> %s
|
||||
save_config_failed=Не удалось сохранить конфигурацию: %v
|
||||
invalid_admin_setting=Указан недопустимый параметр учетной записи администратора: %v
|
||||
install_success=Добро пожаловать! Мы рады, что вы выбрали Gogs. Веселитесь и берегите себя.
|
||||
|
||||
[home]
|
||||
uname_holder=Имя пользователь или E-mail
|
||||
password_holder=Пароль
|
||||
switch_dashboard_context=Переключить контекст панели управления
|
||||
my_repos=Мои репозитории
|
||||
collaborative_repos=Совместные репозитории
|
||||
my_orgs=Моя Организация
|
||||
my_mirrors=Мои зеркала
|
||||
|
||||
[explore]
|
||||
repos=Репозитории
|
||||
|
||||
[auth]
|
||||
create_new_account=Создать новый аккаунт
|
||||
register_hepler_msg=Уже есть аккаунт? Авторизуйтесь!
|
||||
social_register_hepler_msg=Уже есть учетная запись? Свяжите ее с соцсетью!
|
||||
disable_register_prompt=Извините, возможность регистрации отключена. Пожалуйста, свяжитесь с администратором сайта.
|
||||
disable_register_mail=К сожалению подтверждение регистрации по почте отключено.
|
||||
remember_me=Запомнить меня
|
||||
forgot_password=Забыли пароль
|
||||
forget_password=Забыли пароль?
|
||||
sign_up_now=Нужен аккаунт? Зарегистрируйтесь.
|
||||
confirmation_mail_sent_prompt=Новое письмо для подтверждения было направлено на <b>%s</b>, пожалуйста, проверьте ваш почтовый ящик в течение %d часов для завершения регистрации.
|
||||
sign_in_email=Войдите в свой адрес электронной почты
|
||||
active_your_account=Активируйте свой аккаунт
|
||||
resent_limit_prompt=Вы слишком часто отправляете письмо с активацией. Подождите 3 минуты, пожалуйста.
|
||||
has_unconfirmed_mail=Здравствуйте, %s! У вас есть неподтвержденный адрес электронной почты (<b>%s</b>). Если вам не приходило письмо с подтверждением или нужно выслать новое письмо, нажмите на кнопку ниже.
|
||||
resend_mail=Нажмите здесь, чтобы переотправить активационное письмо
|
||||
email_not_associate=Этот адрес электронной почты не связан ни с одной учетной записью.
|
||||
send_reset_mail=Нажмите сюда, чтобы отправить письмо для сброса пароля
|
||||
reset_password=Сброс пароля
|
||||
invalid_code=Извините, ваш код подтверждения истек или не является допустимым.
|
||||
reset_password_helper=Нажмите здесь, чтобы сбросить свой пароль
|
||||
password_too_short=Длина пароля не менее 6 символов.
|
||||
|
||||
[form]
|
||||
UserName=Пользователь
|
||||
RepoName=Имя репозитория
|
||||
Email=Адрес эл. почты
|
||||
Password=Пароль
|
||||
Retype=Введите пароль еще раз
|
||||
SSHTitle=Имя SSH ключа
|
||||
HttpsUrl=URL HTTPS
|
||||
PayloadUrl=Payload URL
|
||||
TeamName=Название команды
|
||||
AuthName=Имя авторизации
|
||||
AdminEmail=Электронная почта администратора
|
||||
|
||||
require_error=«не может быть пустым.»
|
||||
alpha_dash_error=«должен быть допустимым символьным, числовым или dash(-_) значением.»
|
||||
alpha_dash_dot_error=«должен быть допустимым символьным, числовым или dash(-_) символами, включая точку.»
|
||||
min_size_error=«должен содержать по крайней мере %s символов.»
|
||||
max_size_error=` должен содержать максимум %s символов.`
|
||||
email_error=«не является адресом электронной почты.»
|
||||
url_error=«не является допустимым URL-адресом.»
|
||||
unknown_error=Неизвестная ошибка:
|
||||
captcha_incorrect=CAPTCHA не совпадает.
|
||||
password_not_match=Пароль и подтверждение пароля не совпадают.
|
||||
|
||||
username_been_taken=Имя пользователя уже принято.
|
||||
repo_name_been_taken=Имя репозитория уже принято.
|
||||
org_name_been_taken=Название организации было уже принято.
|
||||
team_name_been_taken=Название команды было уже принято.
|
||||
email_been_used=Адрес электронной почты уже используется.
|
||||
ssh_key_been_used=Имя открытого ключа уже используется.
|
||||
illegal_username=Ваше имя пользователя содержит недопустимые символы.
|
||||
illegal_repo_name=Имя репозитория содержит недопустимые знаки.
|
||||
illegal_org_name=Название организации содержит недопустимые знаки.
|
||||
illegal_team_name=Имя группы содержит недопустимые знаки.
|
||||
username_password_incorrect=Имя пользователя или пароль не правильный.
|
||||
enterred_invalid_repo_name=Пожалуйста, убедитесь, что введенно правильное имя хранилища.
|
||||
enterred_invalid_owner_name=Убедитесь, что введенное имя владельца верное.
|
||||
enterred_invalid_password=Убедитесь, что введенный пароль верен.
|
||||
user_not_exist=Данный пользователь не существует.
|
||||
last_org_owner=Удаляемый пользователь является последним в команде владельцев. Должен быть хотя бы один владелец.
|
||||
|
||||
invalid_ssh_key=К сожалению, мы не смогли проверить ваш SSH-ключ: %s
|
||||
unable_verify_ssh_key=Gogs не может проверить ваш SSH-ключ, но мы допускаем, что он действителен. Пожалуйста, удостоверьтесь самостоятельно, что ключ действителен.
|
||||
auth_failed=Ошибка аутентификации: %v
|
||||
|
||||
still_own_repo=На вашем аккаунте все еще остается как минимум один репозиторий, сначала вам нужно удалить или передать его.
|
||||
still_has_org=Вы находитесь в организации, сперва Вам необходимо покинуть ее или удалить.
|
||||
org_still_own_repo=Данная организация все еще является владельцем репозиториев, необходимо удалить или переместить их в начале.
|
||||
|
||||
still_own_user=Эта проверка подлинности по-прежнему используется некоторыми пользователями, вы должны переместить их и затем снова удалить.
|
||||
|
||||
target_branch_not_exist=Целевая ветка не существует
|
||||
|
||||
[user]
|
||||
change_avatar=Измените ваш аватар на gravatar.com
|
||||
change_custom_avatar=Измените ваш аватар в настройках
|
||||
join_on=Присоединилась к
|
||||
repositories=Репозитории
|
||||
activity=Активность
|
||||
followers=Подписчики
|
||||
starred=Избранное
|
||||
following=Подписан
|
||||
|
||||
[settings]
|
||||
profile=Профиль
|
||||
password=Пароль
|
||||
ssh_keys=SSH ключи
|
||||
social=Учетные записи в соцсетях
|
||||
applications=Приложения
|
||||
orgs=Организации
|
||||
delete=Удалить аккаунт
|
||||
uid=UID
|
||||
|
||||
public_profile=Открытый профиль
|
||||
profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт.
|
||||
full_name=ФИО
|
||||
website=Веб-сайт
|
||||
location=Местоположение
|
||||
update_profile=Обновить профиль
|
||||
update_profile_success=Ваш профиль был успешно обновлен.
|
||||
change_username=Имя пользователя изменено
|
||||
change_username_desc=Имя пользователя изменено, вы хотите продолжить? Это повлияет на все ссылки, связанные с вашей учетной записью.
|
||||
continue=Далее
|
||||
cancel=Отмена
|
||||
|
||||
enable_custom_avatar=Включить собственный аватар
|
||||
enable_custom_avatar_helper=Включите эту опцию, чтоб отключить загрузку с Gravatar
|
||||
choose_new_avatar=Выбрать новый аватар
|
||||
update_avatar=Обновить настройку аватара
|
||||
uploaded_avatar_not_a_image=Загружаемый файл не является изображением.
|
||||
no_custom_avatar_available=Собственный аватар недоступен, включить его невозможно.
|
||||
update_avatar_success=Настройка вашего аватара обновлена успешно.
|
||||
|
||||
change_password=Сменить пароль
|
||||
old_password=Текущий пароль
|
||||
new_password=Новый пароль
|
||||
password_incorrect=Текущий пароль не правильный.
|
||||
change_password_success=Пароль сменен успешно. Теперь вы можете войти с новым паролем.
|
||||
|
||||
emails=Адреса электронной почты
|
||||
manage_emails=Управление адресами электронной почты
|
||||
email_desc=Ваш основной адрес электронной почты будет использован для уведомлений и других операций.
|
||||
primary=Основной
|
||||
primary_email=Установить как основной
|
||||
delete_email=Удалить
|
||||
add_new_email=Добавить новый адрес электронной почты
|
||||
add_email=Добавить электронную почту
|
||||
add_email_success=Новый адрес электронной почты успешно добавлен.
|
||||
|
||||
manage_ssh_keys=Управление SSH ключами
|
||||
add_key=Добавить ключ
|
||||
ssh_desc=Это список ключей SSH связанных с вашей учетной записью. Удаляйте любые неизвестные вам ключи.
|
||||
ssh_helper=<strong>Нужна помощь?</strong> Ознакомьтесь с нашим путеводителем по <a href="%s">созданию SSH-ключей</a> или посмотрите решения <a href="%s">частых проблем, связанных с SSH</a>.
|
||||
add_new_key=Добавить SSH ключ
|
||||
key_name=Имя ключа
|
||||
key_content=Содержимое
|
||||
add_key_success=Был добавлен новый ключ SSH!
|
||||
delete_key=Удалить
|
||||
add_on=Добавлено
|
||||
last_used=Последний раз использовался
|
||||
no_activity=Еще не применялся
|
||||
|
||||
manage_social=Управление привязанными учетными записями в соцсетях
|
||||
social_desc=Это список привязанных учетных записей в соцсетях. Удаляйте любые неизвестные вам привязки.
|
||||
unbind=Отвязать
|
||||
unbind_success=Социальная учетная запись отвязана.
|
||||
|
||||
manage_access_token=Управление Токенами Персонального Доступа
|
||||
generate_new_token=Создать новый token
|
||||
tokens_desc=Созданные вами токены могут использоваться для доступа к Gogs API.
|
||||
new_token_desc=Пока что каждый токен будет иметь полный доступ к вашей учетной записи.
|
||||
token_name=Имя маркера
|
||||
generate_token=Генерировать маркер
|
||||
generate_token_succees=Успешно создан новый токен доступа! Пожалуйста сделайте копию вашего нового токена персонального доступа. Вы не сможете увидеть его снова!
|
||||
delete_token=Удалить
|
||||
delete_token_success=Персональный токен доступа был успешно удален! Не забудьте так же обновить ваши приложения.
|
||||
|
||||
delete_account=Удалить свой аккаунт
|
||||
delete_prompt=Этим действием вы удалите свою учетную запись навсегда и <strong>НЕ СМОЖЕТЕ</strong> ее вернуть!
|
||||
confirm_delete_account=Подтвердите удаление
|
||||
delete_account_title=Удаление аккаунта
|
||||
delete_account_desc=Эта учетная запись будет удалена насовсем. Вы хотите продолжить?
|
||||
|
||||
[repo]
|
||||
owner=Владелец
|
||||
repo_name=Имя репозитория
|
||||
repo_name_helper=Лучшие названия репозиториев коротки, запоминаемы и <strong>уникальны</strong>.
|
||||
visibility=Видимость
|
||||
visiblity_helper=Это хранилище — <span class="label label-red label-radius">частное</span>
|
||||
fork_repo=Ответвить репозиторий
|
||||
fork_from=Ответвление от
|
||||
fork_visiblity_helper=Ответвленному репозиторию нельзя поменять уровень видимости
|
||||
repo_desc=Описание
|
||||
repo_lang=Язык
|
||||
repo_lang_helper=Выберите файл .gitignore
|
||||
license=Лицензия
|
||||
license_helper=Выберите файл лицензии
|
||||
init_readme=Создать репозиторий с файлом README.md
|
||||
create_repo=Создание репозитория
|
||||
default_branch=Ветка по умолчанию
|
||||
mirror_interval=Интервал зеркалирования (час)
|
||||
goget_meta=Meta-тег для go get
|
||||
goget_meta_helper=Репозиторий будет доступен для <span class="label label-blue label-radius">go get</span>
|
||||
|
||||
need_auth=Требуется авторизация
|
||||
migrate_type=Тип миграции
|
||||
migrate_type_helper=Этот репозиторий будет <span class="label label-blue label-radius">зеркалом</span>
|
||||
migrate_repo=Перенос репозитория
|
||||
|
||||
copy_link=Копировать
|
||||
click_to_copy=Скопировать в буфер обмена
|
||||
copied=Успешно скопировано
|
||||
clone_helper=Нужна помощь в клонировании? Посетите страницу <a target="_blank" href="%s">помощи</a>!
|
||||
unwatch=Перестать следить
|
||||
watch=Следить
|
||||
unstar=Убрать из избранного
|
||||
star=В избранное
|
||||
fork=Ответвить
|
||||
|
||||
no_desc=Нет описания
|
||||
quick_guide=Краткое руководство
|
||||
clone_this_repo=Клонировать репозиторий
|
||||
create_new_repo_command=Создать новый репозиторий из командной строки
|
||||
push_exist_repo=Отправить существующий репозиторий из командной строки
|
||||
|
||||
branch=Ветка
|
||||
tree=Дерево
|
||||
branch_and_tags=Ветки и метки
|
||||
branches=Ветки
|
||||
tags=Метки
|
||||
issues=Обсуждения
|
||||
commits=Коммиты
|
||||
releases=Релизы
|
||||
file_raw=Raw
|
||||
file_history=История
|
||||
file_view_raw=View Raw
|
||||
|
||||
commits.commits=Коммиты
|
||||
commits.search=Поиск коммитов
|
||||
commits.find=Найти
|
||||
commits.author=Автор
|
||||
commits.message=Сообщение
|
||||
commits.date=Дата
|
||||
commits.older=Раньше
|
||||
commits.newer=Новее
|
||||
|
||||
settings=Настройки
|
||||
settings.options=Опции
|
||||
settings.collaboration=Сотрудничество
|
||||
settings.hooks=Автоматическое обновление
|
||||
settings.githooks=Git хуки
|
||||
settings.deploy_keys=Deploy Keys
|
||||
settings.basic_settings=Основные параметры
|
||||
settings.danger_zone=Опасная зона
|
||||
settings.site=Официальный сайт
|
||||
settings.update_settings=Обновить настройки
|
||||
settings.change_reponame=Имя репозитория изменено
|
||||
settings.change_reponame_desc=Имя хранилища изменено, вы хотите продолжить? Это действие повлияет на все ссылки, относящиеся к этому репозиторию.
|
||||
settings.transfer=Передать права собственности
|
||||
settings.transfer_desc=Transfer this repo to another user or to an organization where you have admin rights.
|
||||
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
|
||||
settings.delete=Удалить этот репозиторий
|
||||
settings.delete_desc=Как только вы удалите репозиторий — пути назад не будет. Удостоверьтесь, что вам это точно нужно.
|
||||
settings.transfer_notices=<p>- You will lose access if new owner is a individual user.</p><p>- You will remain access if new owner is an organization and you're one of the owners.</p>
|
||||
settings.update_settings_success=Настройка репозитория обновлена успешно.
|
||||
settings.transfer_owner=Новый владелец
|
||||
settings.make_transfer=Выполнить передачу
|
||||
settings.transfer_succeed=Repository ownership has been transferred successfully.
|
||||
settings.confirm_delete=Подтвердить удаление
|
||||
settings.add_collaborator=Добавить нового соавтора
|
||||
settings.add_collaborator_success=Был добавлен новый соавтор.
|
||||
settings.remove_collaborator_success=Соавтор был удален.
|
||||
settings.user_is_org_member=User is organization member who cannot be added as a collaborator.
|
||||
settings.add_webhook=Добавить Webhook
|
||||
settings.hooks_desc=Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="%s">Webhooks Guide</a>.
|
||||
settings.githooks_desc=Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations.
|
||||
settings.githook_edit_desc=If hook is not active, sample content will be presented. Leave content to be blank will disable this hook.
|
||||
settings.githook_name=Название Hook'a
|
||||
settings.githook_content=Перехватить содержание
|
||||
settings.update_githook=Обновить Hook
|
||||
settings.remove_hook_success=Webhook has been removed.
|
||||
settings.add_webhook_desc=We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="%s">Webhooks Guide</a>.
|
||||
settings.payload_url=Payload URL
|
||||
settings.content_type=Тип содержимого
|
||||
settings.secret=Secret
|
||||
settings.event_desc=Which events would you like to trigger this webhook?
|
||||
settings.event_push_only=Just the <code>push</code> event.
|
||||
settings.active=Активен
|
||||
settings.active_helper=We will deliver event details when this hook is triggered.
|
||||
settings.add_hook_success=New webhook has been added.
|
||||
settings.update_webhook=Update Webhook
|
||||
settings.update_hook_success=Webhook has been updated.
|
||||
settings.delete_webhook=Удалить автоматическое обновление
|
||||
settings.recent_deliveries=Recent Deliveries
|
||||
settings.hook_type=Тип перехватчика
|
||||
settings.add_slack_hook_desc=Add <a href="%s">Slack</a> integration to your repository.
|
||||
settings.slack_token=Token
|
||||
settings.slack_domain=Домен
|
||||
settings.slack_channel=Канал
|
||||
|
||||
diff.browse_source=Просмотр исходного кода
|
||||
diff.parent=Родитель
|
||||
diff.commit=Сommit
|
||||
diff.data_not_available=Данные Diff не доступны.
|
||||
diff.show_diff_stats=Show Diff Stats
|
||||
diff.stats_desc=<strong> %d changed files</strong> with <strong>%d additions</strong> and <strong>%d deletions</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Просмотреть файл
|
||||
|
||||
release.releases=Релизы
|
||||
release.new_release=Новый релиз
|
||||
release.draft=Черновик
|
||||
release.prerelease=Предрелиз
|
||||
release.stable=Стабильный
|
||||
release.edit=Редактировать
|
||||
release.ahead=<strong>%d</strong> commits to %s since this release
|
||||
release.source_code=Исходный код
|
||||
release.tag_name=Имя тега
|
||||
release.target=Цель
|
||||
release.tag_helper=Choose an existing tag, or create a new tag on publish.
|
||||
release.release_title=Название релиза
|
||||
release.content_with_md=Содержимое с <a href="%s">Markdown</a>
|
||||
release.write=Запись
|
||||
release.preview=Предварительный просмотр
|
||||
release.content_placeholder=Write some content
|
||||
release.loading=Загрузка...
|
||||
release.prerelease_desc=Это предварительный релиз
|
||||
release.prerelease_helper=We’ll point out that this release is identified as non-production ready.
|
||||
release.publish=Опубликовать релиз
|
||||
release.save_draft=Сохранить черновик
|
||||
release.edit_release=Редактировать релиз
|
||||
release.tag_name_already_exist=Релиз с этим именем тега уже существует.
|
||||
|
||||
[org]
|
||||
org_name_holder=Название организации
|
||||
org_name_helper=Лучшие названия организаций коротки и запоминаемы.
|
||||
org_email_helper=Organization's E-mail receives all notifications and confirmations.
|
||||
create_org=Создать Организацию
|
||||
repo_updated=Обновлено
|
||||
people=Люди
|
||||
invite_someone=Пригласить кого-нибудь
|
||||
teams=Команды
|
||||
lower_members=Участники
|
||||
lower_repositories=Репозитории
|
||||
create_new_team=Создать Новую Команду
|
||||
org_desc=Описание
|
||||
team_name=Название команды
|
||||
team_desc=Описание
|
||||
team_name_helper=You'll use this name to mention this team in conversations.
|
||||
team_desc_helper=What is this team all about?
|
||||
team_permission_desc=What permission level should this team have?
|
||||
|
||||
settings=Настройки
|
||||
settings.options=Опции
|
||||
settings.full_name=Полное имя
|
||||
settings.website=Сайт
|
||||
settings.location=Местоположение
|
||||
settings.update_settings=Обновить настройки
|
||||
settings.change_orgname=Имя Организации изменено
|
||||
settings.change_orgname_desc=Organization name has been changed, do you want to continue? This will affect all links relate to this organization.
|
||||
settings.update_setting_success=Organization setting has been updated successfully.
|
||||
settings.delete=Удалить Организацию
|
||||
settings.delete_account=Удалить Эту Организацию
|
||||
settings.delete_prompt=The operation will delete this organization permanently, and <strong>CANNOT</strong> be undone!
|
||||
settings.confirm_delete_account=Подтвердить удаление
|
||||
settings.delete_org_title=Удаление Организации
|
||||
settings.delete_org_desc=This organization is going to be deleted permanently, do you want to continue?
|
||||
settings.hooks_desc=Добавьте автоматическое обновление, который будет вызываться для <strong>всех репозиций</strong> под этой Группой.
|
||||
|
||||
members.public=Публичный
|
||||
members.public_helper=Сделать Приватным
|
||||
members.private=Приватный
|
||||
members.private_helper=Сделать Публичным
|
||||
members.owner=Владелец
|
||||
members.member=Участник
|
||||
members.conceal=Conceal
|
||||
members.remove=Удалить
|
||||
members.leave=Покинуть
|
||||
members.invite_desc=Начните вводить имя пользователя чтобы пригласить нового члена %s:
|
||||
members.invite_now=Пригласите сейчас
|
||||
|
||||
teams.join=Объединить
|
||||
teams.leave=Выйти
|
||||
teams.read_access=Доступ на чтение
|
||||
teams.read_access_helper=Эта команда будет иметь возможность просматривать и клонировать ее репозитории.
|
||||
teams.write_access=Доступ на запись
|
||||
teams.write_access_helper=Эта команда будет в состоянии прочитать ее репозитории, а также посылать изменения.
|
||||
teams.admin_access=Доступ администратора
|
||||
teams.admin_access_helper=This team will be able to push/pull to its repositories, as well as add other collaborators to them.
|
||||
teams.no_desc=Эта группа не имеет описания
|
||||
teams.settings=Настройки
|
||||
teams.owners_permission_desc=Владельцы имеют полный доступ ко <strong>всем репозиториям</strong> и имеют <strong>права администратора</strong> организации.
|
||||
teams.members=Члены группы разработки
|
||||
teams.update_settings=Обновить настройки
|
||||
teams.delete_team=Удалить эту группу разработки
|
||||
teams.add_team_member=Добавление члена группы разработки
|
||||
teams.delete_team_title=Удалить группу разработки
|
||||
teams.delete_team_desc=This team is going to be deleted, do you want to continue? Members of this team may lose access to some repositories.
|
||||
teams.delete_team_success=Given team has been deleted successfully.
|
||||
teams.read_permission_desc=This team grants <strong>Read</strong> access: members can view and clone the team's repositories.
|
||||
teams.write_permission_desc=This team grants <strong>Write</strong> access: members can read from and push to the team's repositories.
|
||||
teams.admin_permission_desc=This team grants <strong>Admin</strong> access: members can read from, push to, and add collaborators to the team's repositories.
|
||||
teams.repositories=Репозитории группы разработки
|
||||
teams.add_team_repository=Добавить репозиторий группы разработки
|
||||
teams.remove_repo=Удалить
|
||||
teams.add_nonexistent_repo=Вы добавляете в отсутствующий репозиторий, пожалуйста сначала его создайте.
|
||||
|
||||
[admin]
|
||||
dashboard=Панель управления
|
||||
users=Пользователи
|
||||
organizations=Организации
|
||||
repositories=Репозитории
|
||||
authentication=Авторизация
|
||||
config=Настройки
|
||||
notices=System Notices
|
||||
monitor=Мониторинг
|
||||
prev=Предыдущий.
|
||||
next=Следующий
|
||||
|
||||
dashboard.statistic=Статистика
|
||||
dashboard.operations=Операции
|
||||
dashboard.system_status=System Monitor Status
|
||||
dashboard.statistic_info=В базе данных Gogs записано <b>%d</b> пользователей, <b>%d</b> организаций, <b>%d</b> публичных ключей, <b>%d</b> репозиторий, <b>%d</b> подписок на репозитории, <b>%d</b> добавлений в избранное, <b>%d</b> действий, <b>%d</b> доступов, <b>%d</b> обсуждений, <b>%d</b> комментариев, <b>%d</b> социальных учетных записей, <b>%d</b> подписок на пользователей, <b>%d</b> зеркал, <b>%d</b> релизов, <b>%d</b> источников входа, <b>%d</b> веб-хуков, <b>%d</b> вех, <b>%d</b> меток, <b>%d</b> задач хуков, <b>%d</b> команд, <b>%d</b> задач по обновлению, <b>%d</b> присоединенных файлов.
|
||||
dashboard.operation_name=Operation Name
|
||||
dashboard.operation_switch=Переключить
|
||||
dashboard.operation_run=Запуск
|
||||
dashboard.clean_unbind_oauth=Clean unbound OAuthes
|
||||
dashboard.clean_unbind_oauth_success=All unbind OAuthes have been deleted successfully.
|
||||
dashboard.delete_inactivate_accounts=Удалить все неактивированные учетные записи
|
||||
dashboard.delete_inactivate_accounts_success=Все неактивированные учетные записи удалены успешно.
|
||||
dashboard.delete_repo_archives=Удаление всех архивов репозиториев
|
||||
dashboard.delete_repo_archives_success=Все архивы репозиториев были успешно удалены.
|
||||
dashboard.git_gc_repos=Выполнить сборку мусора на репозиториях
|
||||
dashboard.git_gc_repos_success=Сборка мусора на всех репозиториях успешно выполнена.
|
||||
dashboard.resync_all_sshkeys=Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost)
|
||||
dashboard.resync_all_sshkeys_success=All public keys have been rewritten successfully.
|
||||
dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
|
||||
dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
|
||||
|
||||
dashboard.server_uptime=Время непрерывной работы сервера
|
||||
dashboard.current_goroutine=Current Goroutines
|
||||
dashboard.current_memory_usage=Текущее использование памяти
|
||||
dashboard.total_memory_allocated=Всего памяти выделено
|
||||
dashboard.memory_obtained=Memory Obtained
|
||||
dashboard.pointer_lookup_times=Pointer Lookup Times
|
||||
dashboard.memory_allocate_times=Memory Allocate Times
|
||||
dashboard.memory_free_times=Memory Free Times
|
||||
dashboard.current_heap_usage=Current Heap Usage
|
||||
dashboard.heap_memory_obtained=Heap Memory Obtained
|
||||
dashboard.heap_memory_idle=Heap Memory Idle
|
||||
dashboard.heap_memory_in_use=Heap Memory In Use
|
||||
dashboard.heap_memory_released=Heap Memory Released
|
||||
dashboard.heap_objects=Heap Objects
|
||||
dashboard.bootstrap_stack_usage=Bootstrap Stack Usage
|
||||
dashboard.stack_memory_obtained=Stack Memory Obtained
|
||||
dashboard.mspan_structures_usage=MSpan Structures Usage
|
||||
dashboard.mspan_structures_obtained=MSpan Structures Obtained
|
||||
dashboard.mcache_structures_usage=MCache Structures Usage
|
||||
dashboard.mcache_structures_obtained=MCache Structures Obtained
|
||||
dashboard.profiling_bucket_hash_table_obtained=Profiling Bucket Hash Table Obtained
|
||||
dashboard.gc_metadata_obtained=GC Metadada Obtained
|
||||
dashboard.other_system_allocation_obtained=Other System Allocation Obtained
|
||||
dashboard.next_gc_recycle=Next GC Recycle
|
||||
dashboard.last_gc_time=Since Last GC Time
|
||||
dashboard.total_gc_time=Total GC Pause
|
||||
dashboard.total_gc_pause=Total GC Pause
|
||||
dashboard.last_gc_pause=Last GC Pause
|
||||
dashboard.gc_times=GC Times
|
||||
|
||||
users.user_manage_panel=User Manage Panel
|
||||
users.new_account=Создать новый аккаунт
|
||||
users.name=Имя
|
||||
users.activated=Активирован
|
||||
users.admin=Администратор
|
||||
users.repos=Репозитории
|
||||
users.created=Создано
|
||||
users.edit=Редактировать
|
||||
users.auth_source=Источник авторизации
|
||||
users.local=Локальный
|
||||
users.auth_login_name=Authorization Login Name
|
||||
users.update_profile_success=Профиль учетной записи обновлен успешно.
|
||||
users.edit_account=Изменение учетной записи
|
||||
users.is_activated=Эта учетная запись активирована
|
||||
users.is_admin=У этой учетной записи есть права администратора
|
||||
users.allow_git_hook=Пользователь имеет право создать Git перехватчик
|
||||
users.update_profile=Обновить профиль учетной записи
|
||||
users.delete_account=Удалить эту учетную запись
|
||||
users.still_own_repo=На вашем аккаунте все еще остается как минимум один репозиторий, сначала вам нужно удалить или передать его.
|
||||
users.still_has_org=This account still have membership of organization, you have to left or delete them first.
|
||||
|
||||
orgs.org_manage_panel=Управление группами
|
||||
orgs.name=Имя
|
||||
orgs.teams=Команды
|
||||
orgs.members=Участники
|
||||
|
||||
repos.repo_manage_panel=Repository Manage Panel
|
||||
repos.owner=Владелец
|
||||
repos.name=Имя
|
||||
repos.private=Приватный
|
||||
repos.watches=Следят
|
||||
repos.stars=В избранном
|
||||
repos.issues=Вопросы
|
||||
|
||||
auths.auth_manage_panel=Authorization Manage Panel
|
||||
auths.new=Add New Authorization Source
|
||||
auths.name=Имя
|
||||
auths.type=Тип
|
||||
auths.enabled=Включено
|
||||
auths.updated=Обновлено
|
||||
auths.auth_type=Тип авторизации
|
||||
auths.auth_name=Название авторизации
|
||||
auths.domain=Домен
|
||||
auths.host=Хост
|
||||
auths.port=Порт
|
||||
auths.base_dn=Base DN
|
||||
auths.attributes=Search Attributes
|
||||
auths.filter=Фильтр поиска
|
||||
auths.ms_ad_sa=Ms Ad SA
|
||||
auths.smtp_auth=Тип авторизации SMTP
|
||||
auths.smtphost=Узел SMTP
|
||||
auths.smtpport=SMTP-порт
|
||||
auths.enable_tls=Включение шифрования TLS
|
||||
auths.enable_auto_register=Включить автоматическую регистрацию
|
||||
auths.tips=Советы
|
||||
auths.edit=Редактировать параметры авторизации
|
||||
auths.activated=Эта аутентификация активирована
|
||||
auths.update_success=Настройка авторизации обновлена успешно.
|
||||
auths.update=Обновить параметры авторизации
|
||||
auths.delete=Удалить эту авторизацию
|
||||
auths.delete_auth_title=Удаление авторизации
|
||||
auths.delete_auth_desc=Эта авторизация будет удалена. Вы хотите продолжить?
|
||||
|
||||
config.server_config=Конфигурация сервера
|
||||
config.app_name=Имя приложения
|
||||
config.app_ver=Версия приложения
|
||||
config.app_url=URL приложения
|
||||
config.domain=Домен
|
||||
config.offline_mode=Автономный режим
|
||||
config.disable_router_log=Отключение журнала маршрутизатора
|
||||
config.run_user=Запуск пользователем
|
||||
config.run_mode=Режим выполнения
|
||||
config.repo_root_path=Repository Root Path
|
||||
config.static_file_root_path=Static File Root Path
|
||||
config.log_file_root_path=Log File Root Path
|
||||
config.script_type=Тип сценария
|
||||
config.reverse_auth_user=Reverse Authentication User
|
||||
config.db_config=Конфигурация базы данных
|
||||
config.db_type=Тип
|
||||
config.db_host=Хост
|
||||
config.db_name=Имя
|
||||
config.db_user=Пользователь
|
||||
config.db_ssl_mode=Режим SSL
|
||||
config.db_ssl_mode_helper=(только для «postgres»)
|
||||
config.db_path=Path
|
||||
config.db_path_helper=(for "sqlite3" only)
|
||||
config.service_config=Service Configuration
|
||||
config.register_email_confirm=Require E-mail Confirmation
|
||||
config.disable_register=Отключить регистрацию
|
||||
config.show_registration_button=Show Register Button
|
||||
config.require_sign_in_view=Для просмотра необходима авторизация
|
||||
config.mail_notify=Почтовые уведомления
|
||||
config.enable_cache_avatar=Кешировать аватар
|
||||
config.active_code_lives=Active Code Lives
|
||||
config.reset_password_code_lives=Reset Password Code Lives
|
||||
config.webhook_config=Настройка автоматического обновления репозиции
|
||||
config.task_interval=Интервал задания
|
||||
config.deliver_timeout=Задержка доставки
|
||||
config.skip_tls_verify=Skip TLS Verify
|
||||
config.mailer_config=Настройки почты
|
||||
config.mailer_enabled=Включено
|
||||
config.mailer_name=Имя
|
||||
config.mailer_host=Сервер
|
||||
config.mailer_user=Пользователь
|
||||
config.oauth_config=Конфигурация OAuth
|
||||
config.oauth_enabled=Включено
|
||||
config.cache_config=Настройки кеша
|
||||
config.cache_adapter=Cache Adapter
|
||||
config.cache_interval=Cache Interval
|
||||
config.cache_conn=Cache Connection
|
||||
config.session_config=Session Configuration
|
||||
config.session_provider=Session Provider
|
||||
config.provider_config=Provider Config
|
||||
config.cookie_name=Имя файла cookie
|
||||
config.enable_set_cookie=Enable Set Cookie
|
||||
config.gc_interval_time=GC Interval Time
|
||||
config.session_life_time=Время жизни сессии
|
||||
config.https_only=Только HTTPS
|
||||
config.cookie_life_time=Время жизни файла cookie
|
||||
config.picture_config=Настройка изображения
|
||||
config.picture_service=Picture Service
|
||||
config.disable_gravatar=Отключить Gravatar
|
||||
config.log_config=Конфигурация журнала
|
||||
config.log_mode=Режим журналирования
|
||||
|
||||
monitor.cron=Задачи cron
|
||||
monitor.name=Имя
|
||||
monitor.schedule=Расписание
|
||||
monitor.next=В следующий раз
|
||||
monitor.previous=Предыдущий раз
|
||||
monitor.execute_times=Execute Times
|
||||
monitor.process=Запущенные процессы
|
||||
monitor.desc=Описание
|
||||
monitor.start=Start Time
|
||||
monitor.execute_time=Время выполнения
|
||||
|
||||
notices.system_notice_list=Система уведомлений
|
||||
notices.type=Тип
|
||||
notices.type_1=Репозиторий
|
||||
notices.desc=Описание
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notice has been deleted successfully.
|
||||
|
||||
[action]
|
||||
create_repo=создан репозиторий <a href="%s/%s"> %s</a>
|
||||
commit_repo=pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a>
|
||||
create_issue=`opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
comment_issue=`commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
|
||||
transfer_repo=transfered repository <code>%s</code> to <a href="/%s%s">%s</a>
|
||||
push_tag=pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a>
|
||||
compare_2_commits=View comparison for these 2 commits
|
||||
|
||||
[tool]
|
||||
ago=ago
|
||||
from_now=from now
|
||||
now=сейчас
|
||||
1s=1 second %s
|
||||
1m=1 minute %s
|
||||
1h=1 hour %s
|
||||
1d=1 day %s
|
||||
1w=1 week %s
|
||||
1mon=1 month %s
|
||||
1y=1 year %s
|
||||
seconds=%d секунд %s
|
||||
minutes=%d минут %s
|
||||
hours=%d часов %s
|
||||
days=%d days %s
|
||||
weeks=%d weeks %s
|
||||
months=%d months %s
|
||||
years=%d years %s
|
||||
raw_seconds=seconds
|
||||
raw_minutes=minutes
|
||||
|
||||
1368
conf/locale/locale_zh-CN.ini
Normal file → Executable file
1368
conf/locale/locale_zh-CN.ini
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1366
conf/locale/locale_zh-HK.ini
Normal file → Executable file
1366
conf/locale/locale_zh-HK.ini
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@ The `config` file contains lines which will in the gogs docker container end up
|
||||
Here you can define things like the MySQL server for your database block.
|
||||
|
||||
The `fig` file will just be added to `fig.yml`, which is used by fig to manage your containers.
|
||||
This inculdes container linking!
|
||||
This includes container linking!
|
||||
|
||||
Just have a look at them and it will be clear how to write your own blocks.
|
||||
|
||||
@@ -53,7 +53,7 @@ Example:
|
||||
More sophisticated Example
|
||||
--------------------------
|
||||
|
||||
Her is a more elaborated example
|
||||
Here is a more elaborated example
|
||||
|
||||
```sh
|
||||
./assemble_blocks.sh docker_gogs w_db_cache_session option_db_postgresql option_cache_redis option_session_mysql
|
||||
@@ -86,4 +86,4 @@ This will pull in the `Dockerfile` from `docker_gogs` instead of the one from `d
|
||||
`Dockerfile`s for the `master` and `dev` branch are provided as `docker_gogs` and `docker_gogs_dev`
|
||||
|
||||
|
||||
[fig]:http://www.fig.sh/
|
||||
[fig]:http://www.fig.sh/
|
||||
|
||||
@@ -46,7 +46,7 @@ ENV HOME /home/git
|
||||
ENV USER git
|
||||
ENV PATH $GOGS_PATH:$PATH
|
||||
|
||||
RUN git config --global user.name "GoGS"
|
||||
RUN git config --global user.name "GoGS" && git config --global user.email "gogitservice@gmail.com"
|
||||
|
||||
ENTRYPOINT ["/tmp/init_gogs.sh"]
|
||||
CMD ["gogs", "web"]
|
||||
|
||||
@@ -47,7 +47,7 @@ ENV HOME /home/git
|
||||
ENV USER git
|
||||
ENV PATH $GOGS_PATH:$PATH
|
||||
|
||||
RUN git config --global user.name "GoGS"
|
||||
RUN git config --global user.name "GoGS" && git config --global user.email "gogitservice@gmail.com"
|
||||
|
||||
ENTRYPOINT ["/tmp/init_gogs.sh"]
|
||||
CMD ["gogs", "web"]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
[unix_http_server]
|
||||
file=/tmp/supervisor.sock ; path to your socket file
|
||||
file=log/supervisor.sock ; path to your socket file
|
||||
|
||||
[supervisord]
|
||||
logfile=log/supervisord.log ; supervisord log file
|
||||
logfile_maxbytes=50MB ; maximum size of logfile before rotation
|
||||
logfile_backups=10 ; number of backed up logfiles
|
||||
loglevel=warn ; info, debug, warn, trace
|
||||
pidfile=/tmp/supervisord.pid ; pidfile location
|
||||
pidfile=log/supervisord.pid ; pidfile location
|
||||
nodaemon=false ; run supervisord as a daemon
|
||||
minfds=1024 ; number of startup file descriptors
|
||||
minprocs=200 ; number of process descriptors
|
||||
@@ -17,10 +17,10 @@ childlogdir=log
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
|
||||
serverurl=unix://log/supervisor.sock ; use a unix:// URL for a unix socket
|
||||
|
||||
[program:gogs]
|
||||
command = /root/Developer/gopath/src/github.com/gogits/gogs/start.sh ; here must be the real url, not ~ or $GOROOT like
|
||||
command = gogs_start
|
||||
autostart = true
|
||||
stdout_logfile = log/supervisor-gogs-stderr.log
|
||||
stderr_logfile = log/supervisor-gogs-error.log
|
||||
stdout_logfile = log/supervisor-gogs-out.log
|
||||
stderr_logfile = log/supervisor-gogs-err.log
|
||||
|
||||
3
gogs.go
3
gogs.go
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const APP_VER = "0.5.5.1010 Beta"
|
||||
const APP_VER = "0.5.13.0212 Beta"
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
@@ -33,7 +33,6 @@ func main() {
|
||||
cmd.CmdWeb,
|
||||
cmd.CmdServ,
|
||||
cmd.CmdUpdate,
|
||||
cmd.CmdFix,
|
||||
cmd.CmdDump,
|
||||
cmd.CmdCert,
|
||||
}
|
||||
|
||||
135
models/action.go
135
models/action.go
@@ -41,12 +41,21 @@ var (
|
||||
|
||||
var (
|
||||
// Same as Github. See https://help.github.com/articles/closing-issues-via-commit-messages
|
||||
IssueKeywords = []string{"close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"}
|
||||
IssueKeywordsPat *regexp.Regexp
|
||||
IssueCloseKeywords = []string{"close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"}
|
||||
IssueReopenKeywords = []string{"reopen", "reopens", "reopened"}
|
||||
|
||||
IssueCloseKeywordsPat, IssueReopenKeywordsPat *regexp.Regexp
|
||||
IssueReferenceKeywordsPat *regexp.Regexp
|
||||
)
|
||||
|
||||
func assembleKeywordsPattern(words []string) string {
|
||||
return fmt.Sprintf(`(?i)(?:%s) \S+`, strings.Join(words, "|"))
|
||||
}
|
||||
|
||||
func init() {
|
||||
IssueKeywordsPat = regexp.MustCompile(fmt.Sprintf(`(?i)(?:%s) \S+`, strings.Join(IssueKeywords, "|")))
|
||||
IssueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(IssueCloseKeywords))
|
||||
IssueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(IssueReopenKeywords))
|
||||
IssueReferenceKeywordsPat = regexp.MustCompile(`(?i)(?:)(^| )\S+`)
|
||||
}
|
||||
|
||||
// Action represents user operation type and other information to repository.,
|
||||
@@ -58,6 +67,7 @@ type Action struct {
|
||||
ActUserId int64 // Action user id.
|
||||
ActUserName string // Action user name.
|
||||
ActEmail string
|
||||
ActAvatar string `xorm:"-"`
|
||||
RepoId int64
|
||||
RepoUserName string
|
||||
RepoName string
|
||||
@@ -88,7 +98,7 @@ func (a Action) GetRepoName() string {
|
||||
}
|
||||
|
||||
func (a Action) GetRepoLink() string {
|
||||
return path.Join(a.RepoUserName, a.RepoName)
|
||||
return path.Join(setting.AppSubUrl, a.RepoUserName, a.RepoName)
|
||||
}
|
||||
|
||||
func (a Action) GetBranch() string {
|
||||
@@ -109,9 +119,39 @@ func (a Action) GetIssueInfos() []string {
|
||||
|
||||
func updateIssuesCommit(userId, repoId int64, repoUserName, repoName string, commits []*base.PushCommit) error {
|
||||
for _, c := range commits {
|
||||
refs := IssueKeywordsPat.FindAllString(c.Message, -1)
|
||||
for _, ref := range IssueReferenceKeywordsPat.FindAllString(c.Message, -1) {
|
||||
ref := ref[strings.IndexByte(ref, byte(' '))+1:]
|
||||
ref = strings.TrimRightFunc(ref, func(c rune) bool {
|
||||
return !unicode.IsDigit(c)
|
||||
})
|
||||
|
||||
for _, ref := range refs {
|
||||
if len(ref) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add repo name if missing
|
||||
if ref[0] == '#' {
|
||||
ref = fmt.Sprintf("%s/%s%s", repoUserName, repoName, ref)
|
||||
} else if strings.Contains(ref, "/") == false {
|
||||
// FIXME: We don't support User#ID syntax yet
|
||||
// return ErrNotImplemented
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
issue, err := GetIssueByRef(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/%s/commit/%s", setting.AppSubUrl, repoUserName, repoName, c.Sha1)
|
||||
message := fmt.Sprintf(`<a href="%s">%s</a>`, url, c.Message)
|
||||
if _, err = CreateComment(userId, issue.RepoId, issue.Id, 0, 0, COMMENT_TYPE_COMMIT, message, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, ref := range IssueCloseKeywordsPat.FindAllString(c.Message, -1) {
|
||||
ref := ref[strings.IndexByte(ref, byte(' '))+1:]
|
||||
ref = strings.TrimRightFunc(ref, func(c rune) bool {
|
||||
return !unicode.IsDigit(c)
|
||||
@@ -132,27 +172,20 @@ func updateIssuesCommit(userId, repoId int64, repoUserName, repoName string, com
|
||||
}
|
||||
|
||||
issue, err := GetIssueByRef(ref)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/%s/commit/%s", setting.AppSubUrl, repoUserName, repoName, c.Sha1)
|
||||
message := fmt.Sprintf(`<a href="%s">%s</a>`, url, c.Message)
|
||||
|
||||
if _, err = CreateComment(userId, issue.RepoId, issue.Id, 0, 0, COMMIT, message, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if issue.RepoId == repoId {
|
||||
if issue.IsClosed {
|
||||
continue
|
||||
}
|
||||
|
||||
issue.IsClosed = true
|
||||
|
||||
if err = UpdateIssue(issue); err != nil {
|
||||
return err
|
||||
} else if err = UpdateIssueUserPairsByStatus(issue.Id, issue.IsClosed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ChangeMilestoneIssueStats(issue); err != nil {
|
||||
@@ -160,13 +193,60 @@ func updateIssuesCommit(userId, repoId int64, repoUserName, repoName string, com
|
||||
}
|
||||
|
||||
// If commit happened in the referenced repository, it means the issue can be closed.
|
||||
if _, err = CreateComment(userId, repoId, issue.Id, 0, 0, CLOSE, "", nil); err != nil {
|
||||
if _, err = CreateComment(userId, repoId, issue.Id, 0, 0, COMMENT_TYPE_CLOSE, "", nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, ref := range IssueReopenKeywordsPat.FindAllString(c.Message, -1) {
|
||||
ref := ref[strings.IndexByte(ref, byte(' '))+1:]
|
||||
ref = strings.TrimRightFunc(ref, func(c rune) bool {
|
||||
return !unicode.IsDigit(c)
|
||||
})
|
||||
|
||||
if len(ref) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add repo name if missing
|
||||
if ref[0] == '#' {
|
||||
ref = fmt.Sprintf("%s/%s%s", repoUserName, repoName, ref)
|
||||
} else if strings.Contains(ref, "/") == false {
|
||||
// We don't support User#ID syntax yet
|
||||
// return ErrNotImplemented
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
issue, err := GetIssueByRef(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if issue.RepoId == repoId {
|
||||
if !issue.IsClosed {
|
||||
continue
|
||||
}
|
||||
issue.IsClosed = false
|
||||
|
||||
if err = UpdateIssue(issue); err != nil {
|
||||
return err
|
||||
} else if err = UpdateIssueUserPairsByStatus(issue.Id, issue.IsClosed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ChangeMilestoneIssueStats(issue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If commit happened in the referenced repository, it means the issue can be closed.
|
||||
if _, err = CreateComment(userId, repoId, issue.Id, 0, 0, COMMENT_TYPE_REOPEN, "", nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -181,13 +261,19 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
|
||||
commit = &base.PushCommits{}
|
||||
}
|
||||
|
||||
refName := git.RefEndName(refFullName)
|
||||
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
|
||||
// if not the first commit, set the compareUrl
|
||||
if !strings.HasPrefix(oldCommitId, "0000000") {
|
||||
commit.CompareUrl = fmt.Sprintf("%s/compare/%s...%s", repoLink, oldCommitId, newCommitId)
|
||||
}
|
||||
|
||||
bs, err := json.Marshal(commit)
|
||||
if err != nil {
|
||||
return errors.New("action.CommitRepoAction(json): " + err.Error())
|
||||
}
|
||||
|
||||
refName := git.RefEndName(refFullName)
|
||||
|
||||
// Change repository bare status and update last updated time.
|
||||
repo, err := GetRepositoryByName(repoUserId, repoName)
|
||||
if err != nil {
|
||||
@@ -211,7 +297,6 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
|
||||
return errors.New("action.CommitRepoAction(NotifyWatchers): " + err.Error())
|
||||
|
||||
}
|
||||
//qlog.Info("action.CommitRepoAction(end): %d/%s", repoUserId, repoName)
|
||||
|
||||
// New push event hook.
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
@@ -237,13 +322,6 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
|
||||
return nil
|
||||
}
|
||||
|
||||
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
|
||||
compareUrl := ""
|
||||
// if not the first commit, set the compareUrl
|
||||
if !strings.HasPrefix(oldCommitId, "0000000") {
|
||||
compareUrl = fmt.Sprintf("%s/compare/%s...%s", repoLink, oldCommitId, newCommitId)
|
||||
}
|
||||
|
||||
pusher_email, pusher_name := "", ""
|
||||
pusher, err := GetUserByName(userName)
|
||||
if err == nil {
|
||||
@@ -293,7 +371,7 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
|
||||
},
|
||||
Before: oldCommitId,
|
||||
After: newCommitId,
|
||||
CompareUrl: compareUrl,
|
||||
CompareUrl: commit.CompareUrl,
|
||||
}
|
||||
|
||||
for _, w := range ws {
|
||||
@@ -331,7 +409,6 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
|
||||
}
|
||||
}
|
||||
|
||||
go DeliverHooks()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -348,7 +425,7 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// TransferRepoAction adds new action for transfering repository.
|
||||
// TransferRepoAction adds new action for transferring repository.
|
||||
func TransferRepoAction(u, newUser *User, repo *Repository) (err error) {
|
||||
action := &Action{
|
||||
ActUserId: u.Id,
|
||||
|
||||
@@ -6,6 +6,7 @@ package models
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -13,8 +14,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/html/charset"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/process"
|
||||
@@ -55,6 +60,8 @@ type DiffFile struct {
|
||||
Index int
|
||||
Addition, Deletion int
|
||||
Type int
|
||||
IsCreated bool
|
||||
IsDeleted bool
|
||||
IsBin bool
|
||||
Sections []*DiffSection
|
||||
}
|
||||
@@ -80,6 +87,8 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||
|
||||
leftLine, rightLine int
|
||||
isTooLong bool
|
||||
// FIXME: use first 30 lines to detect file encoding. Should use cache in the future.
|
||||
buf bytes.Buffer
|
||||
)
|
||||
|
||||
diff := &Diff{Files: make([]*DiffFile, 0)}
|
||||
@@ -97,6 +106,11 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||
|
||||
i = i + 1
|
||||
|
||||
// FIXME: use first 30 lines to detect file encoding.
|
||||
if i <= 30 {
|
||||
buf.WriteString(line)
|
||||
}
|
||||
|
||||
// Diff data too large, we only show the first about maxlines lines
|
||||
if i == maxlines {
|
||||
isTooLong = true
|
||||
@@ -169,10 +183,16 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||
switch {
|
||||
case strings.HasPrefix(scanner.Text(), "new file"):
|
||||
curFile.Type = DIFF_FILE_ADD
|
||||
curFile.IsDeleted = false
|
||||
curFile.IsCreated = true
|
||||
case strings.HasPrefix(scanner.Text(), "deleted"):
|
||||
curFile.Type = DIFF_FILE_DEL
|
||||
curFile.IsCreated = false
|
||||
curFile.IsDeleted = true
|
||||
case strings.HasPrefix(scanner.Text(), "index"):
|
||||
curFile.Type = DIFF_FILE_CHANGE
|
||||
curFile.IsCreated = false
|
||||
curFile.IsDeleted = false
|
||||
}
|
||||
if curFile.Type > 0 {
|
||||
break
|
||||
@@ -181,6 +201,25 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: use first 30 lines to detect file encoding.
|
||||
charsetLabel, err := base.DetectEncoding(buf.Bytes())
|
||||
if charsetLabel != "utf8" && err == nil {
|
||||
encoding, _ := charset.Lookup(charsetLabel)
|
||||
|
||||
if encoding != nil {
|
||||
d := encoding.NewDecoder()
|
||||
for _, f := range diff.Files {
|
||||
for _, sec := range f.Sections {
|
||||
for _, l := range sec.Lines {
|
||||
if c, _, err := transform.String(d, l.Content); err == nil {
|
||||
l.Content = c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,10 @@ func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labelIds, sort
|
||||
|
||||
if len(labelIds) > 0 {
|
||||
for _, label := range strings.Split(labelIds, ",") {
|
||||
sess.And("label_ids like '%$" + label + "|%'")
|
||||
// Prevent SQL inject.
|
||||
if com.StrTo(label).MustInt() > 0 {
|
||||
sess.And("label_ids like '%$" + label + "|%'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,8 +472,8 @@ func UpdateIssueUserPairByAssignee(aid, iid int64) error {
|
||||
if aid == 0 {
|
||||
return nil
|
||||
}
|
||||
rawSql = "UPDATE `issue_user` SET is_assigned = true WHERE uid = ? AND issue_id = ?"
|
||||
_, err := x.Exec(rawSql, aid, iid)
|
||||
rawSql = "UPDATE `issue_user` SET is_assigned = ? WHERE uid = ? AND issue_id = ?"
|
||||
_, err := x.Exec(rawSql, true, aid, iid)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -856,22 +859,16 @@ type CommentType int
|
||||
|
||||
const (
|
||||
// Plain comment, can be associated with a commit (CommitId > 0) and a line (Line > 0)
|
||||
COMMENT CommentType = iota
|
||||
|
||||
// Reopen action
|
||||
REOPEN
|
||||
|
||||
// Close action
|
||||
CLOSE
|
||||
|
||||
// Reference from another issue
|
||||
ISSUE
|
||||
COMMENT_TYPE_COMMENT CommentType = iota
|
||||
COMMENT_TYPE_REOPEN
|
||||
COMMENT_TYPE_CLOSE
|
||||
|
||||
// References.
|
||||
COMMENT_TYPE_ISSUE
|
||||
// Reference from some commit (not part of a pull request)
|
||||
COMMIT
|
||||
|
||||
COMMENT_TYPE_COMMIT
|
||||
// Reference from some pull request
|
||||
PULL
|
||||
COMMENT_TYPE_PULL
|
||||
)
|
||||
|
||||
// Comment represents a comment in commit and issue page.
|
||||
@@ -905,7 +902,7 @@ func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType Commen
|
||||
|
||||
// Check comment type.
|
||||
switch cmtType {
|
||||
case COMMENT:
|
||||
case COMMENT_TYPE_COMMENT:
|
||||
rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?"
|
||||
if _, err := sess.Exec(rawSql, issueId); err != nil {
|
||||
sess.Rollback()
|
||||
@@ -926,13 +923,13 @@ func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType Commen
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
case REOPEN:
|
||||
case COMMENT_TYPE_REOPEN:
|
||||
rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues - 1 WHERE id = ?"
|
||||
if _, err := sess.Exec(rawSql, repoId); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
case CLOSE:
|
||||
case COMMENT_TYPE_CLOSE:
|
||||
rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues + 1 WHERE id = ?"
|
||||
if _, err := sess.Exec(rawSql, repoId); err != nil {
|
||||
sess.Rollback()
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/gogits/gogs/modules/auth/ldap"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/uuid"
|
||||
)
|
||||
|
||||
type LoginType int
|
||||
@@ -40,7 +41,7 @@ var LoginTypes = map[LoginType]string{
|
||||
SMTP: "SMTP",
|
||||
}
|
||||
|
||||
// Ensure structs implmented interface.
|
||||
// Ensure structs implemented interface.
|
||||
var (
|
||||
_ core.Conversion = &LDAPConfig{}
|
||||
_ core.Conversion = &SMTPConfig{}
|
||||
@@ -149,7 +150,7 @@ func DelLoginSource(source *LoginSource) error {
|
||||
|
||||
// UserSignIn validates user name and password.
|
||||
func UserSignIn(uname, passwd string) (*User, error) {
|
||||
var u *User
|
||||
u := new(User)
|
||||
if strings.Contains(uname, "@") {
|
||||
u = &User{Email: uname}
|
||||
} else {
|
||||
@@ -225,33 +226,35 @@ func UserSignIn(uname, passwd string) (*User, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Query if name/passwd can login against the LDAP direcotry pool
|
||||
// Query if name/passwd can login against the LDAP directory pool
|
||||
// Create a local user if success
|
||||
// Return the same LoginUserPlain semantic
|
||||
// FIXME: https://github.com/gogits/gogs/issues/672
|
||||
func LoginUserLdapSource(u *User, name, passwd string, sourceId int64, cfg *LDAPConfig, autoRegister bool) (*User, error) {
|
||||
mail, logged := cfg.Ldapsource.SearchEntry(name, passwd)
|
||||
if !logged {
|
||||
// user not in LDAP, do nothing
|
||||
// User not in LDAP, do nothing
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
if !autoRegister {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// fake a local user creation
|
||||
// Fallback.
|
||||
if len(mail) == 0 {
|
||||
mail = uuid.NewV4().String() + "@localhost"
|
||||
}
|
||||
|
||||
u = &User{
|
||||
LowerName: strings.ToLower(name),
|
||||
Name: strings.ToLower(name),
|
||||
Name: name,
|
||||
LoginType: LDAP,
|
||||
LoginSource: sourceId,
|
||||
LoginName: name,
|
||||
IsActive: true,
|
||||
Passwd: passwd,
|
||||
Email: mail,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
err := CreateUser(u)
|
||||
return u, err
|
||||
return u, CreateUser(u)
|
||||
}
|
||||
|
||||
type loginAuth struct {
|
||||
@@ -315,7 +318,7 @@ func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error {
|
||||
return ErrUnsupportedLoginType
|
||||
}
|
||||
|
||||
// Query if name/passwd can login against the LDAP direcotry pool
|
||||
// Query if name/passwd can login against the LDAP directory pool
|
||||
// Create a local user if success
|
||||
// Return the same LoginUserPlain semantic
|
||||
func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
|
||||
|
||||
53
models/migrations/migrations.go
Normal file
53
models/migrations/migrations.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
type migration func(*xorm.Engine) error
|
||||
|
||||
// The version table. Should have only one row with id==1
|
||||
type Version struct {
|
||||
Id int64
|
||||
Version int64
|
||||
}
|
||||
|
||||
// This is a sequence of migrations. Add new migrations to the bottom of the list.
|
||||
// If you want to "retire" a migration, replace it with "expiredMigration"
|
||||
var migrations = []migration{}
|
||||
|
||||
// Migrate database to current version
|
||||
func Migrate(x *xorm.Engine) error {
|
||||
if err := x.Sync(new(Version)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentVersion := &Version{Id: 1}
|
||||
has, err := x.Get(currentVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
if _, err = x.InsertOne(currentVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v := currentVersion.Version
|
||||
|
||||
for i, migration := range migrations[v:] {
|
||||
if err = migration(x); err != nil {
|
||||
return err
|
||||
}
|
||||
currentVersion.Version = v + int64(i) + 1
|
||||
if _, err = x.Id(1).Update(currentVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func expiredMigration(x *xorm.Engine) error {
|
||||
return errors.New("You are migrating from a too old gogs version")
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
@@ -14,17 +15,27 @@ import (
|
||||
"github.com/go-xorm/xorm"
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
// "github.com/gogits/gogs/models/migrations"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
x *xorm.Engine
|
||||
tables []interface{}
|
||||
// Engine represents a xorm engine or session.
|
||||
type Engine interface {
|
||||
Delete(interface{}) (int64, error)
|
||||
Exec(string, ...interface{}) (sql.Result, error)
|
||||
Get(interface{}) (bool, error)
|
||||
Insert(...interface{}) (int64, error)
|
||||
Id(interface{}) *xorm.Session
|
||||
Where(string, ...interface{}) *xorm.Session
|
||||
}
|
||||
|
||||
var (
|
||||
x *xorm.Engine
|
||||
tables []interface{}
|
||||
HasEngine bool
|
||||
|
||||
DbCfg struct {
|
||||
Type, Host, Name, User, Pwd, Path, SslMode string
|
||||
Type, Host, Name, User, Passwd, Path, SSLMode string
|
||||
}
|
||||
|
||||
EnableSQLite3 bool
|
||||
@@ -32,27 +43,29 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
tables = append(tables, new(User), new(PublicKey), new(Follow), new(Oauth2),
|
||||
tables = append(tables,
|
||||
new(User), new(PublicKey), new(Follow), new(Oauth2), new(AccessToken),
|
||||
new(Repository), new(Watch), new(Star), new(Action), new(Access),
|
||||
new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
|
||||
new(Mirror), new(Release), new(LoginSource), new(Webhook),
|
||||
new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
|
||||
new(Notice))
|
||||
new(Notice), new(EmailAddress))
|
||||
}
|
||||
|
||||
func LoadModelsConfig() {
|
||||
DbCfg.Type = setting.Cfg.MustValue("database", "DB_TYPE")
|
||||
sec := setting.Cfg.Section("database")
|
||||
DbCfg.Type = sec.Key("DB_TYPE").String()
|
||||
if DbCfg.Type == "sqlite3" {
|
||||
UseSQLite3 = true
|
||||
}
|
||||
DbCfg.Host = setting.Cfg.MustValue("database", "HOST")
|
||||
DbCfg.Name = setting.Cfg.MustValue("database", "NAME")
|
||||
DbCfg.User = setting.Cfg.MustValue("database", "USER")
|
||||
if len(DbCfg.Pwd) == 0 {
|
||||
DbCfg.Pwd = setting.Cfg.MustValue("database", "PASSWD")
|
||||
DbCfg.Host = sec.Key("HOST").String()
|
||||
DbCfg.Name = sec.Key("NAME").String()
|
||||
DbCfg.User = sec.Key("USER").String()
|
||||
if len(DbCfg.Passwd) == 0 {
|
||||
DbCfg.Passwd = sec.Key("PASSWD").String()
|
||||
}
|
||||
DbCfg.SslMode = setting.Cfg.MustValue("database", "SSL_MODE")
|
||||
DbCfg.Path = setting.Cfg.MustValue("database", "PATH", "data/gogs.db")
|
||||
DbCfg.SSLMode = sec.Key("SSL_MODE").String()
|
||||
DbCfg.Path = sec.Key("PATH").MustString("data/gogs.db")
|
||||
}
|
||||
|
||||
func getEngine() (*xorm.Engine, error) {
|
||||
@@ -60,7 +73,7 @@ func getEngine() (*xorm.Engine, error) {
|
||||
switch DbCfg.Type {
|
||||
case "mysql":
|
||||
cnnstr = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
|
||||
DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)
|
||||
DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name)
|
||||
case "postgres":
|
||||
var host, port = "127.0.0.1", "5432"
|
||||
fields := strings.Split(DbCfg.Host, ":")
|
||||
@@ -71,7 +84,7 @@ func getEngine() (*xorm.Engine, error) {
|
||||
port = fields[1]
|
||||
}
|
||||
cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
|
||||
DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode)
|
||||
DbCfg.User, DbCfg.Passwd, host, port, DbCfg.Name, DbCfg.SSLMode)
|
||||
case "sqlite3":
|
||||
if !EnableSQLite3 {
|
||||
return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type)
|
||||
@@ -87,7 +100,7 @@ func getEngine() (*xorm.Engine, error) {
|
||||
func NewTestEngine(x *xorm.Engine) (err error) {
|
||||
x, err = getEngine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("models.init(fail to connect to database): %v", err)
|
||||
return fmt.Errorf("connect to database: %v", err)
|
||||
}
|
||||
|
||||
return x.Sync(tables...)
|
||||
@@ -96,10 +109,10 @@ func NewTestEngine(x *xorm.Engine) (err error) {
|
||||
func SetEngine() (err error) {
|
||||
x, err = getEngine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("models.init(fail to connect to database): %v", err)
|
||||
return fmt.Errorf("connect to database: %v", err)
|
||||
}
|
||||
|
||||
// WARNNING: for serv command, MUST remove the output to os.stdout,
|
||||
// WARNING: for serv command, MUST remove the output to os.stdout,
|
||||
// so use log file to instead print to stdout.
|
||||
logPath := path.Join(setting.LogRootPath, "xorm.log")
|
||||
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
||||
@@ -122,7 +135,12 @@ func NewEngine() (err error) {
|
||||
if err = SetEngine(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = x.Sync2(tables...); err != nil {
|
||||
|
||||
// if err = migrations.Migrate(x); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
|
||||
return fmt.Errorf("sync database struct error: %v\n", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -79,7 +79,7 @@ func UpdateOauth2(oa *Oauth2) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// GetOauthByUserId returns list of oauthes that are releated to given user.
|
||||
// GetOauthByUserId returns list of oauthes that are related to given user.
|
||||
func GetOauthByUserId(uid int64) ([]*Oauth2, error) {
|
||||
socials := make([]*Oauth2, 0, 5)
|
||||
err := x.Find(&socials, Oauth2{Uid: uid})
|
||||
|
||||
148
models/org.go
148
models/org.go
@@ -12,7 +12,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
)
|
||||
@@ -25,8 +24,8 @@ var (
|
||||
ErrLastOrgOwner = errors.New("The user to remove is the last member in owner team")
|
||||
)
|
||||
|
||||
// IsOrgOwner returns true if given user is in the owner team.
|
||||
func (org *User) IsOrgOwner(uid int64) bool {
|
||||
// IsOwnedBy returns true if given user is in the owner team.
|
||||
func (org *User) IsOwnedBy(uid int64) bool {
|
||||
return IsOrganizationOwner(org.Id, uid)
|
||||
}
|
||||
|
||||
@@ -77,6 +76,17 @@ func (org *User) RemoveMember(uid int64) error {
|
||||
return RemoveOrgUser(org.Id, uid)
|
||||
}
|
||||
|
||||
// IsOrgEmailUsed returns true if the e-mail has been used in organization account.
|
||||
func IsOrgEmailUsed(email string) (bool, error) {
|
||||
if len(email) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
return x.Get(&User{
|
||||
Email: email,
|
||||
Type: ORGANIZATION,
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOrganization creates record of a new organization.
|
||||
func CreateOrganization(org, owner *User) (*User, error) {
|
||||
if !IsLegalName(org.Name) {
|
||||
@@ -90,7 +100,7 @@ func CreateOrganization(org, owner *User) (*User, error) {
|
||||
return nil, ErrUserAlreadyExist
|
||||
}
|
||||
|
||||
isExist, err = IsEmailUsed(org.Email)
|
||||
isExist, err = IsOrgEmailUsed(org.Email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if isExist {
|
||||
@@ -159,6 +169,24 @@ func CreateOrganization(org, owner *User) (*User, error) {
|
||||
return org, sess.Commit()
|
||||
}
|
||||
|
||||
// GetOrgByName returns organization by given name.
|
||||
func GetOrgByName(name string) (*User, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, ErrOrgNotExist
|
||||
}
|
||||
u := &User{
|
||||
LowerName: strings.ToLower(name),
|
||||
Type: ORGANIZATION,
|
||||
}
|
||||
has, err := x.Get(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrOrgNotExist
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// CountOrganizations returns number of organizations.
|
||||
func CountOrganizations() int64 {
|
||||
count, _ := x.Where("type=1").Count(new(User))
|
||||
@@ -229,7 +257,7 @@ func IsOrganizationMember(orgId, uid int64) bool {
|
||||
return has
|
||||
}
|
||||
|
||||
// IsPublicMembership returns ture if given user public his/her membership.
|
||||
// IsPublicMembership returns true if given user public his/her membership.
|
||||
func IsPublicMembership(orgId, uid int64) bool {
|
||||
has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("is_public=?", true).Get(new(OrgUser))
|
||||
return has
|
||||
@@ -362,7 +390,7 @@ func RemoveOrgUser(orgId, uid int64) error {
|
||||
return err
|
||||
}
|
||||
for _, t := range ts {
|
||||
if err = removeTeamMemberWithSess(org.Id, t.Id, u.Id, sess); err != nil {
|
||||
if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -457,18 +485,18 @@ func (t *Team) RemoveMember(uid int64) error {
|
||||
}
|
||||
|
||||
// addAccessWithAuthorize inserts or updates access with given mode.
|
||||
func addAccessWithAuthorize(sess *xorm.Session, access *Access, mode AccessType) error {
|
||||
has, err := x.Get(access)
|
||||
func addAccessWithAuthorize(e Engine, access *Access, mode AccessType) error {
|
||||
has, err := e.Get(access)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to get access: %v", err)
|
||||
}
|
||||
access.Mode = mode
|
||||
if has {
|
||||
if _, err = sess.Id(access.Id).Update(access); err != nil {
|
||||
if _, err = e.Id(access.Id).Update(access); err != nil {
|
||||
return fmt.Errorf("fail to update access: %v", err)
|
||||
}
|
||||
} else {
|
||||
if _, err = sess.Insert(access); err != nil {
|
||||
if _, err = e.Insert(access); err != nil {
|
||||
return fmt.Errorf("fail to insert access: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -507,7 +535,7 @@ func (t *Team) AddRepository(repo *Repository) (err error) {
|
||||
mode := AuthorizeToAccessType(t.Authorize)
|
||||
|
||||
for _, u := range t.Members {
|
||||
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
|
||||
auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, t.Id)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
@@ -523,7 +551,7 @@ func (t *Team) AddRepository(repo *Repository) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = WatchRepo(u.Id, repo.Id, true); err != nil {
|
||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
@@ -564,7 +592,7 @@ func (t *Team) RemoveRepository(repoId int64) error {
|
||||
|
||||
// Remove access to team members.
|
||||
for _, u := range t.Members {
|
||||
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
|
||||
auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, t.Id)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
@@ -578,7 +606,7 @@ func (t *Team) RemoveRepository(repoId int64) error {
|
||||
if _, err = sess.Delete(access); err != nil {
|
||||
sess.Rollback()
|
||||
return fmt.Errorf("fail to delete access: %v", err)
|
||||
} else if err = WatchRepo(u.Id, repo.Id, false); err != nil {
|
||||
} else if err = watchRepo(sess, u.Id, repo.Id, false); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
@@ -649,10 +677,9 @@ func GetTeam(orgId int64, name string) (*Team, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// GetTeamById returns team by given ID.
|
||||
func GetTeamById(teamId int64) (*Team, error) {
|
||||
func getTeamById(e Engine, teamId int64) (*Team, error) {
|
||||
t := new(Team)
|
||||
has, err := x.Id(teamId).Get(t)
|
||||
has, err := e.Id(teamId).Get(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@@ -661,9 +688,13 @@ func GetTeamById(teamId int64) (*Team, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// GetHighestAuthorize returns highest repository authorize level for given user and team.
|
||||
func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) {
|
||||
ts, err := GetUserTeams(orgId, uid)
|
||||
// GetTeamById returns team by given ID.
|
||||
func GetTeamById(teamId int64) (*Team, error) {
|
||||
return getTeamById(x, teamId)
|
||||
}
|
||||
|
||||
func getHighestAuthorize(e Engine, orgId, uid, repoId, teamId int64) (AuthorizeType, error) {
|
||||
ts, err := getUserTeams(e, orgId, uid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -685,6 +716,11 @@ func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
// GetHighestAuthorize returns highest repository authorize level for given user and team.
|
||||
func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) {
|
||||
return getHighestAuthorize(x, orgId, uid, repoId, teamId)
|
||||
}
|
||||
|
||||
// UpdateTeam updates information of team.
|
||||
func UpdateTeam(t *Team, authChanged bool) (err error) {
|
||||
if !IsLegalName(t.Name) {
|
||||
@@ -837,41 +873,33 @@ type TeamUser struct {
|
||||
TeamId int64
|
||||
}
|
||||
|
||||
func isTeamMember(e Engine, orgId, teamId, uid int64) bool {
|
||||
has, _ := e.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser))
|
||||
return has
|
||||
}
|
||||
|
||||
// IsTeamMember returns true if given user is a member of team.
|
||||
func IsTeamMember(orgId, teamId, uid int64) bool {
|
||||
has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser))
|
||||
return has
|
||||
return isTeamMember(x, orgId, teamId, uid)
|
||||
}
|
||||
|
||||
// GetTeamMembers returns all members in given team of organization.
|
||||
func GetTeamMembers(orgId, teamId int64) ([]*User, error) {
|
||||
tus := make([]*TeamUser, 0, 10)
|
||||
err := x.Where("org_id=?", orgId).And("team_id=?", teamId).Find(&tus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
us := make([]*User, len(tus))
|
||||
for i, tu := range tus {
|
||||
us[i], err = GetUserById(tu.Uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return us, nil
|
||||
us := make([]*User, 0, 10)
|
||||
err := x.Sql("SELECT * FROM `user` JOIN `team_user` ON `team_user`.`team_id` = ? AND `team_user`.`uid` = `user`.`id`", teamId).Find(&us)
|
||||
return us, err
|
||||
}
|
||||
|
||||
// GetUserTeams returns all teams that user belongs to in given origanization.
|
||||
func GetUserTeams(orgId, uid int64) ([]*Team, error) {
|
||||
func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) {
|
||||
tus := make([]*TeamUser, 0, 5)
|
||||
if err := x.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil {
|
||||
if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ts := make([]*Team, len(tus))
|
||||
for i, tu := range tus {
|
||||
t := new(Team)
|
||||
has, err := x.Id(tu.TeamId).Get(t)
|
||||
has, err := e.Id(tu.TeamId).Get(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@@ -882,6 +910,11 @@ func GetUserTeams(orgId, uid int64) ([]*Team, error) {
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
// GetUserTeams returns all teams that user belongs to in given organization.
|
||||
func GetUserTeams(orgId, uid int64) ([]*Team, error) {
|
||||
return getUserTeams(x, orgId, uid)
|
||||
}
|
||||
|
||||
// AddTeamMember adds new member to given team of given organization.
|
||||
func AddTeamMember(orgId, teamId, uid int64) error {
|
||||
if IsTeamMember(orgId, teamId, uid) {
|
||||
@@ -938,7 +971,7 @@ func AddTeamMember(orgId, teamId, uid int64) error {
|
||||
// Give access to team repositories.
|
||||
mode := AuthorizeToAccessType(t.Authorize)
|
||||
for _, repo := range t.Repos {
|
||||
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId)
|
||||
auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, teamId)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
@@ -975,13 +1008,13 @@ func AddTeamMember(orgId, teamId, uid int64) error {
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) error {
|
||||
if !IsTeamMember(orgId, teamId, uid) {
|
||||
func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
|
||||
if !isTeamMember(e, orgId, teamId, uid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get team and its repositories.
|
||||
t, err := GetTeamById(teamId)
|
||||
t, err := getTeamById(e, teamId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1015,19 +1048,16 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro
|
||||
TeamId: teamId,
|
||||
}
|
||||
|
||||
if _, err := sess.Delete(tu); err != nil {
|
||||
sess.Rollback()
|
||||
if _, err := e.Delete(tu); err != nil {
|
||||
return err
|
||||
} else if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
|
||||
sess.Rollback()
|
||||
} else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete access to team repositories.
|
||||
for _, repo := range t.Repos {
|
||||
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId)
|
||||
auth, err := getHighestAuthorize(e, t.OrgId, u.Id, repo.Id, teamId)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1037,17 +1067,14 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro
|
||||
}
|
||||
// Delete access if this is the last team user belongs to.
|
||||
if auth == 0 {
|
||||
if _, err = sess.Delete(access); err != nil {
|
||||
sess.Rollback()
|
||||
if _, err = e.Delete(access); err != nil {
|
||||
return fmt.Errorf("fail to delete access: %v", err)
|
||||
} else if err = WatchRepo(u.Id, repo.Id, false); err != nil {
|
||||
sess.Rollback()
|
||||
} else if err = watchRepo(e, u.Id, repo.Id, false); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if auth < t.Authorize {
|
||||
// Downgrade authorize level.
|
||||
if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil {
|
||||
sess.Rollback()
|
||||
if err = addAccessWithAuthorize(e, access, AuthorizeToAccessType(auth)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -1055,17 +1082,15 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro
|
||||
|
||||
// This must exist.
|
||||
ou := new(OrgUser)
|
||||
_, err = sess.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou)
|
||||
_, err = e.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
ou.NumTeams--
|
||||
if t.IsOwnerTeam() {
|
||||
ou.IsOwner = false
|
||||
}
|
||||
if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil {
|
||||
sess.Rollback()
|
||||
if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -1078,7 +1103,8 @@ func RemoveTeamMember(orgId, teamId, uid int64) error {
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := removeTeamMemberWithSess(orgId, teamId, uid, sess); err != nil {
|
||||
if err := removeTeamMember(sess, orgId, teamId, uid); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
|
||||
@@ -6,6 +6,8 @@ package models
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -27,18 +29,19 @@ import (
|
||||
|
||||
const (
|
||||
// "### autogenerated by gitgos, DO NOT EDIT\n"
|
||||
_TPL_PUBLICK_KEY = `command="%s serv key-%d",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
|
||||
_TPL_PUBLICK_KEY = `command="%s serv key-%d --config='%s'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrKeyAlreadyExist = errors.New("Public key already exist")
|
||||
ErrKeyAlreadyExist = errors.New("Public key already exists")
|
||||
ErrKeyNotExist = errors.New("Public key does not exist")
|
||||
ErrKeyUnableVerify = errors.New("Unable to verify public key")
|
||||
)
|
||||
|
||||
var sshOpLocker = sync.Mutex{}
|
||||
|
||||
var (
|
||||
SshPath string // SSH directory.
|
||||
SSHPath string // SSH directory.
|
||||
appPath string // Execution(binary) path.
|
||||
)
|
||||
|
||||
@@ -69,18 +72,18 @@ func init() {
|
||||
appPath = strings.Replace(appPath, "\\", "/", -1)
|
||||
|
||||
// Determine and create .ssh path.
|
||||
SshPath = filepath.Join(homeDir(), ".ssh")
|
||||
if err = os.MkdirAll(SshPath, 0700); err != nil {
|
||||
log.Fatal(4, "fail to create SshPath(%s): %v\n", SshPath, err)
|
||||
SSHPath = filepath.Join(homeDir(), ".ssh")
|
||||
if err = os.MkdirAll(SSHPath, 0700); err != nil {
|
||||
log.Fatal(4, "fail to create '%s': %v", SSHPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// PublicKey represents a SSH key.
|
||||
type PublicKey struct {
|
||||
Id int64
|
||||
OwnerId int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Fingerprint string
|
||||
OwnerId int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Fingerprint string `xorm:"INDEX NOT NULL"`
|
||||
Content string `xorm:"TEXT NOT NULL"`
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time
|
||||
@@ -88,9 +91,14 @@ type PublicKey struct {
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// OmitEmail returns content of public key but without e-mail address.
|
||||
func (k *PublicKey) OmitEmail() string {
|
||||
return strings.Join(strings.Split(k.Content, " ")[:2], " ")
|
||||
}
|
||||
|
||||
// GetAuthorizedString generates and returns formatted public key string for authorized_keys file.
|
||||
func (key *PublicKey) GetAuthorizedString() string {
|
||||
return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.Id, key.Content)
|
||||
return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.Id, setting.CustomConf, key.Content)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -105,10 +113,90 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func extractTypeFromBase64Key(key string) (string, error) {
|
||||
b, err := base64.StdEncoding.DecodeString(key)
|
||||
if err != nil || len(b) < 4 {
|
||||
return "", errors.New("Invalid key format")
|
||||
}
|
||||
|
||||
keyLength := int(binary.BigEndian.Uint32(b))
|
||||
|
||||
if len(b) < 4+keyLength {
|
||||
return "", errors.New("Invalid key format")
|
||||
}
|
||||
|
||||
return string(b[4 : 4+keyLength]), nil
|
||||
}
|
||||
|
||||
// Parse any key string in openssh or ssh2 format to clean openssh string (rfc4253)
|
||||
func ParseKeyString(content string) (string, error) {
|
||||
|
||||
// Transform all legal line endings to a single "\n"
|
||||
s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1)
|
||||
|
||||
lines := strings.Split(s, "\n")
|
||||
|
||||
var keyType, keyContent, keyComment string
|
||||
|
||||
if len(lines) == 1 {
|
||||
// Parse openssh format
|
||||
parts := strings.Fields(lines[0])
|
||||
switch len(parts) {
|
||||
case 0:
|
||||
return "", errors.New("Empty key")
|
||||
case 1:
|
||||
keyContent = parts[0]
|
||||
case 2:
|
||||
keyType = parts[0]
|
||||
keyContent = parts[1]
|
||||
default:
|
||||
keyType = parts[0]
|
||||
keyContent = parts[1]
|
||||
keyComment = parts[2]
|
||||
}
|
||||
|
||||
// If keyType is not given, extract it from content. If given, validate it
|
||||
if len(keyType) == 0 {
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err == nil {
|
||||
keyType = t
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err != nil || keyType != t {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Parse SSH2 file format.
|
||||
continuationLine := false
|
||||
|
||||
for _, line := range lines {
|
||||
// Skip lines that:
|
||||
// 1) are a continuation of the previous line,
|
||||
// 2) contain ":" as that are comment lines
|
||||
// 3) contain "-" as that are begin and end tags
|
||||
if continuationLine || strings.ContainsAny(line, ":-") {
|
||||
continuationLine = strings.HasSuffix(line, "\\")
|
||||
} else {
|
||||
keyContent = keyContent + line
|
||||
}
|
||||
}
|
||||
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err == nil {
|
||||
keyType = t
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return keyType + " " + keyContent + " " + keyComment, nil
|
||||
}
|
||||
|
||||
// CheckPublicKeyString checks if the given public key string is recognized by SSH.
|
||||
func CheckPublicKeyString(content string) (bool, error) {
|
||||
content = strings.TrimRight(content, "\n\r")
|
||||
if strings.ContainsAny(content, "\n\r") {
|
||||
return false, errors.New("Only a single line with a single key please")
|
||||
return false, errors.New("only a single line with a single key please")
|
||||
}
|
||||
|
||||
// write the key to a file…
|
||||
@@ -126,7 +214,7 @@ func CheckPublicKeyString(content string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, errors.New("ssh-keygen -l -f: " + stderr)
|
||||
} else if len(stdout) < 2 {
|
||||
return false, errors.New("ssh-keygen returned not enough output to evaluate the key")
|
||||
return false, errors.New("ssh-keygen returned not enough output to evaluate the key: " + stdout)
|
||||
}
|
||||
|
||||
// The ssh-keygen in Windows does not print key type, so no need go further.
|
||||
@@ -134,37 +222,39 @@ func CheckPublicKeyString(content string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
fmt.Println(stdout)
|
||||
sshKeygenOutput := strings.Split(stdout, " ")
|
||||
if len(sshKeygenOutput) < 4 {
|
||||
return false, errors.New("Not enough fields returned by ssh-keygen -l -f")
|
||||
return false, ErrKeyUnableVerify
|
||||
}
|
||||
|
||||
// Check if key type and key size match.
|
||||
keySize, err := com.StrTo(sshKeygenOutput[0]).Int()
|
||||
if err != nil {
|
||||
return false, errors.New("Cannot get key size of the given key")
|
||||
keySize := com.StrTo(sshKeygenOutput[0]).MustInt()
|
||||
if keySize == 0 {
|
||||
return false, errors.New("cannot get key size of the given key")
|
||||
}
|
||||
keyType := strings.TrimSpace(sshKeygenOutput[len(sshKeygenOutput)-1])
|
||||
if minimumKeySize := MinimumKeySize[keyType]; minimumKeySize == 0 {
|
||||
return false, errors.New("Sorry, unrecognized public key type")
|
||||
return false, errors.New("sorry, unrecognized public key type")
|
||||
} else if keySize < minimumKeySize {
|
||||
return false, fmt.Errorf("The minimum accepted size of a public key %s is %d", keyType, minimumKeySize)
|
||||
return false, fmt.Errorf("the minimum accepted size of a public key %s is %d", keyType, minimumKeySize)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// saveAuthorizedKeyFile writes SSH key content to authorized_keys file.
|
||||
func saveAuthorizedKeyFile(key *PublicKey) error {
|
||||
func saveAuthorizedKeyFile(keys ...*PublicKey) error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
fpath := filepath.Join(SshPath, "authorized_keys")
|
||||
fpath := filepath.Join(SSHPath, "authorized_keys")
|
||||
f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
finfo, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -180,8 +270,12 @@ func saveAuthorizedKeyFile(key *PublicKey) error {
|
||||
}
|
||||
}
|
||||
|
||||
_, err = f.WriteString(key.GetAuthorizedString())
|
||||
return err
|
||||
for _, key := range keys {
|
||||
if _, err = f.WriteString(key.GetAuthorizedString()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPublicKey adds new public key to database and authorized_keys file.
|
||||
@@ -204,9 +298,12 @@ func AddPublicKey(key *PublicKey) (err error) {
|
||||
if err != nil {
|
||||
return errors.New("ssh-keygen -l -f: " + stderr)
|
||||
} else if len(stdout) < 2 {
|
||||
return errors.New("Not enough output for calculating fingerprint")
|
||||
return errors.New("not enough output for calculating fingerprint: " + stdout)
|
||||
}
|
||||
key.Fingerprint = strings.Split(stdout, " ")[1]
|
||||
if has, err := x.Get(&PublicKey{Fingerprint: key.Fingerprint}); err == nil && has {
|
||||
return ErrKeyAlreadyExist
|
||||
}
|
||||
|
||||
// Save SSH key.
|
||||
if _, err = x.Insert(key); err != nil {
|
||||
@@ -234,10 +331,10 @@ func GetPublicKeyById(keyId int64) (*PublicKey, error) {
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// ListPublicKey returns a list of all public keys that user has.
|
||||
func ListPublicKey(uid int64) ([]*PublicKey, error) {
|
||||
// ListPublicKeys returns a list of public keys belongs to given user.
|
||||
func ListPublicKeys(uid int64) ([]*PublicKey, error) {
|
||||
keys := make([]*PublicKey, 0, 5)
|
||||
err := x.Find(&keys, &PublicKey{OwnerId: uid})
|
||||
err := x.Where("owner_id=?", uid).Find(&keys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -321,8 +418,8 @@ func DeletePublicKey(key *PublicKey) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fpath := filepath.Join(SshPath, "authorized_keys")
|
||||
tmpPath := filepath.Join(SshPath, "authorized_keys.tmp")
|
||||
fpath := filepath.Join(SSHPath, "authorized_keys")
|
||||
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
|
||||
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
|
||||
return err
|
||||
} else if err = os.Remove(fpath); err != nil {
|
||||
@@ -330,3 +427,37 @@ func DeletePublicKey(key *PublicKey) error {
|
||||
}
|
||||
return os.Rename(tmpPath, fpath)
|
||||
}
|
||||
|
||||
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
|
||||
func RewriteAllPublicKeys() error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
|
||||
f, err := os.Create(tmpPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
_, err = f.WriteString((bean.(*PublicKey)).GetAuthorizedString())
|
||||
return err
|
||||
})
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fpath := filepath.Join(SSHPath, "authorized_keys")
|
||||
if com.IsExist(fpath) {
|
||||
if err = os.Remove(fpath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = os.Rename(tmpPath, fpath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
513
models/repo.go
513
models/repo.go
@@ -7,7 +7,6 @@ package models
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -31,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3\n"
|
||||
_TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3 --config='%s'\n"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -105,21 +104,18 @@ func NewRepoContext() {
|
||||
log.Fatal(4, "Gogs requires Git version greater or equal to 1.7.1")
|
||||
}
|
||||
|
||||
// Check if server has basic git setting and set if not.
|
||||
if stdout, stderr, err := process.Exec("NewRepoContext(get setting)", "git", "config", "--get", "user.name"); err != nil || strings.TrimSpace(stdout) == "" {
|
||||
// ExitError indicates user.name is not set
|
||||
if _, ok := err.(*exec.ExitError); ok || strings.TrimSpace(stdout) == "" {
|
||||
stndrdUserName := "Gogs"
|
||||
stndrdUserEmail := "gogitservice@gmail.com"
|
||||
if _, stderr, gerr := process.Exec("NewRepoContext(set name)", "git", "config", "--global", "user.name", stndrdUserName); gerr != nil {
|
||||
log.Fatal(4, "Fail to set git user.name(%s): %s", gerr, stderr)
|
||||
// Check if server has user.email and user.name set correctly and set if they're not.
|
||||
for configKey, defaultValue := range map[string]string{"user.name": "Gogs", "user.email": "gogitservice@gmail.com"} {
|
||||
if stdout, stderr, err := process.Exec("NewRepoContext(get setting)", "git", "config", "--get", configKey); err != nil || strings.TrimSpace(stdout) == "" {
|
||||
// ExitError indicates this config is not set
|
||||
if _, ok := err.(*exec.ExitError); ok || strings.TrimSpace(stdout) == "" {
|
||||
if _, stderr, gerr := process.Exec("NewRepoContext(set "+configKey+")", "git", "config", "--global", configKey, defaultValue); gerr != nil {
|
||||
log.Fatal(4, "Fail to set git %s(%s): %s", configKey, gerr, stderr)
|
||||
}
|
||||
log.Info("Git config %s set to %s", configKey, defaultValue)
|
||||
} else {
|
||||
log.Fatal(4, "Fail to get git %s(%s): %s", configKey, err, stderr)
|
||||
}
|
||||
if _, stderr, gerr := process.Exec("NewRepoContext(set email)", "git", "config", "--global", "user.email", stndrdUserEmail); gerr != nil {
|
||||
log.Fatal(4, "Fail to set git user.email(%s): %s", gerr, stderr)
|
||||
}
|
||||
log.Info("Git user.name and user.email set to %s <%s>", stndrdUserName, stndrdUserEmail)
|
||||
} else {
|
||||
log.Fatal(4, "Fail to get git user.name(%s): %s", err, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,14 +129,15 @@ func NewRepoContext() {
|
||||
|
||||
// Repository represents a git repository.
|
||||
type Repository struct {
|
||||
Id int64
|
||||
OwnerId int64 `xorm:"UNIQUE(s)"`
|
||||
Owner *User `xorm:"-"`
|
||||
ForkId int64
|
||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"INDEX NOT NULL"`
|
||||
Description string
|
||||
Website string
|
||||
Id int64
|
||||
OwnerId int64 `xorm:"UNIQUE(s)"`
|
||||
Owner *User `xorm:"-"`
|
||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"INDEX NOT NULL"`
|
||||
Description string
|
||||
Website string
|
||||
DefaultBranch string
|
||||
|
||||
NumWatches int
|
||||
NumStars int
|
||||
NumForks int
|
||||
@@ -154,15 +151,20 @@ type Repository struct {
|
||||
NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"`
|
||||
NumOpenMilestones int `xorm:"-"`
|
||||
NumTags int `xorm:"-"`
|
||||
IsPrivate bool
|
||||
IsMirror bool
|
||||
*Mirror `xorm:"-"`
|
||||
IsFork bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsBare bool
|
||||
IsGoget bool
|
||||
DefaultBranch string
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
|
||||
IsPrivate bool
|
||||
IsBare bool
|
||||
IsGoget bool
|
||||
|
||||
IsMirror bool
|
||||
*Mirror `xorm:"-"`
|
||||
|
||||
IsFork bool `xorm:"NOT NULL DEFAULT false"`
|
||||
ForkId int64
|
||||
ForkRepo *Repository `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
}
|
||||
|
||||
func (repo *Repository) GetOwner() (err error) {
|
||||
@@ -177,6 +179,33 @@ func (repo *Repository) GetMirror() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *Repository) GetForkRepo() (err error) {
|
||||
if !repo.IsFork {
|
||||
return nil
|
||||
}
|
||||
|
||||
repo.ForkRepo, err = GetRepositoryById(repo.ForkId)
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *Repository) RepoPath() (string, error) {
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return RepoPath(repo.Owner.Name, repo.Name), nil
|
||||
}
|
||||
|
||||
func (repo *Repository) RepoLink() (string, error) {
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return setting.AppSubUrl + "/" + repo.Owner.Name + "/" + repo.Name, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) IsOwnedBy(u *User) bool {
|
||||
return repo.OwnerId == u.Id
|
||||
}
|
||||
|
||||
func (repo *Repository) HasAccess(uname string) bool {
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return false
|
||||
@@ -188,11 +217,9 @@ func (repo *Repository) HasAccess(uname string) bool {
|
||||
// DescriptionHtml does special handles to description and return HTML string.
|
||||
func (repo *Repository) DescriptionHtml() template.HTML {
|
||||
sanitize := func(s string) string {
|
||||
// TODO(nuss-justin): Improve sanitization. Strip all tags?
|
||||
ss := html.EscapeString(s)
|
||||
return fmt.Sprintf(`<a href="%s" target="_blank">%s</a>`, ss, ss)
|
||||
return fmt.Sprintf(`<a href="%[1]s" target="_blank">%[1]s</a>`, s)
|
||||
}
|
||||
return template.HTML(DescPattern.ReplaceAllStringFunc(base.XSSString(repo.Description), sanitize))
|
||||
return template.HTML(DescPattern.ReplaceAllStringFunc(base.Sanitizer.Sanitize(repo.Description), sanitize))
|
||||
}
|
||||
|
||||
// IsRepositoryExist returns true if the repository with given name under user has already existed.
|
||||
@@ -208,9 +235,30 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
|
||||
return com.IsDir(RepoPath(u.Name, repoName)), nil
|
||||
}
|
||||
|
||||
// CloneLink represents different types of clone URLs of repository.
|
||||
type CloneLink struct {
|
||||
SSH string
|
||||
HTTPS string
|
||||
Git string
|
||||
}
|
||||
|
||||
// CloneLink returns clone URLs of repository.
|
||||
func (repo *Repository) CloneLink() (cl CloneLink, err error) {
|
||||
if err = repo.GetOwner(); err != nil {
|
||||
return cl, err
|
||||
}
|
||||
if setting.SSHPort != 22 {
|
||||
cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.Domain, setting.SSHPort, repo.Owner.LowerName, repo.LowerName)
|
||||
} else {
|
||||
cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, repo.Owner.LowerName, repo.LowerName)
|
||||
}
|
||||
cl.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, repo.Owner.LowerName, repo.LowerName)
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
var (
|
||||
illegalEquals = []string{"debug", "raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin", "new"}
|
||||
illegalSuffixs = []string{".git"}
|
||||
illegalSuffixs = []string{".git", ".keys"}
|
||||
)
|
||||
|
||||
// IsLegalName returns false if name contains illegal characters.
|
||||
@@ -275,28 +323,6 @@ func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// MirrorUpdate checks and updates mirror repositories.
|
||||
func MirrorUpdate() {
|
||||
if err := x.Iterate(new(Mirror), func(idx int, bean interface{}) error {
|
||||
m := bean.(*Mirror)
|
||||
if m.NextUpdate.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
repoPath := filepath.Join(setting.RepoRootPath, m.RepoName+".git")
|
||||
if _, stderr, err := process.ExecDir(10*time.Minute,
|
||||
repoPath, fmt.Sprintf("MirrorUpdate: %s", repoPath),
|
||||
"git", "remote", "update"); err != nil {
|
||||
return errors.New("git remote update: " + stderr)
|
||||
}
|
||||
|
||||
m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
|
||||
return UpdateMirror(m)
|
||||
}); err != nil {
|
||||
log.Error(4, "repo.MirrorUpdate: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// MigrateRepository migrates a existing repository from other project hosting.
|
||||
func MigrateRepository(u *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
|
||||
repo, err := CreateRepository(u, name, desc, "", "", private, mirror, false)
|
||||
@@ -331,13 +357,16 @@ func MigrateRepository(u *User, name, desc string, private, mirror bool, url str
|
||||
os.RemoveAll(repoPath)
|
||||
}
|
||||
|
||||
// this command could for both migrate and mirror
|
||||
// FIXME: this command could for both migrate and mirror
|
||||
_, stderr, err := process.ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("MigrateRepository: %s", repoPath),
|
||||
"git", "clone", "--mirror", "--bare", url, repoPath)
|
||||
if err != nil {
|
||||
return repo, errors.New("git clone: " + stderr)
|
||||
return repo, fmt.Errorf("git clone --mirror --bare: %v", stderr)
|
||||
} else if err = createUpdateHook(repoPath); err != nil {
|
||||
return repo, fmt.Errorf("create update hook: %v", err)
|
||||
}
|
||||
|
||||
return repo, UpdateRepository(repo)
|
||||
}
|
||||
|
||||
@@ -376,15 +405,9 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createHookUpdate(hookPath, content string) error {
|
||||
pu, err := os.OpenFile(hookPath, os.O_CREATE|os.O_WRONLY, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pu.Close()
|
||||
|
||||
_, err = pu.WriteString(content)
|
||||
return err
|
||||
func createUpdateHook(repoPath string) error {
|
||||
return ioutil.WriteFile(path.Join(repoPath, "hooks/update"),
|
||||
[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777)
|
||||
}
|
||||
|
||||
// InitRepository initializes README and .gitignore if needed.
|
||||
@@ -396,9 +419,7 @@ func initRepository(f string, u *User, repo *Repository, initReadme bool, repoLa
|
||||
return err
|
||||
}
|
||||
|
||||
// hook/post-update
|
||||
if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"),
|
||||
fmt.Sprintf(TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"")); err != nil {
|
||||
if err := createUpdateHook(repoPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -478,6 +499,11 @@ func initRepository(f string, u *User, repo *Repository, initReadme bool, repoLa
|
||||
}
|
||||
|
||||
if len(fileName) == 0 {
|
||||
// Re-fetch the repository from database before updating it (else it would
|
||||
// override changes that were done earlier with sql)
|
||||
if repo, err = GetRepositoryById(repo.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
repo.IsBare = true
|
||||
repo.DefaultBranch = "master"
|
||||
return UpdateRepository(repo)
|
||||
@@ -663,7 +689,7 @@ func RepoPath(userName, repoName string) string {
|
||||
func TransferOwnership(u *User, newOwner string, repo *Repository) error {
|
||||
newUser, err := GetUserByName(newOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("fail to get new owner(%s): %v", newOwner, err)
|
||||
}
|
||||
|
||||
// Check if new owner has repository with same name.
|
||||
@@ -800,13 +826,16 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error {
|
||||
|
||||
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
|
||||
func ChangeRepositoryName(userName, oldRepoName, newRepoName string) (err error) {
|
||||
userName = strings.ToLower(userName)
|
||||
oldRepoName = strings.ToLower(oldRepoName)
|
||||
newRepoName = strings.ToLower(newRepoName)
|
||||
if !IsLegalName(newRepoName) {
|
||||
return ErrRepoNameIllegal
|
||||
}
|
||||
|
||||
// Update accesses.
|
||||
accesses := make([]Access, 0, 10)
|
||||
if err = x.Find(&accesses, &Access{RepoName: strings.ToLower(userName + "/" + oldRepoName)}); err != nil {
|
||||
if err = x.Find(&accesses, &Access{RepoName: userName + "/" + oldRepoName}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -845,7 +874,7 @@ func UpdateRepository(repo *Repository) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteRepository deletes a repository for a user or orgnaztion.
|
||||
// DeleteRepository deletes a repository for a user or organization.
|
||||
func DeleteRepository(uid, repoId int64, userName string) error {
|
||||
repo := &Repository{Id: repoId, OwnerId: uid}
|
||||
has, err := x.Get(repo)
|
||||
@@ -940,6 +969,13 @@ func DeleteRepository(uid, repoId int64, userName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if repo.IsFork {
|
||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
@@ -1040,15 +1076,21 @@ func GetCollaboratorNames(repoName string) ([]string, error) {
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// CollaborativeRepository represents a repository with collaborative information.
|
||||
type CollaborativeRepository struct {
|
||||
*Repository
|
||||
CanPush bool
|
||||
}
|
||||
|
||||
// GetCollaborativeRepos returns a list of repositories that user is collaborator.
|
||||
func GetCollaborativeRepos(uname string) ([]*Repository, error) {
|
||||
func GetCollaborativeRepos(uname string) ([]*CollaborativeRepository, error) {
|
||||
uname = strings.ToLower(uname)
|
||||
accesses := make([]*Access, 0, 10)
|
||||
if err := x.Find(&accesses, &Access{UserName: uname}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repos := make([]*Repository, 0, 10)
|
||||
repos := make([]*CollaborativeRepository, 0, 10)
|
||||
for _, access := range accesses {
|
||||
infos := strings.Split(access.RepoName, "/")
|
||||
if infos[0] == uname {
|
||||
@@ -1065,7 +1107,7 @@ func GetCollaborativeRepos(uname string) ([]*Repository, error) {
|
||||
return nil, err
|
||||
}
|
||||
repo.Owner = u
|
||||
repos = append(repos, repo)
|
||||
repos = append(repos, &CollaborativeRepository{repo, access.Mode == WRITABLE})
|
||||
}
|
||||
return repos, nil
|
||||
}
|
||||
@@ -1091,17 +1133,11 @@ type SearchOption struct {
|
||||
Keyword string
|
||||
Uid int64
|
||||
Limit int
|
||||
Private bool
|
||||
}
|
||||
|
||||
// SearchRepositoryByName returns given number of repositories whose name contains keyword.
|
||||
func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) {
|
||||
// Prevent SQL inject.
|
||||
opt.Keyword = strings.TrimSpace(opt.Keyword)
|
||||
if len(opt.Keyword) == 0 {
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
opt.Keyword = strings.Split(opt.Keyword, " ")[0]
|
||||
if len(opt.Keyword) == 0 {
|
||||
return repos, nil
|
||||
}
|
||||
@@ -1114,10 +1150,132 @@ func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) {
|
||||
if opt.Uid > 0 {
|
||||
sess.Where("owner_id=?", opt.Uid)
|
||||
}
|
||||
sess.And("lower_name like '%" + opt.Keyword + "%'").Find(&repos)
|
||||
if !opt.Private {
|
||||
sess.And("is_private=false")
|
||||
}
|
||||
sess.And("lower_name like ?", "%"+opt.Keyword+"%").Find(&repos)
|
||||
return repos, err
|
||||
}
|
||||
|
||||
// DeleteRepositoryArchives deletes all repositories' archives.
|
||||
func DeleteRepositoryArchives() error {
|
||||
return x.Where("id > 0").Iterate(new(Repository),
|
||||
func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.RemoveAll(filepath.Join(RepoPath(repo.Owner.Name, repo.Name), "archives"))
|
||||
})
|
||||
}
|
||||
|
||||
// RewriteRepositoryUpdateHook rewrites all repositories' update hook.
|
||||
func RewriteRepositoryUpdateHook() error {
|
||||
return x.Where("id > 0").Iterate(new(Repository),
|
||||
func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return err
|
||||
}
|
||||
return createUpdateHook(RepoPath(repo.Owner.Name, repo.Name))
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
// Prevent duplicate tasks.
|
||||
isMirrorUpdating = false
|
||||
isGitFscking = false
|
||||
)
|
||||
|
||||
// MirrorUpdate checks and updates mirror repositories.
|
||||
func MirrorUpdate() {
|
||||
if isMirrorUpdating {
|
||||
return
|
||||
}
|
||||
isMirrorUpdating = true
|
||||
defer func() { isMirrorUpdating = false }()
|
||||
|
||||
mirrors := make([]*Mirror, 0, 10)
|
||||
|
||||
if err := x.Iterate(new(Mirror), func(idx int, bean interface{}) error {
|
||||
m := bean.(*Mirror)
|
||||
if m.NextUpdate.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
repoPath := filepath.Join(setting.RepoRootPath, m.RepoName+".git")
|
||||
if _, stderr, err := process.ExecDir(10*time.Minute,
|
||||
repoPath, fmt.Sprintf("MirrorUpdate: %s", repoPath),
|
||||
"git", "remote", "update"); err != nil {
|
||||
desc := fmt.Sprintf("Fail to update mirror repository(%s): %s", repoPath, stderr)
|
||||
log.Error(4, desc)
|
||||
if err = CreateRepositoryNotice(desc); err != nil {
|
||||
log.Error(4, "Fail to add notice: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
|
||||
mirrors = append(mirrors, m)
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Error(4, "MirrorUpdate: %v", err)
|
||||
}
|
||||
|
||||
for i := range mirrors {
|
||||
if err := UpdateMirror(mirrors[i]); err != nil {
|
||||
log.Error(4, "UpdateMirror", fmt.Sprintf("%s: %v", mirrors[i].RepoName, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GitFsck calls 'git fsck' to check repository health.
|
||||
func GitFsck() {
|
||||
if isGitFscking {
|
||||
return
|
||||
}
|
||||
isGitFscking = true
|
||||
defer func() { isGitFscking = false }()
|
||||
|
||||
args := append([]string{"fsck"}, setting.Git.Fsck.Args...)
|
||||
if err := x.Where("id > 0").Iterate(new(Repository),
|
||||
func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoPath := RepoPath(repo.Owner.Name, repo.Name)
|
||||
_, _, err := process.ExecDir(-1, repoPath, "Repository health check", "git", args...)
|
||||
if err != nil {
|
||||
desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath)
|
||||
log.Warn(desc)
|
||||
if err = CreateRepositoryNotice(desc); err != nil {
|
||||
log.Error(4, "Fail to add notice: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Error(4, "repo.Fsck: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func GitGcRepos() error {
|
||||
args := append([]string{"gc"}, setting.Git.GcArgs...)
|
||||
return x.Where("id > 0").Iterate(new(Repository),
|
||||
func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
if err := repo.GetOwner(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, stderr, err := process.ExecDir(-1, RepoPath(repo.Owner.Name, repo.Name), "Repository garbage collection", "git", args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", err, stderr)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// __ __ __ .__
|
||||
// / \ / \_____ _/ |_ ____ | |__
|
||||
// \ \/\/ /\__ \\ __\/ ___\| | \
|
||||
@@ -1125,39 +1283,43 @@ func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) {
|
||||
// \__/\ / (____ /__| \___ >___| /
|
||||
// \/ \/ \/ \/
|
||||
|
||||
// Watch is connection request for receiving repository notifycation.
|
||||
// Watch is connection request for receiving repository notification.
|
||||
type Watch struct {
|
||||
Id int64
|
||||
UserId int64 `xorm:"UNIQUE(watch)"`
|
||||
RepoId int64 `xorm:"UNIQUE(watch)"`
|
||||
}
|
||||
|
||||
// Watch or unwatch repository.
|
||||
func WatchRepo(uid, repoId int64, watch bool) (err error) {
|
||||
// IsWatching checks if user has watched given repository.
|
||||
func IsWatching(uid, repoId int64) bool {
|
||||
has, _ := x.Get(&Watch{0, uid, repoId})
|
||||
return has
|
||||
}
|
||||
|
||||
func watchRepo(e Engine, uid, repoId int64, watch bool) (err error) {
|
||||
if watch {
|
||||
if IsWatching(uid, repoId) {
|
||||
return nil
|
||||
}
|
||||
if _, err = x.Insert(&Watch{RepoId: repoId, UserId: uid}); err != nil {
|
||||
if _, err = e.Insert(&Watch{RepoId: repoId, UserId: uid}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = x.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoId)
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoId)
|
||||
} else {
|
||||
if !IsWatching(uid, repoId) {
|
||||
return nil
|
||||
}
|
||||
if _, err = x.Delete(&Watch{0, uid, repoId}); err != nil {
|
||||
if _, err = e.Delete(&Watch{0, uid, repoId}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = x.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoId)
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoId)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// IsWatching checks if user has watched given repository.
|
||||
func IsWatching(uid, rid int64) bool {
|
||||
has, _ := x.Get(&Watch{0, uid, rid})
|
||||
return has
|
||||
// Watch or unwatch repository.
|
||||
func WatchRepo(uid, repoId int64, watch bool) (err error) {
|
||||
return watchRepo(x, uid, repoId, watch)
|
||||
}
|
||||
|
||||
// GetWatchers returns all watchers of given repository.
|
||||
@@ -1240,6 +1402,157 @@ func IsStaring(uid, repoId int64) bool {
|
||||
return has
|
||||
}
|
||||
|
||||
func ForkRepository(repoName string, uid int64) {
|
||||
// ___________ __
|
||||
// \_ _____/__________| | __
|
||||
// | __)/ _ \_ __ \ |/ /
|
||||
// | \( <_> ) | \/ <
|
||||
// \___ / \____/|__| |__|_ \
|
||||
// \/ \/
|
||||
|
||||
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (*Repository, error) {
|
||||
isExist, err := IsRepositoryExist(u, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if isExist {
|
||||
return nil, ErrRepoAlreadyExist
|
||||
}
|
||||
|
||||
// In case the old repository is a fork.
|
||||
if oldRepo.IsFork {
|
||||
oldRepo, err = GetRepositoryById(oldRepo.ForkId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
OwnerId: u.Id,
|
||||
Owner: u,
|
||||
Name: name,
|
||||
LowerName: strings.ToLower(name),
|
||||
Description: desc,
|
||||
IsPrivate: oldRepo.IsPrivate,
|
||||
IsFork: true,
|
||||
ForkId: oldRepo.Id,
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(repo); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var t *Team // Owner team.
|
||||
|
||||
mode := WRITABLE
|
||||
|
||||
access := &Access{
|
||||
UserName: u.LowerName,
|
||||
RepoName: path.Join(u.LowerName, repo.LowerName),
|
||||
Mode: mode,
|
||||
}
|
||||
// Give access to all members in owner team.
|
||||
if u.IsOrganization() {
|
||||
t, err = u.GetOwnerTeam()
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err = t.GetMembers(); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
for _, u := range t.Members {
|
||||
access.Id = 0
|
||||
access.UserName = u.LowerName
|
||||
if _, err = sess.Insert(access); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if _, err = sess.Insert(access); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = sess.Exec(
|
||||
"UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", u.Id); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update owner team info and count.
|
||||
if u.IsOrganization() {
|
||||
t.RepoIds += "$" + com.ToStr(repo.Id) + "|"
|
||||
t.NumRepos++
|
||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if u.IsOrganization() {
|
||||
t, err := u.GetOwnerTeam()
|
||||
if err != nil {
|
||||
log.Error(4, "GetOwnerTeam: %v", err)
|
||||
} else {
|
||||
if err = t.GetMembers(); err != nil {
|
||||
log.Error(4, "GetMembers: %v", err)
|
||||
} else {
|
||||
for _, u := range t.Members {
|
||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
|
||||
log.Error(4, "WatchRepo2: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
|
||||
log.Error(4, "WatchRepo3: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = NewRepoAction(u, repo); err != nil {
|
||||
log.Error(4, "NewRepoAction: %v", err)
|
||||
}
|
||||
|
||||
if _, err = sess.Exec(
|
||||
"UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil {
|
||||
sess.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldRepoPath, err := oldRepo.RepoPath()
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return nil, fmt.Errorf("fail to get repo path(%s): %v", oldRepo.Name, err)
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoPath := RepoPath(u.Name, repo.Name)
|
||||
_, stderr, err := process.ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("ForkRepository(git clone): %s/%s", u.Name, repo.Name),
|
||||
"git", "clone", "--bare", oldRepoPath, repoPath)
|
||||
if err != nil {
|
||||
return nil, errors.New("ForkRepository(git clone): " + stderr)
|
||||
}
|
||||
|
||||
_, stderr, err = process.ExecDir(-1,
|
||||
repoPath, fmt.Sprintf("ForkRepository(git update-server-info): %s", repoPath),
|
||||
"git", "update-server-info")
|
||||
if err != nil {
|
||||
return nil, errors.New("ForkRepository(git update-server-info): " + stderr)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ const (
|
||||
)
|
||||
|
||||
type Slack struct {
|
||||
Domain string `json:"domain"`
|
||||
Token string `json:"token"`
|
||||
Channel string `json:"channel"`
|
||||
}
|
||||
|
||||
@@ -36,14 +34,6 @@ type SlackAttachment struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func GetSlackURL(domain string, token string) string {
|
||||
return fmt.Sprintf(
|
||||
"https://%s.slack.com/services/hooks/incoming-webhook?token=%s",
|
||||
domain,
|
||||
token,
|
||||
)
|
||||
}
|
||||
|
||||
func (p SlackPayload) GetJSONPayload() ([]byte, error) {
|
||||
data, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
|
||||
69
models/token.go
Normal file
69
models/token.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAccessTokenNotExist = errors.New("Access token does not exist")
|
||||
)
|
||||
|
||||
// AccessToken represents a personal access token.
|
||||
type AccessToken struct {
|
||||
Id int64
|
||||
Uid int64
|
||||
Name string
|
||||
Sha1 string `xorm:"UNIQUE VARCHAR(40)"`
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// NewAccessToken creates new access token.
|
||||
func NewAccessToken(t *AccessToken) error {
|
||||
t.Sha1 = base.EncodeSha1(uuid.NewV4().String())
|
||||
_, err := x.Insert(t)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAccessTokenBySha returns access token by given sha1.
|
||||
func GetAccessTokenBySha(sha string) (*AccessToken, error) {
|
||||
t := &AccessToken{Sha1: sha}
|
||||
has, err := x.Get(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrAccessTokenNotExist
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// ListAccessTokens returns a list of access tokens belongs to given user.
|
||||
func ListAccessTokens(uid int64) ([]*AccessToken, error) {
|
||||
tokens := make([]*AccessToken, 0, 5)
|
||||
err := x.Where("uid=?", uid).Desc("id").Find(&tokens)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, t := range tokens {
|
||||
t.HasUsed = t.Updated.After(t.Created)
|
||||
t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(time.Now())
|
||||
}
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
// DeleteAccessTokenById deletes access token by given ID.
|
||||
func DeleteAccessTokenById(id int64) error {
|
||||
_, err := x.Id(id).Delete(new(AccessToken))
|
||||
return err
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
|
||||
|
||||
if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
|
||||
repos.Id, repoUserName, repoName, refName, commit, oldCommitId, newCommitId); err != nil {
|
||||
log.GitLogger.Fatal(4, "runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
|
||||
log.GitLogger.Fatal(4, "CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -116,8 +116,8 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
|
||||
return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
|
||||
}
|
||||
|
||||
// Push new branch.
|
||||
var l *list.List
|
||||
// if a new branch
|
||||
if isNew {
|
||||
l, err = newCommit.CommitsBefore()
|
||||
if err != nil {
|
||||
@@ -134,7 +134,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
|
||||
return fmt.Errorf("runUpdate.Commit repoId: %v", err)
|
||||
}
|
||||
|
||||
// if commits push
|
||||
// Push commits.
|
||||
commits := make([]*base.PushCommit, 0)
|
||||
var actEmail string
|
||||
for e := l.Front(); e != nil; e = e.Next() {
|
||||
@@ -153,9 +153,8 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
|
||||
}
|
||||
}
|
||||
|
||||
//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
|
||||
if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
|
||||
repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits}, oldCommitId, newCommitId); err != nil {
|
||||
repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits, ""}, oldCommitId, newCommitId); err != nil {
|
||||
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
|
||||
}
|
||||
return nil
|
||||
|
||||
359
models/user.go
359
models/user.go
@@ -5,18 +5,23 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/nfnt/resize"
|
||||
|
||||
"github.com/gogits/gogs/modules/avatar"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
@@ -37,6 +42,8 @@ var (
|
||||
ErrUserNotExist = errors.New("User does not exist")
|
||||
ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
|
||||
ErrEmailAlreadyUsed = errors.New("E-mail already used")
|
||||
ErrEmailNotExist = errors.New("E-mail does not exist")
|
||||
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
|
||||
ErrUserNameIllegal = errors.New("User name contains illegal characters")
|
||||
ErrLoginSourceNotExist = errors.New("Login source does not exist")
|
||||
ErrLoginSourceNotActived = errors.New("Login source is not actived")
|
||||
@@ -45,32 +52,41 @@ var (
|
||||
|
||||
// User represents the object of individual and member of organization.
|
||||
type User struct {
|
||||
Id int64
|
||||
LowerName string `xorm:"UNIQUE NOT NULL"`
|
||||
Name string `xorm:"UNIQUE NOT NULL"`
|
||||
FullName string
|
||||
Email string `xorm:"UNIQUE NOT NULL"`
|
||||
Passwd string `xorm:"NOT NULL"`
|
||||
LoginType LoginType
|
||||
LoginSource int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
LoginName string
|
||||
Type UserType
|
||||
Orgs []*User `xorm:"-"`
|
||||
Repos []*Repository `xorm:"-"`
|
||||
Id int64
|
||||
LowerName string `xorm:"UNIQUE NOT NULL"`
|
||||
Name string `xorm:"UNIQUE NOT NULL"`
|
||||
FullName string
|
||||
// Email is the primary email address (to be used for communication).
|
||||
Email string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Passwd string `xorm:"NOT NULL"`
|
||||
LoginType LoginType
|
||||
LoginSource int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
LoginName string
|
||||
Type UserType `xorm:"UNIQUE(s)"`
|
||||
Orgs []*User `xorm:"-"`
|
||||
Repos []*Repository `xorm:"-"`
|
||||
Location string
|
||||
Website string
|
||||
Rands string `xorm:"VARCHAR(10)"`
|
||||
Salt string `xorm:"VARCHAR(10)"`
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
|
||||
// Permissions.
|
||||
IsActive bool
|
||||
IsAdmin bool
|
||||
AllowGitHook bool
|
||||
|
||||
// Avatar.
|
||||
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
|
||||
AvatarEmail string `xorm:"NOT NULL"`
|
||||
UseCustomAvatar bool
|
||||
|
||||
// Counters.
|
||||
NumFollowers int
|
||||
NumFollowings int
|
||||
NumStars int
|
||||
NumRepos int
|
||||
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
|
||||
AvatarEmail string `xorm:"NOT NULL"`
|
||||
Location string
|
||||
Website string
|
||||
IsActive bool
|
||||
IsAdmin bool
|
||||
Rands string `xorm:"VARCHAR(10)"`
|
||||
Salt string `xorm:"VARCHAR(10)"`
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
|
||||
// For organization.
|
||||
Description string
|
||||
@@ -80,6 +96,16 @@ type User struct {
|
||||
Members []*User `xorm:"-"`
|
||||
}
|
||||
|
||||
// EmailAdresses is the list of all email addresses of a user. Can contain the
|
||||
// primary email address, but is not obligatory
|
||||
type EmailAddress struct {
|
||||
Id int64
|
||||
Uid int64 `xorm:"INDEX NOT NULL"`
|
||||
Email string `xorm:"UNIQUE NOT NULL"`
|
||||
IsActivated bool
|
||||
IsPrimary bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// DashboardLink returns the user dashboard page link.
|
||||
func (u *User) DashboardLink() string {
|
||||
if u.IsOrganization() {
|
||||
@@ -95,12 +121,15 @@ func (u *User) HomeLink() string {
|
||||
|
||||
// AvatarLink returns user gravatar link.
|
||||
func (u *User) AvatarLink() string {
|
||||
if setting.DisableGravatar {
|
||||
switch {
|
||||
case u.UseCustomAvatar:
|
||||
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
||||
case setting.DisableGravatar:
|
||||
return setting.AppSubUrl + "/img/avatar_default.jpg"
|
||||
} else if setting.Service.EnableCacheAvatar {
|
||||
case setting.Service.EnableCacheAvatar:
|
||||
return setting.AppSubUrl + "/avatar/" + u.Avatar
|
||||
}
|
||||
return "//1.gravatar.com/avatar/" + u.Avatar
|
||||
return setting.GravatarSource + u.Avatar
|
||||
}
|
||||
|
||||
// NewGitSig generates and returns the signature of given user.
|
||||
@@ -125,6 +154,48 @@ func (u *User) ValidtePassword(passwd string) bool {
|
||||
return u.Passwd == newUser.Passwd
|
||||
}
|
||||
|
||||
// CustomAvatarPath returns user custom avatar file path.
|
||||
func (u *User) CustomAvatarPath() string {
|
||||
return filepath.Join(setting.AvatarUploadPath, com.ToStr(u.Id))
|
||||
}
|
||||
|
||||
// UploadAvatar saves custom avatar for user.
|
||||
// FIXME: split uploads to different subdirs in case we have massive users.
|
||||
func (u *User) UploadAvatar(data []byte) error {
|
||||
u.UseCustomAvatar = true
|
||||
|
||||
img, _, err := image.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m := resize.Resize(200, 200, img, resize.NearestNeighbor)
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Id(u.Id).AllCols().Update(u); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
os.MkdirAll(setting.AvatarUploadPath, os.ModePerm)
|
||||
fw, err := os.Create(u.CustomAvatarPath())
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
defer fw.Close()
|
||||
if err = jpeg.Encode(fw, m, nil); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// IsOrganization returns true if user is actually a organization.
|
||||
func (u *User) IsOrganization() bool {
|
||||
return u.Type == ORGANIZATION
|
||||
@@ -190,10 +261,13 @@ func IsEmailUsed(email string) (bool, error) {
|
||||
if len(email) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if has, err := x.Get(&EmailAddress{Email: email}); has || err != nil {
|
||||
return has, err
|
||||
}
|
||||
return x.Get(&User{Email: email})
|
||||
}
|
||||
|
||||
// GetUserSalt returns a user salt token
|
||||
// GetUserSalt returns a ramdom user salt token.
|
||||
func GetUserSalt() string {
|
||||
return base.GetRandomString(10)
|
||||
}
|
||||
@@ -219,8 +293,8 @@ func CreateUser(u *User) error {
|
||||
}
|
||||
|
||||
u.LowerName = strings.ToLower(u.Name)
|
||||
u.Avatar = base.EncodeMd5(u.Email)
|
||||
u.AvatarEmail = u.Email
|
||||
u.Avatar = avatar.HashEmail(u.AvatarEmail)
|
||||
u.Rands = GetUserSalt()
|
||||
u.Salt = GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
@@ -297,6 +371,25 @@ func VerifyUserActiveCode(code string) (user *User) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// verify active code when active account
|
||||
func VerifyActiveEmailCode(code, email string) *EmailAddress {
|
||||
minutes := setting.Service.ActiveCodeLives
|
||||
|
||||
if user := getVerifyUser(code); user != nil {
|
||||
// time limit code
|
||||
prefix := code[:base.TimeLimitCodeLength]
|
||||
data := com.ToStr(user.Id) + email + user.LowerName + user.Passwd + user.Rands
|
||||
|
||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||
emailAddress := &EmailAddress{Email: email}
|
||||
if has, _ := x.Get(emailAddress); has {
|
||||
return emailAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeUserName changes all corresponding setting from old user name to new one.
|
||||
func ChangeUserName(u *User, newUserName string) (err error) {
|
||||
if !IsLegalName(newUserName) {
|
||||
@@ -360,6 +453,13 @@ func ChangeUserName(u *User, newUserName string) (err error) {
|
||||
|
||||
// UpdateUser updates user's information.
|
||||
func UpdateUser(u *User) error {
|
||||
has, err := x.Where("id!=?", u.Id).And("type=?", INDIVIDUAL).And("email=?", u.Email).Get(new(User))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
return ErrEmailAlreadyUsed
|
||||
}
|
||||
|
||||
u.LowerName = strings.ToLower(u.Name)
|
||||
|
||||
if len(u.Location) > 255 {
|
||||
@@ -372,11 +472,17 @@ func UpdateUser(u *User) error {
|
||||
u.Description = u.Description[:255]
|
||||
}
|
||||
|
||||
_, err := x.Id(u.Id).AllCols().Update(u)
|
||||
if u.AvatarEmail == "" {
|
||||
u.AvatarEmail = u.Email
|
||||
}
|
||||
u.Avatar = avatar.HashEmail(u.AvatarEmail)
|
||||
|
||||
u.FullName = base.Sanitizer.Sanitize(u.FullName)
|
||||
_, err = x.Id(u.Id).AllCols().Update(u)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: need some kind of mechanism to record failure.
|
||||
// FIXME: need some kind of mechanism to record failure. HINT: system notice
|
||||
// DeleteUser completely and permanently deletes everything of user.
|
||||
func DeleteUser(u *User) error {
|
||||
// Check ownership of repository.
|
||||
@@ -390,13 +496,13 @@ func DeleteUser(u *User) error {
|
||||
// Check membership of organization.
|
||||
count, err = u.GetOrganizationCount()
|
||||
if err != nil {
|
||||
return errors.New("modesl.GetRepositories(GetOrganizationCount): " + err.Error())
|
||||
return errors.New("GetOrganizationCount: " + err.Error())
|
||||
} else if count > 0 {
|
||||
return ErrUserHasOrgs
|
||||
}
|
||||
|
||||
// TODO: check issues, other repos' commits
|
||||
// TODO: roll backable in some point.
|
||||
// FIXME: check issues, other repos' commits
|
||||
// FIXME: roll backable in some point.
|
||||
|
||||
// Delete all followers.
|
||||
if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil {
|
||||
@@ -418,6 +524,10 @@ func DeleteUser(u *User) error {
|
||||
if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
|
||||
return err
|
||||
}
|
||||
// Delete all alternative email addresses
|
||||
if _, err = x.Delete(&EmailAddress{Uid: u.Id}); err != nil {
|
||||
return err
|
||||
}
|
||||
// Delete all SSH keys.
|
||||
keys := make([]*PublicKey, 0, 10)
|
||||
if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
|
||||
@@ -438,9 +548,12 @@ func DeleteUser(u *User) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteInactivateUsers deletes all inactivate users.
|
||||
// DeleteInactivateUsers deletes all inactivate users and email addresses.
|
||||
func DeleteInactivateUsers() error {
|
||||
_, err := x.Where("is_active=?", false).Delete(new(User))
|
||||
if err == nil {
|
||||
_, err = x.Where("is_activated=?", false).Delete(new(EmailAddress))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -473,22 +586,22 @@ func GetUserById(id int64) (*User, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// GetUserByName returns the user object by given name if exists.
|
||||
// GetUserByName returns user by given name.
|
||||
func GetUserByName(name string) (*User, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
user := &User{LowerName: strings.ToLower(name)}
|
||||
has, err := x.Get(user)
|
||||
u := &User{LowerName: strings.ToLower(name)}
|
||||
has, err := x.Get(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
return user, nil
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// GetUserEmailsByNames returns a slice of e-mails corresponds to names.
|
||||
// GetUserEmailsByNames returns a list of e-mails corresponds to names.
|
||||
func GetUserEmailsByNames(names []string) []string {
|
||||
mails := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
@@ -514,43 +627,151 @@ func GetUserIdsByNames(names []string) []int64 {
|
||||
return ids
|
||||
}
|
||||
|
||||
// UserCommit represtns a commit with validation of user.
|
||||
// Get all email addresses
|
||||
func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
|
||||
emails := make([]*EmailAddress, 0, 5)
|
||||
err := x.Where("uid=?", uid).Find(&emails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err := GetUserById(uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isPrimaryFound := false
|
||||
|
||||
for _, email := range emails {
|
||||
if email.Email == u.Email {
|
||||
isPrimaryFound = true
|
||||
email.IsPrimary = true
|
||||
} else {
|
||||
email.IsPrimary = false
|
||||
}
|
||||
}
|
||||
|
||||
// We alway want the primary email address displayed, even if it's not in
|
||||
// the emailaddress table (yet)
|
||||
if !isPrimaryFound {
|
||||
emails = append(emails, &EmailAddress{Email: u.Email, IsActivated: true, IsPrimary: true})
|
||||
}
|
||||
return emails, nil
|
||||
}
|
||||
|
||||
func AddEmailAddress(email *EmailAddress) error {
|
||||
used, err := IsEmailUsed(email.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if used {
|
||||
return ErrEmailAlreadyUsed
|
||||
}
|
||||
|
||||
_, err = x.Insert(email)
|
||||
return err
|
||||
}
|
||||
|
||||
func (email *EmailAddress) Activate() error {
|
||||
email.IsActivated = true
|
||||
if _, err := x.Id(email.Id).AllCols().Update(email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if user, err := GetUserById(email.Uid); err != nil {
|
||||
return err
|
||||
} else {
|
||||
user.Rands = GetUserSalt()
|
||||
return UpdateUser(user)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteEmailAddress(email *EmailAddress) error {
|
||||
has, err := x.Get(email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrEmailNotExist
|
||||
}
|
||||
|
||||
if _, err = x.Delete(email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func MakeEmailPrimary(email *EmailAddress) error {
|
||||
has, err := x.Get(email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrEmailNotExist
|
||||
}
|
||||
|
||||
if !email.IsActivated {
|
||||
return ErrEmailNotActivated
|
||||
}
|
||||
|
||||
user := &User{Id: email.Uid}
|
||||
has, err = x.Get(user)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrUserNotExist
|
||||
}
|
||||
|
||||
// Make sure the former primary email doesn't disappear
|
||||
former_primary_email := &EmailAddress{Email: user.Email}
|
||||
has, err = x.Get(former_primary_email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
former_primary_email.Uid = user.Id
|
||||
former_primary_email.IsActivated = user.IsActive
|
||||
x.Insert(former_primary_email)
|
||||
}
|
||||
|
||||
user.Email = email.Email
|
||||
_, err = x.Id(user.Id).AllCols().Update(user)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UserCommit represents a commit with validation of user.
|
||||
type UserCommit struct {
|
||||
UserName string
|
||||
User *User
|
||||
*git.Commit
|
||||
}
|
||||
|
||||
// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
|
||||
func ValidateCommitWithEmail(c *git.Commit) (uname string) {
|
||||
func ValidateCommitWithEmail(c *git.Commit) *User {
|
||||
u, err := GetUserByEmail(c.Author.Email)
|
||||
if err == nil {
|
||||
uname = u.Name
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return uname
|
||||
return u
|
||||
}
|
||||
|
||||
// ValidateCommitsWithEmails checks if authors' e-mails of commits are corresponding to users.
|
||||
func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
|
||||
emails := map[string]string{}
|
||||
emails := map[string]*User{}
|
||||
newCommits := list.New()
|
||||
e := oldCommits.Front()
|
||||
for e != nil {
|
||||
c := e.Value.(*git.Commit)
|
||||
|
||||
uname := ""
|
||||
var u *User
|
||||
if v, ok := emails[c.Author.Email]; !ok {
|
||||
u, err := GetUserByEmail(c.Author.Email)
|
||||
if err == nil {
|
||||
uname = u.Name
|
||||
}
|
||||
emails[c.Author.Email] = uname
|
||||
u, _ = GetUserByEmail(c.Author.Email)
|
||||
emails[c.Author.Email] = u
|
||||
} else {
|
||||
uname = v
|
||||
u = v
|
||||
}
|
||||
|
||||
newCommits.PushBack(UserCommit{
|
||||
UserName: uname,
|
||||
Commit: c,
|
||||
User: u,
|
||||
Commit: c,
|
||||
})
|
||||
e = e.Next()
|
||||
}
|
||||
@@ -562,36 +783,42 @@ func GetUserByEmail(email string) (*User, error) {
|
||||
if len(email) == 0 {
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
// First try to find the user by primary email
|
||||
user := &User{Email: strings.ToLower(email)}
|
||||
has, err := x.Get(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
return user, nil
|
||||
if has {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Otherwise, check in alternative list for activated email addresses
|
||||
emailAddress := &EmailAddress{Email: strings.ToLower(email), IsActivated: true}
|
||||
has, err = x.Get(emailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
return GetUserById(emailAddress.Uid)
|
||||
}
|
||||
|
||||
return nil, ErrUserNotExist
|
||||
}
|
||||
|
||||
// SearchUserByName returns given number of users whose name contains keyword.
|
||||
func SearchUserByName(opt SearchOption) (us []*User, err error) {
|
||||
// Prevent SQL inject.
|
||||
opt.Keyword = strings.TrimSpace(opt.Keyword)
|
||||
if len(opt.Keyword) == 0 {
|
||||
return us, nil
|
||||
}
|
||||
|
||||
opt.Keyword = strings.Split(opt.Keyword, " ")[0]
|
||||
if len(opt.Keyword) == 0 {
|
||||
return us, nil
|
||||
}
|
||||
opt.Keyword = strings.ToLower(opt.Keyword)
|
||||
|
||||
us = make([]*User, 0, opt.Limit)
|
||||
err = x.Limit(opt.Limit).Where("type=0").And("lower_name like '%" + opt.Keyword + "%'").Find(&us)
|
||||
err = x.Limit(opt.Limit).Where("type=0").And("lower_name like ?", "%"+opt.Keyword+"%").Find(&us)
|
||||
return us, err
|
||||
}
|
||||
|
||||
// Follow is connection request for receiving user notifycation.
|
||||
// Follow is connection request for receiving user notification.
|
||||
type Follow struct {
|
||||
Id int64
|
||||
UserId int64 `xorm:"unique(follow)"`
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
@@ -27,6 +28,32 @@ const (
|
||||
FORM
|
||||
)
|
||||
|
||||
var hookContentTypes = map[string]HookContentType{
|
||||
"json": JSON,
|
||||
"form": FORM,
|
||||
}
|
||||
|
||||
// ToHookContentType returns HookContentType by given name.
|
||||
func ToHookContentType(name string) HookContentType {
|
||||
return hookContentTypes[name]
|
||||
}
|
||||
|
||||
func (t HookContentType) Name() string {
|
||||
switch t {
|
||||
case JSON:
|
||||
return "json"
|
||||
case FORM:
|
||||
return "form"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsValidHookContentType returns true if given name is a valid hook content type.
|
||||
func IsValidHookContentType(name string) bool {
|
||||
_, ok := hookContentTypes[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HookEvent represents events that will delivery hook.
|
||||
type HookEvent struct {
|
||||
PushOnly bool `json:"push_only"`
|
||||
@@ -46,6 +73,8 @@ type Webhook struct {
|
||||
HookTaskType HookTaskType
|
||||
Meta string `xorm:"TEXT"` // store hook-specific attributes
|
||||
OrgId int64
|
||||
Created time.Time `xorm:"CREATED"`
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
}
|
||||
|
||||
// GetEvent handles conversion from Events to HookEvent.
|
||||
@@ -71,7 +100,7 @@ func (w *Webhook) UpdateEvent() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// HasPushEvent returns true if hook enbaled push event.
|
||||
// HasPushEvent returns true if hook enabled push event.
|
||||
func (w *Webhook) HasPushEvent() bool {
|
||||
if w.PushOnly {
|
||||
return true
|
||||
@@ -147,12 +176,39 @@ const (
|
||||
SLACK
|
||||
)
|
||||
|
||||
var hookTaskTypes = map[string]HookTaskType{
|
||||
"gogs": GOGS,
|
||||
"slack": SLACK,
|
||||
}
|
||||
|
||||
// ToHookTaskType returns HookTaskType by given name.
|
||||
func ToHookTaskType(name string) HookTaskType {
|
||||
return hookTaskTypes[name]
|
||||
}
|
||||
|
||||
func (t HookTaskType) Name() string {
|
||||
switch t {
|
||||
case GOGS:
|
||||
return "gogs"
|
||||
case SLACK:
|
||||
return "slack"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsValidHookTaskType returns true if given name is a valid hook task type.
|
||||
func IsValidHookTaskType(name string) bool {
|
||||
_, ok := hookTaskTypes[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
type HookEventType string
|
||||
|
||||
const (
|
||||
PUSH HookEventType = "push"
|
||||
)
|
||||
|
||||
// FIXME: just use go-gogs-client structs maybe?
|
||||
type PayloadAuthor struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
@@ -252,13 +308,14 @@ func DeliverHooks() {
|
||||
defer func() { isShooting = false }()
|
||||
|
||||
tasks := make([]*HookTask, 0, 10)
|
||||
timeout := time.Duration(setting.WebhookDeliverTimeout) * time.Second
|
||||
timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
|
||||
x.Where("is_delivered=?", false).Iterate(new(HookTask),
|
||||
func(idx int, bean interface{}) error {
|
||||
t := bean.(*HookTask)
|
||||
req := httplib.Post(t.Url).SetTimeout(timeout, timeout).
|
||||
Header("X-Gogs-Delivery", t.Uuid).
|
||||
Header("X-Gogs-Event", string(t.EventType))
|
||||
Header("X-Gogs-Event", string(t.EventType)).
|
||||
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify})
|
||||
|
||||
switch t.ContentType {
|
||||
case JSON:
|
||||
@@ -274,7 +331,7 @@ func DeliverHooks() {
|
||||
case GOGS:
|
||||
{
|
||||
if _, err := req.Response(); err != nil {
|
||||
log.Error(4, "Delivery: %v", err)
|
||||
log.Error(5, "Delivery: %v", err)
|
||||
} else {
|
||||
t.IsSucceed = true
|
||||
}
|
||||
@@ -282,15 +339,15 @@ func DeliverHooks() {
|
||||
case SLACK:
|
||||
{
|
||||
if res, err := req.Response(); err != nil {
|
||||
log.Error(4, "Delivery: %v", err)
|
||||
log.Error(5, "Delivery: %v", err)
|
||||
} else {
|
||||
defer res.Body.Close()
|
||||
contents, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Error(4, "%s", err)
|
||||
log.Error(5, "%s", err)
|
||||
} else {
|
||||
if string(contents) != "ok" {
|
||||
log.Error(4, "slack failed with: %s", string(contents))
|
||||
log.Error(5, "slack failed with: %s", string(contents))
|
||||
} else {
|
||||
t.IsSucceed = true
|
||||
}
|
||||
|
||||
@@ -256,11 +256,11 @@ func ReadPacket(reader io.Reader) (*Packet, error) {
|
||||
}
|
||||
|
||||
func DecodeString(data []byte) (ret string) {
|
||||
for _, c := range data {
|
||||
ret += fmt.Sprintf("%c", c)
|
||||
}
|
||||
// for _, c := range data {
|
||||
// ret += fmt.Sprintf("%c", c)
|
||||
// }
|
||||
|
||||
return
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func DecodeInteger(data []byte) (ret uint64) {
|
||||
|
||||
@@ -6,22 +6,22 @@ package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/macaron-contrib/binding"
|
||||
)
|
||||
|
||||
type AdminEditUserForm struct {
|
||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||
Passwd string `form:"password"`
|
||||
Website string `form:"website" binding:"MaxSize(50)"`
|
||||
Location string `form:"location" binding:"MaxSize(50)"`
|
||||
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
||||
Active bool `form:"active"`
|
||||
Admin bool `form:"admin"`
|
||||
LoginType int `form:"login_type"`
|
||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||
Passwd string `form:"password"`
|
||||
Website string `form:"website" binding:"MaxSize(50)"`
|
||||
Location string `form:"location" binding:"MaxSize(50)"`
|
||||
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
||||
Active bool `form:"active"`
|
||||
Admin bool `form:"admin"`
|
||||
AllowGitHook bool `form:"allow_git_hook"`
|
||||
LoginType int `form:"login_type"`
|
||||
}
|
||||
|
||||
func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -8,31 +8,24 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
"github.com/macaron-contrib/binding"
|
||||
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
)
|
||||
|
||||
type MarkdownForm struct {
|
||||
Text string `form:"text" binding:"Required"`
|
||||
Text string `form:"text"`
|
||||
Mode string `form:"mode"`
|
||||
Context string `form:"context"`
|
||||
}
|
||||
|
||||
func (f *MarkdownForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validateApiReq(errs, ctx.Data, f, l)
|
||||
func (f *MarkdownForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validateApiReq(errs, ctx.Data, f)
|
||||
}
|
||||
|
||||
func validateApiReq(errs *binding.Errors, data map[string]interface{}, f interface{}, l i18n.Locale) {
|
||||
if errs.Count() == 0 {
|
||||
return
|
||||
} else if len(errs.Overall) > 0 {
|
||||
for _, err := range errs.Overall {
|
||||
log.Error(4, "%s: %v", reflect.TypeOf(f), err)
|
||||
}
|
||||
return
|
||||
func validateApiReq(errs binding.Errors, data map[string]interface{}, f auth.Form) binding.Errors {
|
||||
if errs.Len() == 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
data["HasError"] = true
|
||||
@@ -54,26 +47,27 @@ func validateApiReq(errs *binding.Errors, data map[string]interface{}, f interfa
|
||||
continue
|
||||
}
|
||||
|
||||
if err, ok := errs.Fields[field.Name]; ok {
|
||||
switch err {
|
||||
case binding.BindingRequireError:
|
||||
if errs[0].FieldNames[0] == field.Name {
|
||||
switch errs[0].Classification {
|
||||
case binding.ERR_REQUIRED:
|
||||
data["ErrorMsg"] = fieldName + " cannot be empty"
|
||||
case binding.BindingAlphaDashError:
|
||||
case binding.ERR_ALPHA_DASH:
|
||||
data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) characters"
|
||||
case binding.BindingAlphaDashDotError:
|
||||
case binding.ERR_ALPHA_DASH_DOT:
|
||||
data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) or dot characters"
|
||||
case binding.BindingMinSizeError:
|
||||
case binding.ERR_MIN_SIZE:
|
||||
data["ErrorMsg"] = fieldName + " must contain at least " + auth.GetMinSize(field) + " characters"
|
||||
case binding.BindingMaxSizeError:
|
||||
case binding.ERR_MAX_SIZE:
|
||||
data["ErrorMsg"] = fieldName + " must contain at most " + auth.GetMaxSize(field) + " characters"
|
||||
case binding.BindingEmailError:
|
||||
case binding.ERR_EMAIL:
|
||||
data["ErrorMsg"] = fieldName + " is not a valid e-mail address"
|
||||
case binding.BindingUrlError:
|
||||
case binding.ERR_URL:
|
||||
data["ErrorMsg"] = fieldName + " is not a valid URL"
|
||||
default:
|
||||
data["ErrorMsg"] = "Unknown error: " + err
|
||||
data["ErrorMsg"] = "Unknown error: " + errs[0].Classification
|
||||
}
|
||||
return
|
||||
return errs
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
@@ -9,32 +9,39 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/macaron-contrib/i18n"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/binding"
|
||||
"github.com/macaron-contrib/session"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/modules/uuid"
|
||||
)
|
||||
|
||||
// SignedInId returns the id of signed in user.
|
||||
func SignedInId(header http.Header, sess session.Store) int64 {
|
||||
func SignedInId(req *http.Request, sess session.Store) int64 {
|
||||
if !models.HasEngine {
|
||||
return 0
|
||||
}
|
||||
|
||||
if setting.Service.EnableReverseProxyAuth {
|
||||
webAuthUser := header.Get(setting.ReverseProxyAuthUser)
|
||||
if len(webAuthUser) > 0 {
|
||||
u, err := models.GetUserByName(webAuthUser)
|
||||
if err != nil {
|
||||
if err != models.ErrUserNotExist {
|
||||
log.Error(4, "GetUserByName: %v", err)
|
||||
// API calls need to check access token.
|
||||
if strings.HasPrefix(req.URL.Path, "/api/") {
|
||||
auHead := req.Header.Get("Authorization")
|
||||
if len(auHead) > 0 {
|
||||
auths := strings.Fields(auHead)
|
||||
if len(auths) == 2 && auths[0] == "token" {
|
||||
t, err := models.GetAccessTokenBySha(auths[1])
|
||||
if err != nil {
|
||||
if err != models.ErrAccessTokenNotExist {
|
||||
log.Error(4, "GetAccessTokenBySha: %v", err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
return t.Uid
|
||||
}
|
||||
return u.Id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,18 +62,82 @@ func SignedInId(header http.Header, sess session.Store) int64 {
|
||||
}
|
||||
|
||||
// SignedInUser returns the user object of signed user.
|
||||
func SignedInUser(header http.Header, sess session.Store) *models.User {
|
||||
uid := SignedInId(header, sess)
|
||||
// It returns a bool value to indicate whether user uses basic auth or not.
|
||||
func SignedInUser(req *http.Request, sess session.Store) (*models.User, bool) {
|
||||
if !models.HasEngine {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
uid := SignedInId(req, sess)
|
||||
|
||||
if uid <= 0 {
|
||||
return nil
|
||||
if setting.Service.EnableReverseProxyAuth {
|
||||
webAuthUser := req.Header.Get(setting.ReverseProxyAuthUser)
|
||||
if len(webAuthUser) > 0 {
|
||||
u, err := models.GetUserByName(webAuthUser)
|
||||
if err != nil {
|
||||
if err != models.ErrUserNotExist {
|
||||
log.Error(4, "GetUserByName: %v", err)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Check if enabled auto-registration.
|
||||
if setting.Service.EnableReverseProxyAutoRegister {
|
||||
u := &models.User{
|
||||
Name: webAuthUser,
|
||||
Email: uuid.NewV4().String() + "@localhost",
|
||||
Passwd: webAuthUser,
|
||||
IsActive: true,
|
||||
}
|
||||
if err = models.CreateUser(u); err != nil {
|
||||
// FIXME: should I create a system notice?
|
||||
log.Error(4, "CreateUser: %v", err)
|
||||
return nil, false
|
||||
} else {
|
||||
return u, false
|
||||
}
|
||||
}
|
||||
}
|
||||
return u, false
|
||||
}
|
||||
}
|
||||
|
||||
// Check with basic auth.
|
||||
baHead := req.Header.Get("Authorization")
|
||||
if len(baHead) > 0 {
|
||||
auths := strings.Fields(baHead)
|
||||
if len(auths) == 2 && auths[0] == "Basic" {
|
||||
uname, passwd, _ := base.BasicAuthDecode(auths[1])
|
||||
u, err := models.GetUserByName(uname)
|
||||
if err != nil {
|
||||
if err != models.ErrUserNotExist {
|
||||
log.Error(4, "GetUserByName: %v", err)
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if u.ValidtePassword(passwd) {
|
||||
return u, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
u, err := models.GetUserById(uid)
|
||||
if err != nil {
|
||||
log.Error(4, "GetUserById: %v", err)
|
||||
return nil
|
||||
return nil, false
|
||||
}
|
||||
return u
|
||||
return u, false
|
||||
}
|
||||
|
||||
type Form interface {
|
||||
binding.Validator
|
||||
}
|
||||
|
||||
func init() {
|
||||
binding.SetNameMapper(com.ToSnakeCase)
|
||||
}
|
||||
|
||||
// AssignForm assign form values back to the template data.
|
||||
@@ -86,6 +157,8 @@ func AssignForm(form interface{}, data map[string]interface{}) {
|
||||
// Allow ignored fields in the struct
|
||||
if fieldName == "-" {
|
||||
continue
|
||||
} else if len(fieldName) == 0 {
|
||||
fieldName = com.ToSnakeCase(field.Name)
|
||||
}
|
||||
|
||||
data[fieldName] = val.Field(i).Interface()
|
||||
@@ -109,14 +182,9 @@ func GetMaxSize(field reflect.StructField) string {
|
||||
return getSize(field, "MaxSize(")
|
||||
}
|
||||
|
||||
func validate(errs *binding.Errors, data map[string]interface{}, f interface{}, l i18n.Locale) {
|
||||
if errs.Count() == 0 {
|
||||
return
|
||||
} else if len(errs.Overall) > 0 {
|
||||
for _, err := range errs.Overall {
|
||||
log.Error(4, "%s: %v", reflect.TypeOf(f), err)
|
||||
}
|
||||
return
|
||||
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
|
||||
if errs.Len() == 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
data["HasError"] = true
|
||||
@@ -139,28 +207,29 @@ func validate(errs *binding.Errors, data map[string]interface{}, f interface{},
|
||||
continue
|
||||
}
|
||||
|
||||
if err, ok := errs.Fields[field.Name]; ok {
|
||||
if errs[0].FieldNames[0] == field.Name {
|
||||
data["Err_"+field.Name] = true
|
||||
trName := l.Tr("form." + field.Name)
|
||||
switch err {
|
||||
case binding.BindingRequireError:
|
||||
switch errs[0].Classification {
|
||||
case binding.ERR_REQUIRED:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.require_error")
|
||||
case binding.BindingAlphaDashError:
|
||||
case binding.ERR_ALPHA_DASH:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
|
||||
case binding.BindingAlphaDashDotError:
|
||||
case binding.ERR_ALPHA_DASH_DOT:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
|
||||
case binding.BindingMinSizeError:
|
||||
case binding.ERR_MIN_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
|
||||
case binding.BindingMaxSizeError:
|
||||
case binding.ERR_MAX_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
|
||||
case binding.BindingEmailError:
|
||||
case binding.ERR_EMAIL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.email_error")
|
||||
case binding.BindingUrlError:
|
||||
case binding.ERR_URL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.url_error")
|
||||
default:
|
||||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + err
|
||||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
|
||||
}
|
||||
return
|
||||
return errs
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/macaron-contrib/binding"
|
||||
)
|
||||
|
||||
type AuthenticationForm struct {
|
||||
@@ -31,6 +29,6 @@ type AuthenticationForm struct {
|
||||
AllowAutoRegister bool `form:"allowautoregister"`
|
||||
}
|
||||
|
||||
func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ type Ldapsource struct {
|
||||
Port int // port number
|
||||
UseSSL bool // Use SSL
|
||||
BaseDN string // Base DN
|
||||
Attributes string // Attribut to search
|
||||
Attributes string // Attribute to search
|
||||
Filter string // Query filter to validate entry
|
||||
MsAdSAFormat string // in the case of MS AD Simple Authen, the format to use (see: http://msdn.microsoft.com/en-us/library/cc223499.aspx)
|
||||
Enabled bool // if this source is disabled
|
||||
@@ -37,7 +37,7 @@ func AddSource(name string, host string, port int, usessl bool, basedn string, a
|
||||
Authensource = append(Authensource, ldaphost)
|
||||
}
|
||||
|
||||
//LoginUser : try to login an user to LDAP sources, return requested (attribut,true) if ok, ("",false) other wise
|
||||
//LoginUser : try to login an user to LDAP sources, return requested (attribute,true) if ok, ("",false) other wise
|
||||
//First match wins
|
||||
//Returns first attribute if exists
|
||||
func LoginUser(name, passwd string) (a string, r bool) {
|
||||
|
||||
@@ -6,9 +6,7 @@ package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/macaron-contrib/binding"
|
||||
)
|
||||
|
||||
// ________ .__ __ .__
|
||||
@@ -23,8 +21,8 @@ type CreateOrgForm struct {
|
||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type UpdateOrgSettingForm struct {
|
||||
@@ -37,8 +35,8 @@ type UpdateOrgSettingForm struct {
|
||||
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// ___________
|
||||
@@ -54,6 +52,6 @@ type CreateTeamForm struct {
|
||||
Permission string `form:"permission"`
|
||||
}
|
||||
|
||||
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
)
|
||||
|
||||
type AddSSHKeyForm struct {
|
||||
SSHTitle string `form:"title" binding:"Required"`
|
||||
Content string `form:"content" binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
}
|
||||
@@ -6,9 +6,7 @@ package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/macaron-contrib/binding"
|
||||
)
|
||||
|
||||
// _______________________________________ _________.______________________ _______________.___.
|
||||
@@ -23,13 +21,13 @@ type CreateRepoForm struct {
|
||||
RepoName string `form:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||
Private bool `form:"private"`
|
||||
Description string `form:"desc" binding:"MaxSize(255)"`
|
||||
AutoInit bool `form:"auto_init"`
|
||||
Gitignore string `form:"gitignore"`
|
||||
License string `form:"license"`
|
||||
InitReadme bool `form:"init_readme"`
|
||||
}
|
||||
|
||||
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type MigrateRepoForm struct {
|
||||
@@ -43,8 +41,8 @@ type MigrateRepoForm struct {
|
||||
Description string `form:"desc" binding:"MaxSize(255)"`
|
||||
}
|
||||
|
||||
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type RepoSettingForm struct {
|
||||
@@ -57,8 +55,8 @@ type RepoSettingForm struct {
|
||||
GoGet bool `form:"goget"`
|
||||
}
|
||||
|
||||
func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __ __ ___. .__ .__ __
|
||||
@@ -77,21 +75,20 @@ type NewWebhookForm struct {
|
||||
Active bool `form:"active"`
|
||||
}
|
||||
|
||||
func (f *NewWebhookForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *NewWebhookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type NewSlackHookForm struct {
|
||||
HookTaskType string `form:"hook_type" binding:"Required"`
|
||||
Domain string `form:"domain" binding:"Required`
|
||||
Token string `form:"token" binding:"Required"`
|
||||
PayloadUrl string `form:"payload_url" binding:"Required`
|
||||
Channel string `form:"channel" binding:"Required"`
|
||||
PushOnly bool `form:"push_only"`
|
||||
Active bool `form:"active"`
|
||||
}
|
||||
|
||||
func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// .___
|
||||
@@ -109,8 +106,8 @@ type CreateIssueForm struct {
|
||||
Content string `form:"content"`
|
||||
}
|
||||
|
||||
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// _____ .__.__ __
|
||||
@@ -126,8 +123,8 @@ type CreateMilestoneForm struct {
|
||||
Deadline string `form:"due_date"`
|
||||
}
|
||||
|
||||
func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// .____ ___. .__
|
||||
@@ -142,8 +139,8 @@ type CreateLabelForm struct {
|
||||
Color string `form:"color" binding:"Required;Size(7)"`
|
||||
}
|
||||
|
||||
func (f *CreateLabelForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *CreateLabelForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
@@ -162,18 +159,17 @@ type NewReleaseForm struct {
|
||||
Prerelease bool `form:"prerelease"`
|
||||
}
|
||||
|
||||
func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type EditReleaseForm struct {
|
||||
Target string `form:"tag_target" binding:"Required"`
|
||||
Title string `form:"title" binding:"Required"`
|
||||
Content string `form:"content" binding:"Required"`
|
||||
Draft string `form:"draft"`
|
||||
Prerelease bool `form:"prerelease"`
|
||||
}
|
||||
|
||||
func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -5,37 +5,38 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/i18n"
|
||||
"mime/multipart"
|
||||
|
||||
"github.com/gogits/gogs/modules/middleware/binding"
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/binding"
|
||||
)
|
||||
|
||||
type InstallForm struct {
|
||||
Database string `form:"database" binding:"Required"`
|
||||
DbHost string `form:"host"`
|
||||
DbUser string `form:"user"`
|
||||
DbPasswd string `form:"passwd"`
|
||||
DatabaseName string `form:"database_name"`
|
||||
SslMode string `form:"ssl_mode"`
|
||||
DatabasePath string `form:"database_path"`
|
||||
RepoRootPath string `form:"repo_path" binding:"Required"`
|
||||
RunUser string `form:"run_user" binding:"Required"`
|
||||
Domain string `form:"domain" binding:"Required"`
|
||||
AppUrl string `form:"app_url" binding:"Required"`
|
||||
SmtpHost string `form:"smtp_host"`
|
||||
SmtpEmail string `form:"mailer_user"`
|
||||
SmtpPasswd string `form:"mailer_pwd"`
|
||||
RegisterConfirm string `form:"register_confirm"`
|
||||
MailNotify string `form:"mail_notify"`
|
||||
AdminName string `form:"admin_name" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||
AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(255)"`
|
||||
ConfirmPasswd string `form:"confirm_passwd" binding:"Required;MinSize(6);MaxSize(255)"`
|
||||
AdminEmail string `form:"admin_email" binding:"Required;Email;MaxSize(50)"`
|
||||
DbType string `binding:"Required"`
|
||||
DbHost string
|
||||
DbUser string
|
||||
DbPasswd string
|
||||
DbName string
|
||||
SSLMode string
|
||||
DbPath string
|
||||
RepoRootPath string `binding:"Required"`
|
||||
RunUser string `binding:"Required"`
|
||||
Domain string `binding:"Required"`
|
||||
HTTPPort string `binding:"Required"`
|
||||
AppUrl string `binding:"Required"`
|
||||
SMTPHost string
|
||||
SMTPEmail string
|
||||
SMTPPasswd string
|
||||
RegisterConfirm string
|
||||
MailNotify string
|
||||
AdminName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||
AdminPasswd string `binding:"Required;MinSize(6);MaxSize(255)"`
|
||||
AdminConfirmPasswd string `binding:"Required;MinSize(6);MaxSize(255)"`
|
||||
AdminEmail string `binding:"Required;Email;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *InstallForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// _____ ____ _________________ ___
|
||||
@@ -54,8 +55,8 @@ type RegisterForm struct {
|
||||
LoginName string `form:"loginname"`
|
||||
}
|
||||
|
||||
func (f *RegisterForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *RegisterForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type SignInForm struct {
|
||||
@@ -64,8 +65,8 @@ type SignInForm struct {
|
||||
Remember bool `form:"remember"`
|
||||
}
|
||||
|
||||
func (f *SignInForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________________________________________.___ _______ ________ _________
|
||||
@@ -84,8 +85,25 @@ type UpdateProfileForm struct {
|
||||
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type UploadAvatarForm struct {
|
||||
Enable bool `form:"enable"`
|
||||
Avatar *multipart.FileHeader `form:"avatar"`
|
||||
}
|
||||
|
||||
func (f *UploadAvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type AddEmailForm struct {
|
||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type ChangePasswordForm struct {
|
||||
@@ -94,6 +112,23 @@ type ChangePasswordForm struct {
|
||||
Retype string `form:"retype"`
|
||||
}
|
||||
|
||||
func (f *ChangePasswordForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
|
||||
validate(errs, ctx.Data, f, l)
|
||||
func (f *ChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type AddSSHKeyForm struct {
|
||||
SSHTitle string `form:"title" binding:"Required"`
|
||||
Content string `form:"content" binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type NewAccessTokenForm struct {
|
||||
Name string `form:"name" binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *NewAccessTokenForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -33,17 +33,29 @@ import (
|
||||
"github.com/nfnt/resize"
|
||||
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
gravatar = "http://www.gravatar.com/avatar"
|
||||
)
|
||||
var gravatarSource string
|
||||
|
||||
func UpdateGravatarSource() {
|
||||
gravatarSource = setting.GravatarSource
|
||||
log.Debug("avatar.UpdateGravatarSource(gavatar source): %s", gravatarSource)
|
||||
if !strings.HasPrefix(gravatarSource, "http:") {
|
||||
gravatarSource = "http:" + gravatarSource
|
||||
log.Debug("avatar.UpdateGravatarSource(update gavatar source): %s", gravatarSource)
|
||||
}
|
||||
}
|
||||
|
||||
// hash email to md5 string
|
||||
// keep this func in order to make this package indenpent
|
||||
// keep this func in order to make this package independent
|
||||
func HashEmail(email string) string {
|
||||
// https://en.gravatar.com/site/implement/hash/
|
||||
email = strings.TrimSpace(email)
|
||||
email = strings.ToLower(email)
|
||||
|
||||
h := md5.New()
|
||||
h.Write([]byte(strings.ToLower(email)))
|
||||
h.Write([]byte(email))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
@@ -115,21 +127,23 @@ func (this *Avatar) Encode(wr io.Writer, size int) (err error) {
|
||||
if img, err = decodeImageFile(imgPath); err != nil {
|
||||
return
|
||||
}
|
||||
m := resize.Resize(uint(size), 0, img, resize.Lanczos3)
|
||||
m := resize.Resize(uint(size), 0, img, resize.NearestNeighbor)
|
||||
return jpeg.Encode(wr, m, nil)
|
||||
}
|
||||
|
||||
// get image from gravatar.com
|
||||
func (this *Avatar) Update() {
|
||||
thunder.Fetch(gravatar+"/"+this.Hash+"?"+this.reqParams,
|
||||
UpdateGravatarSource()
|
||||
thunder.Fetch(gravatarSource+this.Hash+"?"+this.reqParams,
|
||||
this.imagePath)
|
||||
}
|
||||
|
||||
func (this *Avatar) UpdateTimeout(timeout time.Duration) (err error) {
|
||||
UpdateGravatarSource()
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
err = fmt.Errorf("get gravatar image %s timeout", this.Hash)
|
||||
case err = <-thunder.GoFetch(gravatar+"/"+this.Hash+"?"+this.reqParams,
|
||||
case err = <-thunder.GoFetch(gravatarSource+this.Hash+"?"+this.reqParams,
|
||||
this.imagePath):
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
|
||||
package base
|
||||
|
||||
const DOC_URL = "http://gogs.io/docs"
|
||||
|
||||
type (
|
||||
TplName string
|
||||
|
||||
ApiJsonErr struct {
|
||||
Message string `json:"message"`
|
||||
DocUrl string `json:"documentation_url"`
|
||||
DocUrl string `json:"url"`
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -63,12 +63,18 @@ func IsImageFile(data []byte) (string, bool) {
|
||||
return contentType, false
|
||||
}
|
||||
|
||||
// IsReadmeFile returns true if given file name suppose to be a README file.
|
||||
func IsReadmeFile(name string) bool {
|
||||
name = strings.ToLower(name)
|
||||
if len(name) < 6 {
|
||||
return false
|
||||
} else if len(name) == 6 {
|
||||
if name == "readme" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if name[:6] == "readme" {
|
||||
if name[:7] == "readme." {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -91,11 +97,20 @@ func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte,
|
||||
options.Renderer.Link(out, link, title, content)
|
||||
}
|
||||
|
||||
func (options *CustomRender) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
|
||||
if len(link) > 0 && !isLink(link) {
|
||||
link = []byte(path.Join(strings.Replace(options.urlPrefix, "/src/", "/raw/", 1), string(link)))
|
||||
}
|
||||
|
||||
options.Renderer.Image(out, link, title, alt)
|
||||
}
|
||||
|
||||
var (
|
||||
MentionPattern = regexp.MustCompile(`@[0-9a-zA-Z_]{1,}`)
|
||||
commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueIndexPattern = regexp.MustCompile(`#[0-9]+`)
|
||||
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_]+`)
|
||||
commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueIndexPattern = regexp.MustCompile(`( |^)#[0-9]+`)
|
||||
sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`)
|
||||
)
|
||||
|
||||
func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte {
|
||||
@@ -113,8 +128,9 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte {
|
||||
if !inCodeBlock && !bytes.HasPrefix(line, tab) {
|
||||
ms := MentionPattern.FindAll(line, -1)
|
||||
for _, m := range ms {
|
||||
m = bytes.TrimSpace(m)
|
||||
line = bytes.Replace(line, m,
|
||||
[]byte(fmt.Sprintf(`<a href="%s/user/%s">%s</a>`, setting.AppSubUrl, m[1:], m)), -1)
|
||||
[]byte(fmt.Sprintf(`<a href="%s/%s">%s</a>`, setting.AppSubUrl, m[1:], m)), -1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,10 +161,25 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte {
|
||||
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(
|
||||
` <a href="%s">#%s</a>`, m, ShortSha(string(m[i+7:j])))), -1)
|
||||
}
|
||||
ms = issueIndexPattern.FindAll(rawBytes, -1)
|
||||
rawBytes = RenderIssueIndexPattern(rawBytes, urlPrefix)
|
||||
rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
|
||||
return rawBytes
|
||||
}
|
||||
|
||||
func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
|
||||
ms := sha1CurrentPattern.FindAll(rawBytes, -1)
|
||||
for _, m := range ms {
|
||||
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(
|
||||
`<a href="%s/issues/%s">%s</a>`, urlPrefix, m[1:], m)), -1)
|
||||
`<a href="%s/commit/%s"><code>%s</code></a>`, urlPrefix, m, ShortSha(string(m)))), -1)
|
||||
}
|
||||
return rawBytes
|
||||
}
|
||||
|
||||
func RenderIssueIndexPattern(rawBytes []byte, urlPrefix string) []byte {
|
||||
ms := issueIndexPattern.FindAll(rawBytes, -1)
|
||||
for _, m := range ms {
|
||||
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(`<a href="%s/issues/%s">%s</a>`,
|
||||
urlPrefix, strings.TrimPrefix(string(m[1:]), "#"), m)), -1)
|
||||
}
|
||||
return rawBytes
|
||||
}
|
||||
@@ -188,7 +219,7 @@ func RenderRawMarkdown(body []byte, urlPrefix string) []byte {
|
||||
func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte {
|
||||
body := RenderSpecialLink(rawBytes, urlPrefix)
|
||||
body = RenderRawMarkdown(body, urlPrefix)
|
||||
body = XSS(body)
|
||||
body = Sanitizer.SanitizeBytes(body)
|
||||
return body
|
||||
}
|
||||
|
||||
|
||||
@@ -5,23 +5,23 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogits/gogs/modules/mahonia"
|
||||
"golang.org/x/net/html/charset"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"github.com/gogits/chardet"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/saintfish/chardet"
|
||||
)
|
||||
|
||||
func Str2html(raw string) template.HTML {
|
||||
return template.HTML(raw)
|
||||
return template.HTML(Sanitizer.Sanitize(raw))
|
||||
}
|
||||
|
||||
func Range(l int) []int {
|
||||
@@ -48,22 +48,37 @@ func ShortSha(sha1 string) string {
|
||||
return sha1
|
||||
}
|
||||
|
||||
func ToUtf8WithErr(content []byte) (error, string) {
|
||||
func DetectEncoding(content []byte) (string, error) {
|
||||
detector := chardet.NewTextDetector()
|
||||
result, err := detector.DetectBest(content)
|
||||
return result.Charset, err
|
||||
}
|
||||
|
||||
func ToUtf8WithErr(content []byte) (error, string) {
|
||||
charsetLabel, err := DetectEncoding(content)
|
||||
if err != nil {
|
||||
return err, ""
|
||||
}
|
||||
|
||||
if result.Charset == "utf8" {
|
||||
if charsetLabel == "utf8" {
|
||||
return nil, string(content)
|
||||
}
|
||||
|
||||
decoder := mahonia.NewDecoder(result.Charset)
|
||||
if decoder != nil {
|
||||
return nil, decoder.ConvertString(string(content))
|
||||
encoding, _ := charset.Lookup(charsetLabel)
|
||||
|
||||
if encoding == nil {
|
||||
return fmt.Errorf("unknow char decoder %s", charsetLabel), string(content)
|
||||
}
|
||||
return errors.New("unknow char decoder"), string(content)
|
||||
|
||||
result, n, err := transform.String(encoding.NewDecoder(), string(content))
|
||||
|
||||
// If there is an error, we concatenate the nicely decoded part and the
|
||||
// original left over. This way we won't loose data.
|
||||
if err != nil {
|
||||
result = result + string(content[n:])
|
||||
}
|
||||
|
||||
return err, result
|
||||
}
|
||||
|
||||
func ToUtf8(content string) string {
|
||||
@@ -71,6 +86,11 @@ func ToUtf8(content string) string {
|
||||
return res
|
||||
}
|
||||
|
||||
// RenderCommitMessage renders commit message with XSS-safe and special links.
|
||||
func RenderCommitMessage(msg, urlPrefix string) template.HTML {
|
||||
return template.HTML(string(RenderIssueIndexPattern([]byte(template.HTMLEscapeString(msg)), urlPrefix)))
|
||||
}
|
||||
|
||||
var mailDomains = map[string]string{
|
||||
"gmail.com": "gmail.com",
|
||||
}
|
||||
@@ -98,7 +118,6 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
|
||||
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
|
||||
},
|
||||
"AvatarLink": AvatarLink,
|
||||
"str2html": Str2html, // TODO: Legacy
|
||||
"Str2html": Str2html,
|
||||
"TimeSince": TimeSince,
|
||||
"FileSize": FileSize,
|
||||
@@ -107,12 +126,11 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
|
||||
return a + b
|
||||
},
|
||||
"ActionIcon": ActionIcon,
|
||||
"ActionDesc": ActionDesc,
|
||||
"DateFormat": DateFormat,
|
||||
"List": List,
|
||||
"Mail2Domain": func(mail string) string {
|
||||
if !strings.Contains(mail, "@") {
|
||||
return "try.gogits.org"
|
||||
return "try.gogs.io"
|
||||
}
|
||||
|
||||
suffix := strings.SplitN(mail, "@", 2)[1]
|
||||
@@ -123,7 +141,17 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
|
||||
return domain
|
||||
},
|
||||
"SubStr": func(str string, start, length int) string {
|
||||
return str[start : start+length]
|
||||
if len(str) == 0 {
|
||||
return ""
|
||||
}
|
||||
end := start + length
|
||||
if length == -1 {
|
||||
end = len(str)
|
||||
}
|
||||
if len(str) < end {
|
||||
return str
|
||||
}
|
||||
return str[start:end]
|
||||
},
|
||||
"DiffTypeToStr": DiffTypeToStr,
|
||||
"DiffLineTypeToStr": DiffLineTypeToStr,
|
||||
@@ -133,6 +161,10 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
|
||||
"Oauth2Icon": Oauth2Icon,
|
||||
"Oauth2Name": Oauth2Name,
|
||||
"ToUtf8": ToUtf8,
|
||||
"EscapePound": func(str string) string {
|
||||
return strings.Replace(str, "#", "%23", -1)
|
||||
},
|
||||
"RenderCommitMessage": RenderCommitMessage,
|
||||
}
|
||||
|
||||
type Actioner interface {
|
||||
@@ -162,19 +194,6 @@ func ActionIcon(opType int) string {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Legacy
|
||||
const (
|
||||
TPL_CREATE_REPO = `<a href="%s/user/%s">%s</a> created repository <a href="%s">%s</a>`
|
||||
TPL_COMMIT_REPO = `<a href="%s/user/%s">%s</a> pushed to <a href="%s/src/%s">%s</a> at <a href="%s">%s</a>%s`
|
||||
TPL_COMMIT_REPO_LI = `<div><img src="%s?s=16" alt="user-avatar"/> <a href="%s/commit/%s" rel="nofollow">%s</a> %s</div>`
|
||||
TPL_CREATE_ISSUE = `<a href="%s/user/%s">%s</a> opened issue <a href="%s/issues/%s">%s#%s</a>
|
||||
<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
|
||||
TPL_TRANSFER_REPO = `<a href="%s/user/%s">%s</a> transfered repository <code>%s</code> to <a href="%s">%s</a>`
|
||||
TPL_PUSH_TAG = `<a href="%s/user/%s">%s</a> pushed tag <a href="%s/src/%s" rel="nofollow">%s</a> at <a href="%s">%s</a>`
|
||||
TPL_COMMENT_ISSUE = `<a href="%s/user/%s">%s</a> commented on issue <a href="%s/issues/%s">%s#%s</a>
|
||||
<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
|
||||
)
|
||||
|
||||
type PushCommit struct {
|
||||
Sha1 string
|
||||
Message string
|
||||
@@ -183,8 +202,9 @@ type PushCommit struct {
|
||||
}
|
||||
|
||||
type PushCommits struct {
|
||||
Len int
|
||||
Commits []*PushCommit
|
||||
Len int
|
||||
Commits []*PushCommit
|
||||
CompareUrl string
|
||||
}
|
||||
|
||||
func ActionContent2Commits(act Actioner) *PushCommits {
|
||||
@@ -195,52 +215,6 @@ func ActionContent2Commits(act Actioner) *PushCommits {
|
||||
return push
|
||||
}
|
||||
|
||||
// FIXME: Legacy
|
||||
// ActionDesc accepts int that represents action operation type
|
||||
// and returns the description.
|
||||
func ActionDesc(act Actioner) string {
|
||||
actUserName := act.GetActUserName()
|
||||
email := act.GetActEmail()
|
||||
repoUserName := act.GetRepoUserName()
|
||||
repoName := act.GetRepoName()
|
||||
repoLink := repoUserName + "/" + repoName
|
||||
branch := act.GetBranch()
|
||||
content := act.GetContent()
|
||||
switch act.GetOpType() {
|
||||
case 1: // Create repository.
|
||||
return fmt.Sprintf(TPL_CREATE_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, repoName)
|
||||
case 5: // Commit repository.
|
||||
var push *PushCommits
|
||||
if err := json.Unmarshal([]byte(content), &push); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
buf := bytes.NewBuffer([]byte("\n"))
|
||||
for _, commit := range push.Commits {
|
||||
buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, AvatarLink(commit.AuthorEmail), repoLink, commit.Sha1, commit.Sha1[:7], commit.Message) + "\n")
|
||||
}
|
||||
if push.Len > 3 {
|
||||
buf.WriteString(fmt.Sprintf(`<div><a href="{{AppRootSubUrl}}/%s/%s/commits/%s" rel="nofollow">%d other commits >></a></div>`, actUserName, repoName, branch, push.Len))
|
||||
}
|
||||
return fmt.Sprintf(TPL_COMMIT_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink,
|
||||
buf.String())
|
||||
case 6: // Create issue.
|
||||
infos := strings.SplitN(content, "|", 2)
|
||||
return fmt.Sprintf(TPL_CREATE_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
|
||||
AvatarLink(email), infos[1])
|
||||
case 8: // Transfer repository.
|
||||
newRepoLink := content + "/" + repoName
|
||||
return fmt.Sprintf(TPL_TRANSFER_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, newRepoLink, newRepoLink)
|
||||
case 9: // Push tag.
|
||||
return fmt.Sprintf(TPL_PUSH_TAG, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink)
|
||||
case 10: // Comment issue.
|
||||
infos := strings.SplitN(content, "|", 2)
|
||||
return fmt.Sprintf(TPL_COMMENT_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
|
||||
AvatarLink(email), infos[1])
|
||||
default:
|
||||
return "invalid type"
|
||||
}
|
||||
}
|
||||
|
||||
func DiffTypeToStr(diffType int) string {
|
||||
diffTypes := map[int]string{
|
||||
1: "add", 2: "modify", 3: "del",
|
||||
|
||||
@@ -9,28 +9,53 @@ import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
"html/template"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
|
||||
"github.com/gogits/gogs/modules/avatar"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
// Encode string to md5 hex value
|
||||
var Sanitizer = bluemonday.UGCPolicy()
|
||||
|
||||
// Encode string to md5 hex value.
|
||||
func EncodeMd5(str string) string {
|
||||
m := md5.New()
|
||||
m.Write([]byte(str))
|
||||
return hex.EncodeToString(m.Sum(nil))
|
||||
}
|
||||
|
||||
// Encode string to sha1 hex value.
|
||||
func EncodeSha1(str string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func BasicAuthDecode(encoded string) (string, string, error) {
|
||||
s, err := base64.StdEncoding.DecodeString(encoded)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
auth := strings.SplitN(string(s), ":", 2)
|
||||
return auth[0], auth[1], nil
|
||||
}
|
||||
|
||||
func BasicAuthEncode(username, password string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
|
||||
}
|
||||
|
||||
// GetRandomString generate random string by specify chars.
|
||||
func GetRandomString(n int, alphabets ...byte) string {
|
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
@@ -148,10 +173,13 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string
|
||||
func AvatarLink(email string) string {
|
||||
if setting.DisableGravatar {
|
||||
return setting.AppSubUrl + "/img/avatar_default.jpg"
|
||||
} else if setting.Service.EnableCacheAvatar {
|
||||
return setting.AppSubUrl + "/avatar/" + EncodeMd5(email)
|
||||
}
|
||||
return "//1.gravatar.com/avatar/" + EncodeMd5(email)
|
||||
|
||||
gravatarHash := avatar.HashEmail(email)
|
||||
if setting.Service.EnableCacheAvatar {
|
||||
return setting.AppSubUrl + "/avatar/" + gravatarHash
|
||||
}
|
||||
return setting.GravatarSource + gravatarHash
|
||||
}
|
||||
|
||||
// Seconds-based time units
|
||||
@@ -447,29 +475,3 @@ func DateFormat(t time.Time, format string) string {
|
||||
format = replacer.Replace(format)
|
||||
return t.Format(format)
|
||||
}
|
||||
|
||||
type xssFilter struct {
|
||||
reg *regexp.Regexp
|
||||
repl []byte
|
||||
}
|
||||
|
||||
var (
|
||||
whiteSpace = []byte(" ")
|
||||
xssFilters = []xssFilter{
|
||||
{regexp.MustCompile(`\ [ONon]\w*=["]*`), whiteSpace},
|
||||
{regexp.MustCompile(`<[SCRIPTscript]{6}`), whiteSpace},
|
||||
{regexp.MustCompile(`=[` + "`" + `'"]*[JAVASCRIPTjavascript \t\0
]*:`), whiteSpace},
|
||||
}
|
||||
)
|
||||
|
||||
// XSS goes through all the XSS filters to make user input content as safe as possible.
|
||||
func XSS(in []byte) []byte {
|
||||
for _, filter := range xssFilters {
|
||||
in = filter.reg.ReplaceAll(in, filter.repl)
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func XSSString(in string) string {
|
||||
return string(XSS([]byte(in)))
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ Callers may register Funcs to be invoked on a given schedule. Cron will run
|
||||
them in their own goroutines.
|
||||
|
||||
c := cron.New()
|
||||
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
||||
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
|
||||
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
|
||||
c.AddFunc("Every hour on the half hour","0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
||||
c.AddFunc("Every hour","@hourly", func() { fmt.Println("Every hour") })
|
||||
c.AddFunc("Every hour and a half","@every 1h30m", func() { fmt.Println("Every hour thirty") })
|
||||
c.Start()
|
||||
..
|
||||
// Funcs are invoked in their own goroutine, asynchronously.
|
||||
|
||||
@@ -15,7 +15,10 @@ var c = New()
|
||||
|
||||
func NewCronContext() {
|
||||
c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate)
|
||||
c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.WebhookTaskInterval), models.DeliverHooks)
|
||||
c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.Webhook.TaskInterval), models.DeliverHooks)
|
||||
if setting.Git.Fsck.Enable {
|
||||
c.AddFunc("Repository health check", fmt.Sprintf("@every %dh", setting.Git.Fsck.Interval), models.GitFsck)
|
||||
}
|
||||
c.Start()
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func (h *Hook) Update() error {
|
||||
if len(strings.TrimSpace(h.Content)) == 0 {
|
||||
return os.Remove(h.path)
|
||||
}
|
||||
return ioutil.WriteFile(h.path, []byte(h.Content), os.ModePerm)
|
||||
return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
|
||||
}
|
||||
|
||||
// ListHooks returns a list of Git hooks of given repository.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package httplib
|
||||
|
||||
// NOTE: last sync c07b1d8 on Aug 23, 2014.
|
||||
// NOTE: last sync 57e62e5 on Oct 29, 2014.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -252,35 +253,36 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
||||
} else {
|
||||
b.url = b.url + "?" + paramBody
|
||||
}
|
||||
} else if b.req.Method == "POST" && b.req.Body == nil && len(paramBody) > 0 {
|
||||
} else if b.req.Method == "POST" && b.req.Body == nil {
|
||||
if len(b.files) > 0 {
|
||||
bodyBuf := &bytes.Buffer{}
|
||||
bodyWriter := multipart.NewWriter(bodyBuf)
|
||||
for formname, filename := range b.files {
|
||||
fileWriter, err := bodyWriter.CreateFormFile(formname, filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
pr, pw := io.Pipe()
|
||||
bodyWriter := multipart.NewWriter(pw)
|
||||
go func() {
|
||||
for formname, filename := range b.files {
|
||||
fileWriter, err := bodyWriter.CreateFormFile(formname, filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fh, err := os.Open(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
//iocopy
|
||||
_, err = io.Copy(fileWriter, fh)
|
||||
fh.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
fh, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for k, v := range b.params {
|
||||
bodyWriter.WriteField(k, v)
|
||||
}
|
||||
//iocopy
|
||||
_, err = io.Copy(fileWriter, fh)
|
||||
fh.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for k, v := range b.params {
|
||||
bodyWriter.WriteField(k, v)
|
||||
}
|
||||
contentType := bodyWriter.FormDataContentType()
|
||||
bodyWriter.Close()
|
||||
b.Header("Content-Type", contentType)
|
||||
b.req.Body = ioutil.NopCloser(bodyBuf)
|
||||
b.req.ContentLength = int64(bodyBuf.Len())
|
||||
} else {
|
||||
bodyWriter.Close()
|
||||
pw.Close()
|
||||
}()
|
||||
b.Header("Content-Type", bodyWriter.FormDataContentType())
|
||||
b.req.Body = ioutil.NopCloser(pr)
|
||||
} else if len(paramBody) > 0 {
|
||||
b.Header("Content-Type", "application/x-www-form-urlencoded")
|
||||
b.Body(paramBody)
|
||||
}
|
||||
@@ -332,7 +334,7 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
||||
Jar: jar,
|
||||
}
|
||||
|
||||
if b.setting.UserAgent != "" {
|
||||
if len(b.setting.UserAgent) > 0 && len(b.req.Header.Get("User-Agent")) == 0 {
|
||||
b.req.Header.Set("User-Agent", b.setting.UserAgent)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,23 +57,23 @@ func TestSimplePost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostFile(t *testing.T) {
|
||||
v := "smallfish"
|
||||
req := Post("http://httpbin.org/post")
|
||||
req.Param("username", v)
|
||||
req.PostFile("uploadfile", "httplib_test.go")
|
||||
// func TestPostFile(t *testing.T) {
|
||||
// v := "smallfish"
|
||||
// req := Post("http://httpbin.org/post")
|
||||
// req.Param("username", v)
|
||||
// req.PostFile("uploadfile", "httplib_test.go")
|
||||
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
// str, err := req.String()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// t.Log(str)
|
||||
|
||||
n := strings.Index(str, v)
|
||||
if n == -1 {
|
||||
t.Fatal(v + " not found in post")
|
||||
}
|
||||
}
|
||||
// n := strings.Index(str, v)
|
||||
// if n == -1 {
|
||||
// t.Fatal(v + " not found in post")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestSimplePut(t *testing.T) {
|
||||
str, err := Put("http://httpbin.org/put").String()
|
||||
@@ -194,3 +194,13 @@ func TestToFile(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeader(t *testing.T) {
|
||||
req := Get("http://httpbin.org/headers")
|
||||
req.Header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36")
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/asn1-ber"
|
||||
)
|
||||
|
||||
// debbuging type
|
||||
// debugging type
|
||||
// - has a Printf method to write the debug output
|
||||
type debugging bool
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ func newLogger(buffer int64) *Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
// SetLogger sets new logger instanse with given logger adapter and config.
|
||||
// SetLogger sets new logger instance with given logger adapter and config.
|
||||
func (l *Logger) SetLogger(adapter string, config string) error {
|
||||
l.lock.Lock()
|
||||
defer l.lock.Unlock()
|
||||
|
||||
@@ -1,844 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Converters for simple 8-bit character sets.
|
||||
|
||||
type eightBitInfo struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
|
||||
// the character used for characters that can't be converted
|
||||
SubstitutionChar byte
|
||||
|
||||
// a string containing all 256 characters, in order.
|
||||
Repertoire string
|
||||
|
||||
// used to synchronize unpacking Repertoire into the conversion tables
|
||||
once *sync.Once
|
||||
|
||||
// true if the first 128 characters are the same as US-ASCII
|
||||
asciiCompatible bool
|
||||
|
||||
byte2char [256]rune
|
||||
char2byte map[rune]byte
|
||||
}
|
||||
|
||||
const asciiRepertoire = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"
|
||||
|
||||
func (info *eightBitInfo) register() {
|
||||
var cs Charset
|
||||
cs.Name = info.Name
|
||||
cs.Aliases = info.Aliases
|
||||
|
||||
info.once = new(sync.Once)
|
||||
|
||||
cs.NewDecoder = func() Decoder {
|
||||
info.once.Do(func() { info.unpack() })
|
||||
|
||||
return func(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
c = info.byte2char[p[0]]
|
||||
|
||||
if c == 0xfffd {
|
||||
status = INVALID_CHAR
|
||||
} else {
|
||||
status = SUCCESS
|
||||
}
|
||||
|
||||
size = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cs.NewEncoder = func() Encoder {
|
||||
info.once.Do(func() { info.unpack() })
|
||||
|
||||
return func(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if c < 128 && info.asciiCompatible {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
b, ok := info.char2byte[c]
|
||||
if !ok {
|
||||
b = info.SubstitutionChar
|
||||
status = INVALID_CHAR
|
||||
} else {
|
||||
status = SUCCESS
|
||||
}
|
||||
p[0] = b
|
||||
size = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
RegisterCharset(&cs)
|
||||
}
|
||||
|
||||
func (info *eightBitInfo) unpack() {
|
||||
info.asciiCompatible = info.Repertoire[:128] == asciiRepertoire
|
||||
|
||||
info.char2byte = make(map[rune]byte, 256)
|
||||
i := 0
|
||||
for _, c := range info.Repertoire {
|
||||
info.byte2char[i] = c
|
||||
if c != 0xfffd {
|
||||
info.char2byte[c] = byte(i)
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i != 256 {
|
||||
panic(fmt.Errorf("%s has only %d characters", info.Name, i))
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
for i := 0; i < len(eightBitCharsets); i++ {
|
||||
eightBitCharsets[i].register()
|
||||
}
|
||||
}
|
||||
|
||||
var eightBitCharsets = []eightBitInfo{
|
||||
{
|
||||
Name: "ISO-8859-2",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0104\u02d8\u0141\u00a4\u013d\u015a\u00a7\u00a8\u0160\u015e\u0164\u0179\u00ad\u017d\u017b\u00b0\u0105\u02db\u0142\u00b4\u013e\u015b\u02c7\u00b8\u0161\u015f\u0165\u017a\u02dd\u017e\u017c\u0154\u00c1\u00c2\u0102\u00c4\u0139\u0106\u00c7\u010c\u00c9\u0118\u00cb\u011a\u00cd\u00ce\u010e\u0110\u0143\u0147\u00d3\u00d4\u0150\u00d6\u00d7\u0158\u016e\u00da\u0170\u00dc\u00dd\u0162\u00df\u0155\u00e1\u00e2\u0103\u00e4\u013a\u0107\u00e7\u010d\u00e9\u0119\u00eb\u011b\u00ed\u00ee\u010f\u0111\u0144\u0148\u00f3\u00f4\u0151\u00f6\u00f7\u0159\u016f\u00fa\u0171\u00fc\u00fd\u0163\u02d9",
|
||||
Aliases: []string{"ISO_8859-2:1987", "iso-ir-101", "latin2", "l2", "csISOLatin2"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-3",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0126\u02d8\u00a3\u00a4\ufffd\u0124\u00a7\u00a8\u0130\u015e\u011e\u0134\u00ad\ufffd\u017b\u00b0\u0127\u00b2\u00b3\u00b4\u00b5\u0125\u00b7\u00b8\u0131\u015f\u011f\u0135\u00bd\ufffd\u017c\u00c0\u00c1\u00c2\ufffd\u00c4\u010a\u0108\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\ufffd\u00d1\u00d2\u00d3\u00d4\u0120\u00d6\u00d7\u011c\u00d9\u00da\u00db\u00dc\u016c\u015c\u00df\u00e0\u00e1\u00e2\ufffd\u00e4\u010b\u0109\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\ufffd\u00f1\u00f2\u00f3\u00f4\u0121\u00f6\u00f7\u011d\u00f9\u00fa\u00fb\u00fc\u016d\u015d\u02d9",
|
||||
Aliases: []string{"ISO_8859-3:1988", "iso-ir-109", "latin3", "l3", "csISOLatin3"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-4",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0104\u0138\u0156\u00a4\u0128\u013b\u00a7\u00a8\u0160\u0112\u0122\u0166\u00ad\u017d\u00af\u00b0\u0105\u02db\u0157\u00b4\u0129\u013c\u02c7\u00b8\u0161\u0113\u0123\u0167\u014a\u017e\u014b\u0100\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u012e\u010c\u00c9\u0118\u00cb\u0116\u00cd\u00ce\u012a\u0110\u0145\u014c\u0136\u00d4\u00d5\u00d6\u00d7\u00d8\u0172\u00da\u00db\u00dc\u0168\u016a\u00df\u0101\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u012f\u010d\u00e9\u0119\u00eb\u0117\u00ed\u00ee\u012b\u0111\u0146\u014d\u0137\u00f4\u00f5\u00f6\u00f7\u00f8\u0173\u00fa\u00fb\u00fc\u0169\u016b\u02d9",
|
||||
Aliases: []string{"ISO_8859-4:1988", "iso-ir-110", "latin4", "l4", "csISOLatin4"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-5",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408\u0409\u040a\u040b\u040c\u00ad\u040e\u040f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u2116\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u00a7\u045e\u045f",
|
||||
Aliases: []string{"ISO_8859-5:1988", "iso-ir-144", "cyrillic", "csISOLatinCyrillic"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-6",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\ufffd\ufffd\ufffd\u00a4\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u060c\u00ad\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u061b\ufffd\ufffd\ufffd\u061f\ufffd\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063a\ufffd\ufffd\ufffd\ufffd\ufffd\u0640\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064a\u064b\u064c\u064d\u064e\u064f\u0650\u0651\u0652\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd",
|
||||
Aliases: []string{"ISO_8859-6:1987", "iso-ir-127", "ECMA-114", "ASMO-708", "arabic", "csISOLatinArabic"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-7",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u2018\u2019\u00a3\u20ac\u20af\u00a6\u00a7\u00a8\u00a9\u037a\u00ab\u00ac\u00ad\ufffd\u2015\u00b0\u00b1\u00b2\u00b3\u0384\u0385\u0386\u00b7\u0388\u0389\u038a\u00bb\u038c\u00bd\u038e\u038f\u0390\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\ufffd\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\ufffd",
|
||||
Aliases: []string{"ISO_8859-7:2003", "iso-ir-126", "ELOT_928", "ECMA-118", "greek", "greek8", "csISOLatinGreek"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-8",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\ufffd\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00d7\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00f7\u00bb\u00bc\u00bd\u00be\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u2017\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\ufffd\u200e\u200f\ufffd",
|
||||
Aliases: []string{"ISO_8859-8:1999", "iso-ir-138", "hebrew", "csISOLatinHebrew"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-9",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u011e\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u0130\u015e\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u011f\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u0131\u015f\u00ff",
|
||||
Aliases: []string{"ISO_8859-9:1999", "iso-ir-148", "latin5", "l5", "csISOLatin5"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-10",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0104\u0112\u0122\u012a\u0128\u0136\u00a7\u013b\u0110\u0160\u0166\u017d\u00ad\u016a\u014a\u00b0\u0105\u0113\u0123\u012b\u0129\u0137\u00b7\u013c\u0111\u0161\u0167\u017e\u2015\u016b\u014b\u0100\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u012e\u010c\u00c9\u0118\u00cb\u0116\u00cd\u00ce\u00cf\u00d0\u0145\u014c\u00d3\u00d4\u00d5\u00d6\u0168\u00d8\u0172\u00da\u00db\u00dc\u00dd\u00de\u00df\u0101\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u012f\u010d\u00e9\u0119\u00eb\u0117\u00ed\u00ee\u00ef\u00f0\u0146\u014d\u00f3\u00f4\u00f5\u00f6\u0169\u00f8\u0173\u00fa\u00fb\u00fc\u00fd\u00fe\u0138",
|
||||
Aliases: []string{"iso_8859-10:1992", "l6", "iso-ir-157", "latin6", "csISOLatin6"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-11",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\ufffd\ufffd\ufffd\ufffd\u0e3f\u0e40\u0e41\u0e42\u0e43\u0e44\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a\u0e4b\u0e4c\u0e4d\u0e4e\u0e4f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e5a\u0e5b\ufffd\ufffd\ufffd\ufffd",
|
||||
Aliases: []string{"iso_8859-11:2001", "Latin/Thai", "TIS-620"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-13",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u201d\u00a2\u00a3\u00a4\u201e\u00a6\u00a7\u00d8\u00a9\u0156\u00ab\u00ac\u00ad\u00ae\u00c6\u00b0\u00b1\u00b2\u00b3\u201c\u00b5\u00b6\u00b7\u00f8\u00b9\u0157\u00bb\u00bc\u00bd\u00be\u00e6\u0104\u012e\u0100\u0106\u00c4\u00c5\u0118\u0112\u010c\u00c9\u0179\u0116\u0122\u0136\u012a\u013b\u0160\u0143\u0145\u00d3\u014c\u00d5\u00d6\u00d7\u0172\u0141\u015a\u016a\u00dc\u017b\u017d\u00df\u0105\u012f\u0101\u0107\u00e4\u00e5\u0119\u0113\u010d\u00e9\u017a\u0117\u0123\u0137\u012b\u013c\u0161\u0144\u0146\u00f3\u014d\u00f5\u00f6\u00f7\u0173\u0142\u015b\u016b\u00fc\u017c\u017e\u2019",
|
||||
Aliases: []string{"latin7", "Baltic Rim"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-14",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u1e02\u1e03\u00a3\u010a\u010b\u1e0a\u00a7\u1e80\u00a9\u1e82\u1e0b\u1ef2\u00ad\u00ae\u0178\u1e1e\u1e1f\u0120\u0121\u1e40\u1e41\u00b6\u1e56\u1e81\u1e57\u1e83\u1e60\u1ef3\u1e84\u1e85\u1e61\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0174\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u1e6a\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u0176\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u0175\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u1e6b\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u0177\u00ff",
|
||||
Aliases: []string{"iso-ir-199", "ISO_8859-14:1998", "latin8", "iso-celtic", "l8"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-15",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u00a1\u00a2\u00a3\u20ac\u00a5\u0160\u00a7\u0161\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u017d\u00b5\u00b6\u00b7\u017e\u00b9\u00ba\u00bb\u0152\u0153\u0178\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff",
|
||||
Aliases: []string{"Latin-9"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-16",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0104\u0105\u0141\u20ac\u201e\u0160\u00a7\u0161\u00a9\u0218\u00ab\u0179\u00ad\u017a\u017b\u00b0\u00b1\u010c\u0142\u017d\u201d\u00b6\u00b7\u017e\u010d\u0219\u00bb\u0152\u0153\u0178\u017c\u00c0\u00c1\u00c2\u0102\u00c4\u0106\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0110\u0143\u00d2\u00d3\u00d4\u0150\u00d6\u015a\u0170\u00d9\u00da\u00db\u00dc\u0118\u021a\u00df\u00e0\u00e1\u00e2\u0103\u00e4\u0107\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u0111\u0144\u00f2\u00f3\u00f4\u0151\u00f6\u015b\u0171\u00f9\u00fa\u00fb\u00fc\u0119\u021b\u00ff",
|
||||
Aliases: []string{"iso-ir-226", "ISO_8859-16:2001", "latin10", "l10"},
|
||||
},
|
||||
{
|
||||
Name: "macos-0_2-10.2",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c4\u00c5\u00c7\u00c9\u00d1\u00d6\u00dc\u00e1\u00e0\u00e2\u00e4\u00e3\u00e5\u00e7\u00e9\u00e8\u00ea\u00eb\u00ed\u00ec\u00ee\u00ef\u00f1\u00f3\u00f2\u00f4\u00f6\u00f5\u00fa\u00f9\u00fb\u00fc\u2020\u00b0\u00a2\u00a3\u00a7\u2022\u00b6\u00df\u00ae\u00a9\u2122\u00b4\u00a8\u2260\u00c6\u00d8\u221e\u00b1\u2264\u2265\u00a5\u00b5\u2202\u2211\u220f\u03c0\u222b\u00aa\u00ba\u03a9\u00e6\u00f8\u00bf\u00a1\u00ac\u221a\u0192\u2248\u2206\u00ab\u00bb\u2026\u00a0\u00c0\u00c3\u00d5\u0152\u0153\u2013\u2014\u201c\u201d\u2018\u2019\u00f7\u25ca\u00ff\u0178\u2044\u20ac\u2039\u203a\ufb01\ufb02\u2021\u00b7\u201a\u201e\u2030\u00c2\u00ca\u00c1\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00d3\u00d4\uf8ff\u00d2\u00da\u00db\u00d9\u0131\u02c6\u02dc\u00af\u02d8\u02d9\u02da\u00b8\u02dd\u02db\u02c7",
|
||||
Aliases: []string{"macos-0_2-10.2", "macintosh", "mac", "csMacintosh", "windows-10000", "macroman"},
|
||||
},
|
||||
{
|
||||
Name: "macos-6_2-10.4",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c4\u00b9\u00b2\u00c9\u00b3\u00d6\u00dc\u0385\u00e0\u00e2\u00e4\u0384\u00a8\u00e7\u00e9\u00e8\u00ea\u00eb\u00a3\u2122\u00ee\u00ef\u2022\u00bd\u2030\u00f4\u00f6\u00a6\u20ac\u00f9\u00fb\u00fc\u2020\u0393\u0394\u0398\u039b\u039e\u03a0\u00df\u00ae\u00a9\u03a3\u03aa\u00a7\u2260\u00b0\u00b7\u0391\u00b1\u2264\u2265\u00a5\u0392\u0395\u0396\u0397\u0399\u039a\u039c\u03a6\u03ab\u03a8\u03a9\u03ac\u039d\u00ac\u039f\u03a1\u2248\u03a4\u00ab\u00bb\u2026\u00a0\u03a5\u03a7\u0386\u0388\u0153\u2013\u2015\u201c\u201d\u2018\u2019\u00f7\u0389\u038a\u038c\u038e\u03ad\u03ae\u03af\u03cc\u038f\u03cd\u03b1\u03b2\u03c8\u03b4\u03b5\u03c6\u03b3\u03b7\u03b9\u03be\u03ba\u03bb\u03bc\u03bd\u03bf\u03c0\u03ce\u03c1\u03c3\u03c4\u03b8\u03c9\u03c2\u03c7\u03c5\u03b6\u03ca\u03cb\u0390\u03b0\u00ad",
|
||||
Aliases: []string{"macos-6_2-10.4", "x-mac-greek", "windows-10006", "macgr"},
|
||||
},
|
||||
{
|
||||
Name: "macos-7_3-10.2",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u2020\u00b0\u0490\u00a3\u00a7\u2022\u00b6\u0406\u00ae\u00a9\u2122\u0402\u0452\u2260\u0403\u0453\u221e\u00b1\u2264\u2265\u0456\u00b5\u0491\u0408\u0404\u0454\u0407\u0457\u0409\u0459\u040a\u045a\u0458\u0405\u00ac\u221a\u0192\u2248\u2206\u00ab\u00bb\u2026\u00a0\u040b\u045b\u040c\u045c\u0455\u2013\u2014\u201c\u201d\u2018\u2019\u00f7\u201e\u040e\u045e\u040f\u045f\u2116\u0401\u0451\u044f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u20ac",
|
||||
Aliases: []string{"macos-7_3-10.2", "x-mac-cyrillic", "windows-10007", "mac-cyrillic", "maccy"},
|
||||
},
|
||||
{
|
||||
Name: "macos-29-10.2",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c4\u0100\u0101\u00c9\u0104\u00d6\u00dc\u00e1\u0105\u010c\u00e4\u010d\u0106\u0107\u00e9\u0179\u017a\u010e\u00ed\u010f\u0112\u0113\u0116\u00f3\u0117\u00f4\u00f6\u00f5\u00fa\u011a\u011b\u00fc\u2020\u00b0\u0118\u00a3\u00a7\u2022\u00b6\u00df\u00ae\u00a9\u2122\u0119\u00a8\u2260\u0123\u012e\u012f\u012a\u2264\u2265\u012b\u0136\u2202\u2211\u0142\u013b\u013c\u013d\u013e\u0139\u013a\u0145\u0146\u0143\u00ac\u221a\u0144\u0147\u2206\u00ab\u00bb\u2026\u00a0\u0148\u0150\u00d5\u0151\u014c\u2013\u2014\u201c\u201d\u2018\u2019\u00f7\u25ca\u014d\u0154\u0155\u0158\u2039\u203a\u0159\u0156\u0157\u0160\u201a\u201e\u0161\u015a\u015b\u00c1\u0164\u0165\u00cd\u017d\u017e\u016a\u00d3\u00d4\u016b\u016e\u00da\u016f\u0170\u0171\u0172\u0173\u00dd\u00fd\u0137\u017b\u0141\u017c\u0122\u02c7",
|
||||
Aliases: []string{"macos-29-10.2", "x-mac-centraleurroman", "windows-10029", "x-mac-ce", "macce", "maccentraleurope"},
|
||||
},
|
||||
{
|
||||
Name: "macos-35-10.2",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c4\u00c5\u00c7\u00c9\u00d1\u00d6\u00dc\u00e1\u00e0\u00e2\u00e4\u00e3\u00e5\u00e7\u00e9\u00e8\u00ea\u00eb\u00ed\u00ec\u00ee\u00ef\u00f1\u00f3\u00f2\u00f4\u00f6\u00f5\u00fa\u00f9\u00fb\u00fc\u2020\u00b0\u00a2\u00a3\u00a7\u2022\u00b6\u00df\u00ae\u00a9\u2122\u00b4\u00a8\u2260\u00c6\u00d8\u221e\u00b1\u2264\u2265\u00a5\u00b5\u2202\u2211\u220f\u03c0\u222b\u00aa\u00ba\u03a9\u00e6\u00f8\u00bf\u00a1\u00ac\u221a\u0192\u2248\u2206\u00ab\u00bb\u2026\u00a0\u00c0\u00c3\u00d5\u0152\u0153\u2013\u2014\u201c\u201d\u2018\u2019\u00f7\u25ca\u00ff\u0178\u011e\u011f\u0130\u0131\u015e\u015f\u2021\u00b7\u201a\u201e\u2030\u00c2\u00ca\u00c1\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00d3\u00d4\uf8ff\u00d2\u00da\u00db\u00d9\uf8a0\u02c6\u02dc\u00af\u02d8\u02d9\u02da\u00b8\u02dd\u02db\u02c7",
|
||||
Aliases: []string{"macos-35-10.2", "x-mac-turkish", "windows-10081", "mactr"},
|
||||
},
|
||||
{
|
||||
Name: "windows-1250",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\ufffd\u201e\u2026\u2020\u2021\ufffd\u2030\u0160\u2039\u015a\u0164\u017d\u0179\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\u2122\u0161\u203a\u015b\u0165\u017e\u017a\u00a0\u02c7\u02d8\u0141\u00a4\u0104\u00a6\u00a7\u00a8\u00a9\u015e\u00ab\u00ac\u00ad\u00ae\u017b\u00b0\u00b1\u02db\u0142\u00b4\u00b5\u00b6\u00b7\u00b8\u0105\u015f\u00bb\u013d\u02dd\u013e\u017c\u0154\u00c1\u00c2\u0102\u00c4\u0139\u0106\u00c7\u010c\u00c9\u0118\u00cb\u011a\u00cd\u00ce\u010e\u0110\u0143\u0147\u00d3\u00d4\u0150\u00d6\u00d7\u0158\u016e\u00da\u0170\u00dc\u00dd\u0162\u00df\u0155\u00e1\u00e2\u0103\u00e4\u013a\u0107\u00e7\u010d\u00e9\u0119\u00eb\u011b\u00ed\u00ee\u010f\u0111\u0144\u0148\u00f3\u00f4\u0151\u00f6\u00f7\u0159\u016f\u00fa\u0171\u00fc\u00fd\u0163\u02d9",
|
||||
},
|
||||
{
|
||||
Name: "windows-1251",
|
||||
Aliases: []string{"CP1251"},
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0402\u0403\u201a\u0453\u201e\u2026\u2020\u2021\u20ac\u2030\u0409\u2039\u040a\u040c\u040b\u040f\u0452\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\u2122\u0459\u203a\u045a\u045c\u045b\u045f\u00a0\u040e\u045e\u0408\u00a4\u0490\u00a6\u00a7\u0401\u00a9\u0404\u00ab\u00ac\u00ad\u00ae\u0407\u00b0\u00b1\u0406\u0456\u0491\u00b5\u00b6\u00b7\u0451\u2116\u0454\u00bb\u0458\u0405\u0455\u0457\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f",
|
||||
},
|
||||
{
|
||||
Name: "windows-1252",
|
||||
Aliases: []string{"cp1252"},
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\ufffd\u017d\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\ufffd\u017e\u0178\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff",
|
||||
},
|
||||
{
|
||||
Name: "windows-1253",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\u0192\u201e\u2026\u2020\u2021\ufffd\u2030\ufffd\u2039\ufffd\ufffd\ufffd\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\u2122\ufffd\u203a\ufffd\ufffd\ufffd\ufffd\u00a0\u0385\u0386\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\ufffd\u00ab\u00ac\u00ad\u00ae\u2015\u00b0\u00b1\u00b2\u00b3\u0384\u00b5\u00b6\u00b7\u0388\u0389\u038a\u00bb\u038c\u00bd\u038e\u038f\u0390\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\ufffd\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\ufffd",
|
||||
},
|
||||
{
|
||||
Name: "windows-1254",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\ufffd\ufffd\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\ufffd\ufffd\u0178\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u011e\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u0130\u015e\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u011f\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u0131\u015f\u00ff",
|
||||
},
|
||||
{
|
||||
Name: "windows-1255",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\ufffd\u2039\ufffd\ufffd\ufffd\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\ufffd\u203a\ufffd\ufffd\ufffd\ufffd\u00a0\u00a1\u00a2\u00a3\u20aa\u00a5\u00a6\u00a7\u00a8\u00a9\u00d7\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00f7\u00bb\u00bc\u00bd\u00be\u00bf\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9\ufffd\u05bb\u05bc\u05bd\u05be\u05bf\u05c0\u05c1\u05c2\u05c3\u05f0\u05f1\u05f2\u05f3\u05f4\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\ufffd\u200e\u200f\ufffd",
|
||||
},
|
||||
{
|
||||
Name: "windows-1256",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\u067e\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0679\u2039\u0152\u0686\u0698\u0688\u06af\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u06a9\u2122\u0691\u203a\u0153\u200c\u200d\u06ba\u00a0\u060c\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u06be\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u061b\u00bb\u00bc\u00bd\u00be\u061f\u06c1\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u00d7\u0637\u0638\u0639\u063a\u0640\u0641\u0642\u0643\u00e0\u0644\u00e2\u0645\u0646\u0647\u0648\u00e7\u00e8\u00e9\u00ea\u00eb\u0649\u064a\u00ee\u00ef\u064b\u064c\u064d\u064e\u00f4\u064f\u0650\u00f7\u0651\u00f9\u0652\u00fb\u00fc\u200e\u200f\u06d2",
|
||||
},
|
||||
{
|
||||
Name: "windows-1257",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\ufffd\u201e\u2026\u2020\u2021\ufffd\u2030\ufffd\u2039\ufffd\u00a8\u02c7\u00b8\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\u2122\ufffd\u203a\ufffd\u00af\u02db\ufffd\u00a0\ufffd\u00a2\u00a3\u00a4\ufffd\u00a6\u00a7\u00d8\u00a9\u0156\u00ab\u00ac\u00ad\u00ae\u00c6\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00f8\u00b9\u0157\u00bb\u00bc\u00bd\u00be\u00e6\u0104\u012e\u0100\u0106\u00c4\u00c5\u0118\u0112\u010c\u00c9\u0179\u0116\u0122\u0136\u012a\u013b\u0160\u0143\u0145\u00d3\u014c\u00d5\u00d6\u00d7\u0172\u0141\u015a\u016a\u00dc\u017b\u017d\u00df\u0105\u012f\u0101\u0107\u00e4\u00e5\u0119\u0113\u010d\u00e9\u017a\u0117\u0123\u0137\u012b\u013c\u0161\u0144\u0146\u00f3\u014d\u00f5\u00f6\u00f7\u0173\u0142\u015b\u016b\u00fc\u017c\u017e\u02d9",
|
||||
},
|
||||
{
|
||||
Name: "windows-1258",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\ufffd\u2039\u0152\ufffd\ufffd\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\ufffd\u203a\u0153\ufffd\ufffd\u0178\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u0102\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u0300\u00cd\u00ce\u00cf\u0110\u00d1\u0309\u00d3\u00d4\u01a0\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u01af\u0303\u00df\u00e0\u00e1\u00e2\u0103\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u0301\u00ed\u00ee\u00ef\u0111\u00f1\u0323\u00f3\u00f4\u01a1\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u01b0\u20ab\u00ff",
|
||||
},
|
||||
{
|
||||
Name: "windows-874",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\ufffd\ufffd\ufffd\ufffd\u2026\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u00a0\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\ufffd\ufffd\ufffd\ufffd\u0e3f\u0e40\u0e41\u0e42\u0e43\u0e44\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a\u0e4b\u0e4c\u0e4d\u0e4e\u0e4f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e5a\u0e5b\ufffd\ufffd\ufffd\ufffd",
|
||||
},
|
||||
{
|
||||
Name: "IBM037",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00a2.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!$*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5~stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae^\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"cp037", "ebcdic-cp-us", "ebcdic-cp-ca", "ebcdic-cp-wt", "ebcdic-cp-nl", "csIBM037"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-273_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00c4.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec~\u00dc$*);^-/\u00c2[\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#\u00a7'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5\u00dfstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9@\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00fcJKLMNOPQR\u00b9\u00fb}\u00f9\u00fa\u00ff\u00d6\u00f7STUVWXYZ\u00b2\u00d4\\\u00d2\u00d3\u00d50123456789\u00b3\u00db]\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-273_P100-1995", "ibm-273", "IBM273", "CP273", "csIBM273", "ebcdic-de", "273"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-277_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3}\u00e7\u00f1#.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u00a4\u00c5*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f8,%_>?\u00a6\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:\u00c6\u00d8'=\"@abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba{\u00b8[]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e6ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-277_P100-1995", "ibm-277", "IBM277", "cp277", "EBCDIC-CP-DK", "EBCDIC-CP-NO", "csIBM277", "ebcdic-dk", "277"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-278_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3}\u00e7\u00f1\u00a7.<(+!&`\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u00a4\u00c5*);^-/\u00c2#\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f6,%_>?\u00f8\\\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00e9:\u00c4\u00d6'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9[\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\u00c9\u00f7STUVWXYZ\u00b2\u00d4@\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-278_P100-1995", "ibm-278", "IBM278", "cp278", "ebcdic-cp-fi", "ebcdic-cp-se", "csIBM278", "ebcdic-sv", "278"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-280_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4{\u00e1\u00e3\u00e5\\\u00f1\u00b0.<(+!&]\u00ea\u00eb}\u00ed\u00ee\u00ef~\u00df\u00e9$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f2,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00f9:\u00a3\u00a7'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1[jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5\u00ecstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2#\u00a5\u00b7\u00a9@\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e0ABCDEFGHI\u00ad\u00f4\u00f6\u00a6\u00f3\u00f5\u00e8JKLMNOPQR\u00b9\u00fb\u00fc`\u00fa\u00ff\u00e7\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-280_P100-1995", "ibm-280", "IBM280", "CP280", "ebcdic-cp-it", "csIBM280", "280"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-284_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00a6[.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df]$*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7#\u00f1,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:\u00d1@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5\u00a8stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be^!\u00af~\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-284_P100-1995", "ibm-284", "IBM284", "CP284", "ebcdic-cp-es", "csIBM284", "cpibm284", "284"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-285_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1$.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!\u00a3*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5\u00afstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2[\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be^]~\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-285_P100-1995", "ibm-285", "IBM285", "CP285", "ebcdic-cp-gb", "csIBM285", "cpibm285", "ebcdic-gb", "285"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-290_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \uff61\uff62\uff63\uff64\uff65\uff66\uff67\uff68\uff69\u00a3.<(+|&\uff6a\uff6b\uff6c\uff6d\uff6e\uff6f\ufffd\uff70\ufffd!\u00a5*);\u00ac-/abcdefgh\ufffd,%_>?[ijklmnop`:#@'=\"]\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78\uff79\uff7aq\uff7b\uff7c\uff7d\uff7e\uff7f\uff80\uff81\uff82\uff83\uff84\uff85\uff86\uff87\uff88\uff89r\ufffd\uff8a\uff8b\uff8c~\u203e\uff8d\uff8e\uff8f\uff90\uff91\uff92\uff93\uff94\uff95s\uff96\uff97\uff98\uff99^\u00a2\\tuvwxyz\uff9a\uff9b\uff9c\uff9d\uff9e\uff9f{ABCDEFGHI\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd}JKLMNOPQR\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd$\ufffdSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-290_P100-1995", "ibm-290", "IBM290", "cp290", "EBCDIC-JP-kana", "csIBM290"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-297_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4@\u00e1\u00e3\u00e5\\\u00f1\u00b0.<(+!&{\u00ea\u00eb}\u00ed\u00ee\u00ef\u00ec\u00df\u00a7$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f9,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00b5:\u00a3\u00e0'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1[jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4`\u00a8stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2#\u00a5\u00b7\u00a9]\u00b6\u00bc\u00bd\u00be\u00ac|\u00af~\u00b4\u00d7\u00e9ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5\u00e8JKLMNOPQR\u00b9\u00fb\u00fc\u00a6\u00fa\u00ff\u00e7\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-297_P100-1995", "ibm-297", "IBM297", "cp297", "ebcdic-cp-fr", "csIBM297", "cpibm297", "297"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-420_X120-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0651\ufe7d\u0640\u200b\u0621\u0622\ufe82\u0623\u00a2.<(+|&\ufe84\u0624\ufffd\ufffd\u0626\u0627\ufe8e\u0628\ufe91!$*);\u00ac-/\u0629\u062a\ufe97\u062b\ufe9b\u062c\ufe9f\u062d\u00a6,%_>?\ufea3\u062e\ufea7\u062f\u0630\u0631\u0632\u0633\ufeb3\u060c:#@'=\"\u0634abcdefghi\ufeb7\u0635\ufebb\u0636\ufebf\u0637\u0638jklmnopqr\u0639\ufeca\ufecb\ufecc\u063a\ufece\ufecf\u00f7stuvwxyz\ufed0\u0641\ufed3\u0642\ufed7\u0643\ufedb\u0644\ufef5\ufef6\ufef7\ufef8\ufffd\ufffd\ufefb\ufefc\ufedf\u0645\ufee3\u0646\ufee7\u0647\u061bABCDEFGHI\u00ad\ufeeb\ufffd\ufeec\ufffd\u0648\u061fJKLMNOPQR\u0649\ufef0\u064a\ufef2\ufef3\u0660\u00d7\ufffdSTUVWXYZ\u0661\u0662\ufffd\u0663\u0664\u06650123456789\ufffd\u0666\u0667\u0668\u0669\u009f",
|
||||
Aliases: []string{"ibm-420_X120-1999", "ibm-420", "IBM420", "cp420", "ebcdic-cp-ar1", "csIBM420", "420"},
|
||||
},
|
||||
{
|
||||
Name: "IBM424",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u00a2.<(+|&\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1!$*);\u00ac-/\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u00a6,%_>?\ufffd\u05ea\ufffd\ufffd\u00a0\ufffd\ufffd\ufffd\u2017`:#@'=\"\ufffdabcdefghi\u00ab\u00bb\ufffd\ufffd\ufffd\u00b1\u00b0jklmnopqr\ufffd\ufffd\ufffd\u00b8\ufffd\u00a4\u00b5~stuvwxyz\ufffd\ufffd\ufffd\ufffd\ufffd\u00ae^\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\ufffd\ufffd\ufffd\ufffd\ufffd}JKLMNOPQR\u00b9\ufffd\ufffd\ufffd\ufffd\ufffd\\\u00f7STUVWXYZ\u00b2\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\u00b3\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"cp424", "ebcdic-cp-he", "csIBM424"},
|
||||
},
|
||||
{
|
||||
Name: "IBM437",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00a2\u00a3\u00a5\u20a7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u2310\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u00b5\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"cp437", "437", "csPC8CodePage437"},
|
||||
},
|
||||
{
|
||||
Name: "IBM500",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1[.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df]$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5~stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"CP500", "ebcdic-cp-be", "ebcdic-cp-ch", "csIBM500"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-720_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\ufffd\ufffd\u00e9\u00e2\ufffd\u00e0\ufffd\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\ufffd\ufffd\ufffd\ufffd\u0651\u0652\u00f4\u00a4\u0640\u00fb\u00f9\u0621\u0622\u0623\u0624\u00a3\u0625\u0626\u0627\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631\u0632\u0633\u0634\u0635\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u0636\u0637\u0638\u0639\u063a\u0641\u00b5\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064a\u2261\u064b\u064c\u064d\u064e\u064f\u0650\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-720_P100-1997", "ibm-720", "windows-720", "DOS-720"},
|
||||
},
|
||||
{
|
||||
Name: "IBM737",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c2\u03c4\u03c5\u03c6\u03c7\u03c8\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03c9\u03ac\u03ad\u03ae\u03ca\u03af\u03cc\u03cd\u03cb\u03ce\u0386\u0388\u0389\u038a\u038c\u038e\u038f\u00b1\u2265\u2264\u03aa\u03ab\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"cp737", "cp737_DOSGreek"},
|
||||
},
|
||||
{
|
||||
Name: "IBM775",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0106\u00fc\u00e9\u0101\u00e4\u0123\u00e5\u0107\u0142\u0113\u0156\u0157\u012b\u0179\u00c4\u00c5\u00c9\u00e6\u00c6\u014d\u00f6\u0122\u00a2\u015a\u015b\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u00a4\u0100\u012a\u00f3\u017b\u017c\u017a\u201d\u00a6\u00a9\u00ae\u00ac\u00bd\u00bc\u0141\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u0104\u010c\u0118\u0116\u2563\u2551\u2557\u255d\u012e\u0160\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u0172\u016a\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u017d\u0105\u010d\u0119\u0117\u012f\u0161\u0173\u016b\u017e\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u00d3\u00df\u014c\u0143\u00f5\u00d5\u00b5\u0144\u0136\u0137\u013b\u013c\u0146\u0112\u0145\u2019\u00ad\u00b1\u201c\u00be\u00b6\u00a7\u00f7\u201e\u00b0\u2219\u00b7\u00b9\u00b3\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"cp775", "csPC775Baltic"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-803_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd$.<(+|\u05d0\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd!\u00a2*);\u00ac-/\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd,%_>?\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd:#@'=\"\ufffd\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdABCDEFGHI\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdJKLMNOPQR\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-803_P100-1999", "ibm-803", "cp803"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-838_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07[\u00a2.<(+|&\u0e48\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e]!$*);\u00ac-/\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15^\u00a6,%_>?\u0e3f\u0e4e\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c`:#@'=\"\u0e4fabcdefghi\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e5ajklmnopqr\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e5b~stuvwxyz\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34{ABCDEFGHI\u0e49\u0e35\u0e36\u0e37\u0e38\u0e39}JKLMNOPQR\u0e3a\u0e40\u0e41\u0e42\u0e43\u0e44\\\u0e4aSTUVWXYZ\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a0123456789\u0e4b\u0e4c\u0e4d\u0e4b\u0e4c\u009f",
|
||||
Aliases: []string{"ibm-838_P100-1995", "ibm-838", "IBM838", "IBM-Thai", "csIBMThai", "cp838", "838", "ibm-9030"},
|
||||
},
|
||||
{
|
||||
Name: "IBM850",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u00c1\u00c2\u00c0\u00a9\u2563\u2551\u2557\u255d\u00a2\u00a5\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u00e3\u00c3\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\u00f0\u00d0\u00ca\u00cb\u00c8\u0131\u00cd\u00ce\u00cf\u2518\u250c\u2588\u2584\u00a6\u00cc\u2580\u00d3\u00df\u00d4\u00d2\u00f5\u00d5\u00b5\u00fe\u00de\u00da\u00db\u00d9\u00fd\u00dd\u00af\u00b4\u00ad\u00b1\u2017\u00be\u00b6\u00a7\u00f7\u00b8\u00b0\u00a8\u00b7\u00b9\u00b3\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"cp850", "850", "csPC850Multilingual"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-851_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u0386\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u0388\u00c4\u0389\u038a\ufffd\u038c\u00f4\u00f6\u038e\u00fb\u00f9\u038f\u00d6\u00dc\u03ac\u00a3\u03ad\u03ae\u03af\u03ca\u0390\u03cc\u03cd\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u00bd\u0398\u0399\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u039a\u039b\u039c\u039d\u2563\u2551\u2557\u255d\u039e\u039f\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u03a0\u03a1\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03b1\u03b2\u03b3\u2518\u250c\u2588\u2584\u03b4\u03b5\u2580\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c2\u03c4\u00b4\u00ad\u00b1\u03c5\u03c6\u03c7\u00a7\u03c8\u00b8\u00b0\u00a8\u03c9\u03cb\u03b0\u03ce\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-851_P100-1995", "ibm-851", "IBM851", "cp851", "851", "csPC851"},
|
||||
},
|
||||
{
|
||||
Name: "IBM852",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u00c7\u00fc\u00e9\u00e2\u00e4\u016f\u0107\u00e7\u0142\u00eb\u0150\u0151\u00ee\u0179\u00c4\u0106\u00c9\u0139\u013a\u00f4\u00f6\u013d\u013e\u015a\u015b\u00d6\u00dc\u0164\u0165\u0141\u00d7\u010d\u00e1\u00ed\u00f3\u00fa\u0104\u0105\u017d\u017e\u0118\u0119\u00ac\u017a\u010c\u015f\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u00c1\u00c2\u011a\u015e\u2563\u2551\u2557\u255d\u017b\u017c\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u0102\u0103\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\u0111\u0110\u010e\u00cb\u010f\u0147\u00cd\u00ce\u011b\u2518\u250c\u2588\u2584\u0162\u016e\u2580\u00d3\u00df\u00d4\u0143\u0144\u0148\u0160\u0161\u0154\u00da\u0155\u0170\u00fd\u00dd\u0163\u00b4\u00ad\u02dd\u02db\u02c7\u02d8\u00a7\u00f7\u00b8\u00b0\u00a8\u02d9\u0171\u0158\u0159\u25a0\u00a0",
|
||||
Aliases: []string{"cp852", "852", "csPCp852"},
|
||||
},
|
||||
{
|
||||
Name: "IBM855",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0452\u0402\u0453\u0403\u0451\u0401\u0454\u0404\u0455\u0405\u0456\u0406\u0457\u0407\u0458\u0408\u0459\u0409\u045a\u040a\u045b\u040b\u045c\u040c\u045e\u040e\u045f\u040f\u044e\u042e\u044a\u042a\u0430\u0410\u0431\u0411\u0446\u0426\u0434\u0414\u0435\u0415\u0444\u0424\u0433\u0413\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u0445\u0425\u0438\u0418\u2563\u2551\u2557\u255d\u0439\u0419\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u043a\u041a\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\u043b\u041b\u043c\u041c\u043d\u041d\u043e\u041e\u043f\u2518\u250c\u2588\u2584\u041f\u044f\u2580\u042f\u0440\u0420\u0441\u0421\u0442\u0422\u0443\u0423\u0436\u0416\u0432\u0412\u044c\u042c\u2116\u00ad\u044b\u042b\u0437\u0417\u0448\u0428\u044d\u042d\u0449\u0429\u0447\u0427\u00a7\u25a0\u00a0",
|
||||
Aliases: []string{"cp855", "855", "csIBM855"},
|
||||
},
|
||||
{
|
||||
Name: "IBM856",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\u00a3\ufffd\u00d7\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u00ae\u00ac\u00bd\u00bc\ufffd\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\ufffd\ufffd\ufffd\u00a9\u2563\u2551\u2557\u255d\u00a2\u00a5\u2510\u2514\u2534\u252c\u251c\u2500\u253c\ufffd\ufffd\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u2518\u250c\u2588\u2584\u00a6\ufffd\u2580\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u00b5\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u00af\u00b4\u00ad\u00b1\u2017\u00be\u00b6\u00a7\u00f7\u00b8\u00b0\u00a8\u00b7\u00b9\u00b3\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"cp856", "cp856_Hebrew_PC"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-857_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u0131\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u0130\u00d6\u00dc\u00f8\u00a3\u00d8\u015e\u015f\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u011e\u011f\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u00c1\u00c2\u00c0\u00a9\u2563\u2551\u2557\u255d\u00a2\u00a5\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u00e3\u00c3\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\u00ba\u00aa\u00ca\u00cb\u00c8\ufffd\u00cd\u00ce\u00cf\u2518\u250c\u2588\u2584\u00a6\u00cc\u2580\u00d3\u00df\u00d4\u00d2\u00f5\u00d5\u00b5\ufffd\u00d7\u00da\u00db\u00d9\u00ec\u00ff\u00af\u00b4\u00ad\u00b1\ufffd\u00be\u00b6\u00a7\u00f7\u00b8\u00b0\u00a8\u00b7\u00b9\u00b3\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-857_P100-1995", "ibm-857", "IBM857", "cp857", "857", "csIBM857", "windows-857"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-858_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u00c1\u00c2\u00c0\u00a9\u2563\u2551\u2557\u255d\u00a2\u00a5\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u00e3\u00c3\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u00a4\u00f0\u00d0\u00ca\u00cb\u00c8\u20ac\u00cd\u00ce\u00cf\u2518\u250c\u2588\u2584\u00a6\u00cc\u2580\u00d3\u00df\u00d4\u00d2\u00f5\u00d5\u00b5\u00fe\u00de\u00da\u00db\u00d9\u00fd\u00dd\u00af\u00b4\u00ad\u00b1\u2017\u00be\u00b6\u00a7\u00f7\u00b8\u00b0\u00a8\u00b7\u00b9\u00b3\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-858_P100-1997", "ibm-858", "IBM00858", "CCSID00858", "CP00858", "PC-Multilingual-850+euro", "cp858", "windows-858"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-860_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e3\u00e0\u00c1\u00e7\u00ea\u00ca\u00e8\u00cd\u00d4\u00ec\u00c3\u00c2\u00c9\u00c0\u00c8\u00f4\u00f5\u00f2\u00da\u00f9\u00cc\u00d5\u00dc\u00a2\u00a3\u00d9\u20a7\u00d3\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00d2\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-860_P100-1995", "ibm-860", "IBM860", "cp860", "860", "csIBM860"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-861_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00d0\u00f0\u00de\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00fe\u00fb\u00dd\u00fd\u00d6\u00dc\u00f8\u00a3\u00d8\u20a7\u0192\u00e1\u00ed\u00f3\u00fa\u00c1\u00cd\u00d3\u00da\u00bf\u2310\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-861_P100-1995", "ibm-861", "IBM861", "cp861", "861", "cp-is", "csIBM861", "windows-861"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-862_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\u00a2\u00a3\u00a5\u20a7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u2310\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-862_P100-1995", "ibm-862", "IBM862", "cp862", "862", "csPC862LatinHebrew", "DOS-862", "windows-862"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-863_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00c2\u00e0\u00b6\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u2017\u00c0\u00a7\u00c9\u00c8\u00ca\u00f4\u00cb\u00cf\u00fb\u00f9\u00a4\u00d4\u00dc\u00a2\u00a3\u00d9\u00db\u0192\u00a6\u00b4\u00f3\u00fa\u00a8\u00b8\u00b3\u00af\u00ce\u2310\u00ac\u00bd\u00bc\u00be\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-863_P100-1995", "ibm-863", "IBM863", "cp863", "863", "csIBM863"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-864_X110-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00b0\u00b7\u2219\u221a\u2592\u2500\u2502\u253c\u2524\u252c\u251c\u2534\u2510\u250c\u2514\u2518\u03b2\u221e\u03c6\u00b1\u00bd\u00bc\u2248\u00ab\u00bb\ufef7\ufef8\ufffd\ufffd\ufefb\ufefc\u200b\u00a0\u00ad\ufe82\u00a3\u00a4\ufe84\ufffd\ufffd\ufe8e\ufe8f\ufe95\ufe99\u060c\ufe9d\ufea1\ufea5\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\ufed1\u061b\ufeb1\ufeb5\ufeb9\u061f\u00a2\ufe80\ufe81\ufe83\ufe85\ufeca\ufe8b\ufe8d\ufe91\ufe93\ufe97\ufe9b\ufe9f\ufea3\ufea7\ufea9\ufeab\ufead\ufeaf\ufeb3\ufeb7\ufebb\ufebf\ufec3\ufec7\ufecb\ufecf\u00a6\u00ac\u00f7\u00d7\ufec9\u0640\ufed3\ufed7\ufedb\ufedf\ufee3\ufee7\ufeeb\ufeed\ufeef\ufef3\ufebd\ufecc\ufece\ufecd\ufee1\ufe7d\ufe7c\ufee5\ufee9\ufeec\ufef0\ufef2\ufed0\ufed5\ufef5\ufef6\ufedd\ufed9\ufef1\u25a0\ufffd",
|
||||
Aliases: []string{"ibm-864_X110-1999", "ibm-864", "IBM864", "cp864", "csIBM864"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-865_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u20a7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u2310\u00ac\u00bd\u00bc\u00a1\u00ab\u00a4\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-865_P100-1995", "ibm-865", "IBM865", "cp865", "865", "csIBM865"},
|
||||
},
|
||||
{
|
||||
Name: "IBM866",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0401\u0451\u0404\u0454\u0407\u0457\u040e\u045e\u00b0\u2219\u00b7\u221a\u2116\u00a4\u25a0\u00a0",
|
||||
Aliases: []string{"cp866", "866", "csIBM866"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-867_P100-1998",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\u00a2\u00a3\u00a5\ufffd\u20aa\u200e\u200f\u202a\u202b\u202d\u202e\u202c\ufffd\ufffd\u2310\u00ac\u00bd\u00bc\u20ac\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-867_P100-1998", "ibm-867"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-868_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u060c\u061b\u061f\ufe81\ufe8d\ufe8e\uf8fb\ufe8f\ufe91\ufb56\ufb58\ufe93\ufe95\ufe97\ufb66\ufb68\ufe99\ufe9b\ufe9d\ufe9f\ufb7a\ufb7c\ufea1\ufea3\ufea5\ufea7\ufea9\ufb88\ufeab\ufead\ufb8c\ufeaf\ufb8a\ufeb1\ufeb3\ufeb5\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\ufeb7\ufeb9\ufebb\ufebd\u2563\u2551\u2557\u255d\ufebf\ufec3\u2510\u2514\u2534\u252c\u251c\u2500\u253c\ufec7\ufec9\u255a\u2554\u2569\u2566\u2560\u2550\u256c\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed3\ufed5\u2518\u250c\u2588\u2584\ufed7\ufb8e\u2580\ufedb\ufb92\ufb94\ufedd\ufedf\ufee0\ufee1\ufee3\ufb9e\ufee5\ufee7\ufe85\ufeed\ufba6\ufba8\ufba9\u00ad\ufbaa\ufe80\ufe89\ufe8a\ufe8b\ufbfc\ufbfd\ufbfe\ufbb0\ufbae\ufe7c\ufe7d\ufffd\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-868_P100-1995", "ibm-868", "IBM868", "CP868", "868", "csIBM868", "cp-ar"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-869_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0386\ufffd\u0387\u00ac\u00a6\u2018\u2019\u0388\u2015\u0389\u038a\u03aa\u038c\ufffd\ufffd\u038e\u03ab\u00a9\u038f\u00b2\u00b3\u03ac\u00a3\u03ad\u03ae\u03af\u03ca\u0390\u03cc\u03cd\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u00bd\u0398\u0399\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u039a\u039b\u039c\u039d\u2563\u2551\u2557\u255d\u039e\u039f\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u03a0\u03a1\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03b1\u03b2\u03b3\u2518\u250c\u2588\u2584\u03b4\u03b5\u2580\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c2\u03c4\u00b4\u00ad\u00b1\u03c5\u03c6\u03c7\u00a7\u03c8\u0385\u00b0\u00a8\u03c9\u03cb\u03b0\u03ce\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-869_P100-1995", "ibm-869", "IBM869", "cp869", "869", "cp-gr", "csIBM869", "windows-869"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-870_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u0163\u00e1\u0103\u010d\u00e7\u0107[.<(+!&\u00e9\u0119\u00eb\u016f\u00ed\u00ee\u013e\u013a\u00df]$*);^-/\u00c2\u00c4\u02dd\u00c1\u0102\u010c\u00c7\u0106|,%_>?\u02c7\u00c9\u0118\u00cb\u016e\u00cd\u00ce\u013d\u0139`:#@'=\"\u02d8abcdefghi\u015b\u0148\u0111\u00fd\u0159\u015f\u00b0jklmnopqr\u0142\u0144\u0161\u00b8\u02db\u00a4\u0105~stuvwxyz\u015a\u0147\u0110\u00dd\u0158\u015e\u02d9\u0104\u017c\u0162\u017b\u00a7\u017e\u017a\u017d\u0179\u0141\u0143\u0160\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u0155\u00f3\u0151}JKLMNOPQR\u011a\u0171\u00fc\u0165\u00fa\u011b\\\u00f7STUVWXYZ\u010f\u00d4\u00d6\u0154\u00d3\u01500123456789\u010e\u0170\u00dc\u0164\u00da\u009f",
|
||||
Aliases: []string{"ibm-870_P100-1995", "ibm-870", "IBM870", "CP870", "ebcdic-cp-roece", "ebcdic-cp-yu", "csIBM870"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-871_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00de.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u00c6$*);\u00d6-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00f0:#\u00d0'=\"\u00d8abcdefghi\u00ab\u00bb`\u00fd{\u00b1\u00b0jklmnopqr\u00aa\u00ba}\u00b8]\u00a4\u00b5\u00f6stuvwxyz\u00a1\u00bf@\u00dd[\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\\\u00d7\u00feABCDEFGHI\u00ad\u00f4~\u00f2\u00f3\u00f5\u00e6JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\u00b4\u00f7STUVWXYZ\u00b2\u00d4^\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-871_P100-1995", "ibm-871", "IBM871", "ebcdic-cp-is", "csIBM871", "CP871", "ebcdic-is", "871"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-874_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0e48\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\u0e49\u0e4a\u0e4b\u0e4c\u0e3f\u0e40\u0e41\u0e42\u0e43\u0e44\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a\u0e4b\u0e4c\u0e4d\u0e4e\u0e4f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e5a\u0e5b\u00a2\u00ac\u00a6\u00a0",
|
||||
Aliases: []string{"ibm-874_P100-1995", "ibm-874", "ibm-9066", "cp874", "tis620.2533", "eucTH"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-875_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399[.<(+!&\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3]$*);^-/\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab|,%_>?\u00a8\u0386\u0388\u0389\u00a0\u038a\u038c\u038e\u038f`:#@'=\"\u0385abcdefghi\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u00b0jklmnopqr\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u00b4~stuvwxyz\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u00a3\u03ac\u03ad\u03ae\u03ca\u03af\u03cc\u03cd\u03cb\u03ce\u03c2\u03c4\u03c5\u03c6\u03c7\u03c8{ABCDEFGHI\u00ad\u03c9\u0390\u03b0\u2018\u2015}JKLMNOPQR\u00b1\u00bd\ufffd\u0387\u2019\u00a6\\\ufffdSTUVWXYZ\u00b2\u00a7\ufffd\ufffd\u00ab\u00ac0123456789\u00b3\u00a9\ufffd\ufffd\u00bb\u009f",
|
||||
Aliases: []string{"ibm-875_P100-1995", "ibm-875", "IBM875", "cp875", "875"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-901_P100-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u201d\u00a2\u00a3\u20ac\u201e\u00a6\u00a7\u00d8\u00a9\u0156\u00ab\u00ac\u00ad\u00ae\u00c6\u00b0\u00b1\u00b2\u00b3\u201c\u00b5\u00b6\u00b7\u00f8\u00b9\u0157\u00bb\u00bc\u00bd\u00be\u00e6\u0104\u012e\u0100\u0106\u00c4\u00c5\u0118\u0112\u010c\u00c9\u0179\u0116\u0122\u0136\u012a\u013b\u0160\u0143\u0145\u00d3\u014c\u00d5\u00d6\u00d7\u0172\u0141\u015a\u016a\u00dc\u017b\u017d\u00df\u0105\u012f\u0101\u0107\u00e4\u00e5\u0119\u0113\u010d\u00e9\u017a\u0117\u0123\u0137\u012b\u013c\u0161\u0144\u0146\u00f3\u014d\u00f5\u00f6\u00f7\u0173\u0142\u015b\u016b\u00fc\u017c\u017e\u2019",
|
||||
Aliases: []string{"ibm-901_P100-1999", "ibm-901"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-902_P100-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u00a1\u00a2\u00a3\u20ac\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0160\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u017d\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u0161\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u017e\u00ff",
|
||||
Aliases: []string{"ibm-902_P100-1999", "ibm-902"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-916_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\ufffd\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00d7\u00ab\u00ac\u00ad\u00ae\u203e\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u2022\u00b8\u00b9\u00f7\u00bb\u00bc\u00bd\u00be\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u2017\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\ufffd\ufffd\ufffd\ufffd",
|
||||
Aliases: []string{"ibm-916_P100-1995", "ibm-916", "cp916", "916"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-918_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u060c\u061b\u061f\ufe81\ufe8d\ufe8e\uf8fb\ufe8f[.<(+!&\ufe91\ufb56\ufb58\ufe93\ufe95\ufe97\ufb66\ufb68\ufe99]$*);^-/\ufe9b\ufe9d\ufe9f\ufb7a\ufb7c\ufea1\ufea3\ufea5`,%_>?\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9:#@'=\"\ufea7abcdefghi\ufea9\ufb88\ufeab\ufead\ufb8c\ufeaf\ufb8ajklmnopqr\ufeb1\ufeb3\ufeb5\ufeb7\ufeb9\ufebb\ufebd~stuvwxyz\ufebf\ufec3\ufec7\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed3\ufed5\ufed7\ufb8e\ufedb|\ufb92\ufb94\ufedd\ufedf{ABCDEFGHI\u00ad\ufee0\ufee1\ufee3\ufb9e\ufee5}JKLMNOPQR\ufee7\ufe85\ufeed\ufba6\ufba8\ufba9\\\ufbaaSTUVWXYZ\ufe80\ufe89\ufe8a\ufe8b\ufbfc\ufbfd0123456789\ufbfe\ufbb0\ufbae\ufe7c\ufe7d\u009f",
|
||||
Aliases: []string{"ibm-918_P100-1995", "ibm-918", "IBM918", "CP918", "ebcdic-cp-ar2", "csIBM918"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-922_P100-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0160\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u017d\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\u0161\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u017e\u00ff",
|
||||
Aliases: []string{"ibm-922_P100-1999", "ibm-922", "IBM922", "cp922", "922"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1006_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u060c\u061b\u00ad\u061f\ufe81\ufe8d\ufe8e\uf8fb\ufe8f\ufe91\ufb56\ufb58\ufe93\ufe95\ufe97\ufb66\ufb68\ufe99\ufe9b\ufe9d\ufe9f\ufb7a\ufb7c\ufea1\ufea3\ufea5\ufea7\ufea9\ufb88\ufeab\ufead\ufb8c\ufeaf\ufb8a\ufeb1\ufeb3\ufeb5\ufeb7\ufeb9\ufebb\ufebd\ufebf\ufec3\ufec7\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed3\ufed5\ufed7\ufb8e\ufedb\ufb92\ufb94\ufedd\ufedf\ufee0\ufee1\ufee3\ufb9e\ufee5\ufee7\ufe85\ufeed\ufba6\ufba8\ufba9\ufbaa\ufe80\ufe89\ufe8a\ufe8b\ufbfc\ufbfd\ufbfe\ufbb0\ufbae\ufe7c\ufe7d",
|
||||
Aliases: []string{"ibm-1006_P100-1995", "ibm-1006", "IBM1006", "cp1006", "1006"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1025_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0452\u0453\u0451\u0454\u0455\u0456\u0457\u0458[.<(+!&\u0459\u045a\u045b\u045c\u045e\u045f\u042a\u2116\u0402]$*);^-/\u0403\u0401\u0404\u0405\u0406\u0407\u0408\u0409|,%_>?\u040a\u040b\u040c\u00ad\u040e\u040f\u044e\u0430\u0431`:#@'=\"\u0446abcdefghi\u0434\u0435\u0444\u0433\u0445\u0438\u0439jklmnopqr\u043a\u043b\u043c\u043d\u043e\u043f\u044f~stuvwxyz\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413{ABCDEFGHI\u0425\u0418\u0419\u041a\u041b\u041c}JKLMNOPQR\u041d\u041e\u041f\u042f\u0420\u0421\\\u00a7STUVWXYZ\u0422\u0423\u0416\u0412\u042c\u042b0123456789\u0417\u0428\u042d\u0429\u0427\u009f",
|
||||
Aliases: []string{"ibm-1025_P100-1995", "ibm-1025", "cp1025", "1025"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1026_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5{\u00f1\u00c7.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u011e\u0130*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5[\u00d1\u015f,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u0131:\u00d6\u015e'=\u00dc\u00d8abcdefghi\u00ab\u00bb}`\u00a6\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5\u00f6stuvwxyz\u00a1\u00bf]$@\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e7ABCDEFGHI\u00ad\u00f4~\u00f2\u00f3\u00f5\u011fJKLMNOPQR\u00b9\u00fb\\\u00f9\u00fa\u00ff\u00fc\u00f7STUVWXYZ\u00b2\u00d4#\u00d2\u00d3\u00d50123456789\u00b3\u00db\"\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1026_P100-1995", "ibm-1026", "IBM1026", "CP1026", "csIBM1026", "1026"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1047_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00a2.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u00a4\u00b5~stuvwxyz\u00a1\u00bf\u00d0[\u00de\u00ae\u00ac\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00dd\u00a8\u00af]\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1047_P100-1995", "ibm-1047", "IBM1047", "cp1047", "1047"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1097_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u060c\u064b\ufe81\ufe82\uf8fa\ufe8d\ufe8e\uf8fb\u00a4.<(+|&\ufe80\ufe83\ufe84\uf8f9\ufe85\ufe8b\ufe8f\ufe91\ufb56!$*);\u00ac-/\ufb58\ufe95\ufe97\ufe99\ufe9b\ufe9d\ufe9f\ufb7a\u061b,%_>?\ufb7c\ufea1\ufea3\ufea5\ufea7\ufea9\ufeab\ufead\ufeaf`:#@'=\"\ufb8aabcdefghi\u00ab\u00bb\ufeb1\ufeb3\ufeb5\ufeb7\ufeb9jklmnopqr\ufebb\ufebd\ufebf\ufec1\ufec3\ufec5\ufec7~stuvwxyz\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed3\ufed5\ufed7\ufb8e\ufedb\ufb92\ufb94[]\ufedd\ufedf\ufee1\u00d7{ABCDEFGHI\u00ad\ufee3\ufee5\ufee7\ufeed\ufee9}JKLMNOPQR\ufeeb\ufeec\ufba4\ufbfc\ufbfd\ufbfe\\\u061fSTUVWXYZ\u0640\u06f0\u06f1\u06f2\u06f3\u06f40123456789\u06f5\u06f6\u06f7\u06f8\u06f9\u009f",
|
||||
Aliases: []string{"ibm-1097_P100-1995", "ibm-1097", "cp1097", "1097"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1098_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\ufffd\ufffd\u060c\u061b\u061f\u064b\ufe81\ufe82\uf8fa\ufe8d\ufe8e\uf8fb\ufe80\ufe83\ufe84\uf8f9\ufe85\ufe8b\ufe8f\ufe91\ufb56\ufb58\ufe95\ufe97\ufe99\ufe9b\ufe9d\ufe9f\ufb7a\ufb7c\u00d7\ufea1\ufea3\ufea5\ufea7\ufea9\ufeab\ufead\ufeaf\ufb8a\ufeb1\ufeb3\ufeb5\ufeb7\ufeb9\ufebb\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\ufebd\ufebf\ufec1\ufec3\u2563\u2551\u2557\u255d\u00a4\ufec5\u2510\u2514\u2534\u252c\u251c\u2500\u253c\ufec7\ufec9\u255a\u2554\u2569\u2566\u2560\u2550\u256c\ufffd\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1\ufed3\u2518\u250c\u2588\u2584\ufed5\ufed7\u2580\ufb8e\ufedb\ufb92\ufb94\ufedd\ufedf\ufee1\ufee3\ufee5\ufee7\ufeed\ufee9\ufeeb\ufeec\ufba4\ufbfc\u00ad\ufbfd\ufbfe\u0640\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-1098_P100-1995", "ibm-1098", "IBM1098", "cp1098", "1098"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1112_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0161\u00e4\u0105\u012f\u016b\u00e5\u0113\u017e\u00a2.<(+|&\u00e9\u0119\u0117\u010d\u0173\u201e\u201c\u0123\u00df!$*);\u00ac-/\u0160\u00c4\u0104\u012e\u016a\u00c5\u0112\u017d\u00a6,%_>?\u00f8\u00c9\u0118\u0116\u010c\u0172\u012a\u013b\u0122`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u0101\u017c\u0144\u00b1\u00b0jklmnopqr\u0156\u0157\u00e6\u0137\u00c6\u00a4\u00b5~stuvwxyz\u201d\u017a\u0100\u017b\u0143\u00ae^\u00a3\u012b\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u0179\u0136\u013c\u00d7{ABCDEFGHI\u00ad\u014d\u00f6\u0146\u00f3\u00f5}JKLMNOPQR\u00b9\u0107\u00fc\u0142\u015b\u2019\\\u00f7STUVWXYZ\u00b2\u014c\u00d6\u0145\u00d3\u00d50123456789\u00b3\u0106\u00dc\u0141\u015a\u009f",
|
||||
Aliases: []string{"ibm-1112_P100-1995", "ibm-1112", "cp1112", "1112"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1122_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3}\u00e7\u00f1\u00a7.<(+!&`\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u00a4\u00c5*);^-/\u00c2#\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f6,%_>?\u00f8\\\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00e9:\u00c4\u00d6'=\"\u00d8abcdefghi\u00ab\u00bb\u0161\u00fd\u017e\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u0160\u00dd\u017d\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9[\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\u00c9\u00f7STUVWXYZ\u00b2\u00d4@\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1122_P100-1999", "ibm-1122", "cp1122", "1122"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1123_P100-1995",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0452\u0491\u0451\u0454\u0455\u0456\u0457\u0458[.<(+!&\u0459\u045a\u045b\u045c\u045e\u045f\u042a\u2116\u0402]$*);^-/\u0490\u0401\u0404\u0405\u0406\u0407\u0408\u0409|,%_>?\u040a\u040b\u040c\u00ad\u040e\u040f\u044e\u0430\u0431`:#@'=\"\u0446abcdefghi\u0434\u0435\u0444\u0433\u0445\u0438\u0439jklmnopqr\u043a\u043b\u043c\u043d\u043e\u043f\u044f~stuvwxyz\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413{ABCDEFGHI\u0425\u0418\u0419\u041a\u041b\u041c}JKLMNOPQR\u041d\u041e\u041f\u042f\u0420\u0421\\\u00a7STUVWXYZ\u0422\u0423\u0416\u0412\u042c\u042b0123456789\u0417\u0428\u042d\u0429\u0427\u009f",
|
||||
Aliases: []string{"ibm-1123_P100-1995", "ibm-1123", "cp1123", "1123"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1124_P100-1996",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0401\u0402\u0490\u0404\u0405\u0406\u0407\u0408\u0409\u040a\u040b\u040c\u00ad\u040e\u040f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u2116\u0451\u0452\u0491\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u00a7\u045e\u045f",
|
||||
Aliases: []string{"ibm-1124_P100-1996", "ibm-1124", "cp1124", "1124"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1125_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0401\u0451\u0490\u0491\u0404\u0454\u0406\u0456\u0407\u0457\u00f7\u00b1\u2116\u00a4\u25a0\u00a0",
|
||||
Aliases: []string{"ibm-1125_P100-1997", "ibm-1125", "cp1125"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1129_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u0153\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u0178\u00b5\u00b6\u00b7\u0152\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u0102\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u0300\u00cd\u00ce\u00cf\u0110\u00d1\u0309\u00d3\u00d4\u01a0\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u01af\u0303\u00df\u00e0\u00e1\u00e2\u0103\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u0301\u00ed\u00ee\u00ef\u0111\u00f1\u0323\u00f3\u00f4\u01a1\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u01b0\u20ab\u00ff",
|
||||
Aliases: []string{"ibm-1129_P100-1997", "ibm-1129"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1130_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u0103\u00e5\u00e7\u00f1[.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u0303\u00df]$*);^-/\u00c2\u00c4\u00c0\u00c1\u0102\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u20ab`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u0111\u0309\u0300\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u0152\u00c6\u00a4\u00b5~stuvwxyz\u00a1\u00bf\u0110\u0323\u0301\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u0153\u0178\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u01b0\u00f3\u01a1}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u01af\u00d3\u01a00123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1130_P100-1997", "ibm-1130"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1131_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1c\x1b\x7f\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x1a\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0401\u0451\u0404\u0454\u0407\u0457\u040e\u045e\u0406\u0456\u00b7\u00a4\u0490\u0491\u2219\u00a0",
|
||||
Aliases: []string{"ibm-1131_P100-1997", "ibm-1131", "cp1131"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1132_P100-1998",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0e81\u0e82\u0e84\u0e87\u0e88\u0eaa\u0e8a[\u00a2.<(+|&\ufffd\u0e8d\u0e94\u0e95\u0e96\u0e97\u0e99\u0e9a]!$*);\u00ac-/\u0e9b\u0e9c\u0e9d\u0e9e\u0e9f\u0ea1\u0ea2^\u00a6,%_>?\u20ad\ufffd\u0ea3\u0ea5\u0ea7\u0eab\u0ead\u0eae\ufffd`:#@'=\"\ufffdabcdefghi\ufffd\ufffd\u0eaf\u0eb0\u0eb2\u0eb3\ufffdjklmnopqr\u0eb4\u0eb5\u0eb6\u0eb7\u0eb8\u0eb9\ufffd~stuvwxyz\u0ebc\u0eb1\u0ebb\u0ebd\ufffd\ufffd\u0ed0\u0ed1\u0ed2\u0ed3\u0ed4\u0ed5\u0ed6\u0ed7\u0ed8\u0ed9\ufffd\u0ec0\u0ec1\u0ec2\u0ec3\u0ec4{ABCDEFGHI\ufffd\u0ec8\u0ec9\u0eca\u0ecb\u0ecc}JKLMNOPQR\u0ecd\u0ec6\ufffd\u0edc\u0edd\ufffd\\\ufffdSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-1132_P100-1998", "ibm-1132"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1133_P100-1997",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\ufffd\u0e81\u0e82\u0e84\u0e87\u0e88\u0eaa\u0e8a\u0e8d\u0e94\u0e95\u0e96\u0e97\u0e99\u0e9a\u0e9b\u0e9c\u0e9d\u0e9e\u0e9f\u0ea1\u0ea2\u0ea3\u0ea5\u0ea7\u0eab\u0ead\u0eae\ufffd\ufffd\ufffd\u0eaf\u0eb0\u0eb2\u0eb3\u0eb4\u0eb5\u0eb6\u0eb7\u0eb8\u0eb9\u0ebc\u0eb1\u0ebb\u0ebd\ufffd\ufffd\ufffd\u0ec0\u0ec1\u0ec2\u0ec3\u0ec4\u0ec8\u0ec9\u0eca\u0ecb\u0ecc\u0ecd\u0ec6\ufffd\u0edc\u0eddk\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0ed0\u0ed1\u0ed2\u0ed3\u0ed4\u0ed5\u0ed6\u0ed7\u0ed8\u0ed9\ufffd\ufffd\u00a2\u00ac\u00a6\u00a0",
|
||||
Aliases: []string{"ibm-1133_P100-1997", "ibm-1133"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1137_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0901\u0902\u0903\u0905\u0906\u0907\u0908\u0909\u090a.<(+|&\u090b\u090c\u090d\u090e\u090f\u0910\u0911\u0912\u0913!$*);^-/\u0914\u0915\u0916\u0917\u0918\u0919\u091a\u091b\u091c,%_>?\u091d\u091e\u091f\u0920\u0921\u0922\u0923\u0924\u0925`:#@'=\"\u0926abcdefghi\u0927\u0928\u092a\u092b\u092c\u092d\u092ejklmnopqr\u092f\u0930\u0932\u0933\u0935\u0936\u200c~stuvwxyz\u0937\u0938\u0939[\u093c\u093d\u093e\u093f\u0940\u0941\u0942\u0943\u0944\u0945\u0946\u0947\u0948\u0949\u094a]\u094b\u094c{ABCDEFGHI\u094d\u0950\u0951\u0952\ufffd\ufffd}JKLMNOPQR\u0960\u0961\u0962\u0963\u0964\u0965\\\u200dSTUVWXYZ\u0966\u0967\u0968\u0969\u096a\u096b0123456789\u096c\u096d\u096e\u096f\u0970\u009f",
|
||||
Aliases: []string{"ibm-1137_P100-1999", "ibm-1137"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1140_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00a2.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!$*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5~stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae^\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1140_P100-1997", "ibm-1140", "IBM01140", "CCSID01140", "CP01140", "cp1140", "ebcdic-us-37+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1141_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00c4.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec~\u00dc$*);^-/\u00c2[\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#\u00a7'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5\u00dfstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9@\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00fcJKLMNOPQR\u00b9\u00fb}\u00f9\u00fa\u00ff\u00d6\u00f7STUVWXYZ\u00b2\u00d4\\\u00d2\u00d3\u00d50123456789\u00b3\u00db]\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1141_P100-1997", "ibm-1141", "IBM01141", "CCSID01141", "CP01141", "cp1141", "ebcdic-de-273+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1142_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3}\u00e7\u00f1#.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u20ac\u00c5*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f8,%_>?\u00a6\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:\u00c6\u00d8'=\"@abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba{\u00b8[]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e6ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1142_P100-1997", "ibm-1142", "IBM01142", "CCSID01142", "CP01142", "cp1142", "ebcdic-dk-277+euro", "ebcdic-no-277+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1143_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3}\u00e7\u00f1\u00a7.<(+!&`\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u20ac\u00c5*);^-/\u00c2#\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f6,%_>?\u00f8\\\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00e9:\u00c4\u00d6'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9[\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\u00c9\u00f7STUVWXYZ\u00b2\u00d4@\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1143_P100-1997", "ibm-1143", "IBM01143", "CCSID01143", "CP01143", "cp1143", "ebcdic-fi-278+euro", "ebcdic-se-278+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1144_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4{\u00e1\u00e3\u00e5\\\u00f1\u00b0.<(+!&]\u00ea\u00eb}\u00ed\u00ee\u00ef~\u00df\u00e9$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f2,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00f9:\u00a3\u00a7'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1[jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5\u00ecstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2#\u00a5\u00b7\u00a9@\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e0ABCDEFGHI\u00ad\u00f4\u00f6\u00a6\u00f3\u00f5\u00e8JKLMNOPQR\u00b9\u00fb\u00fc`\u00fa\u00ff\u00e7\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1144_P100-1997", "ibm-1144", "IBM01144", "CCSID01144", "CP01144", "cp1144", "ebcdic-it-280+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1145_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00a6[.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df]$*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7#\u00f1,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:\u00d1@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5\u00a8stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be^!\u00af~\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1145_P100-1997", "ibm-1145", "IBM01145", "CCSID01145", "CP01145", "cp1145", "ebcdic-es-284+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1146_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1$.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!\u00a3*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5\u00afstuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2[\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be^]~\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1146_P100-1997", "ibm-1146", "IBM01146", "CCSID01146", "CP01146", "cp1146", "ebcdic-gb-285+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1147_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4@\u00e1\u00e3\u00e5\\\u00f1\u00b0.<(+!&{\u00ea\u00eb}\u00ed\u00ee\u00ef\u00ec\u00df\u00a7$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00f9,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00b5:\u00a3\u00e0'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1[jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac`\u00a8stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2#\u00a5\u00b7\u00a9]\u00b6\u00bc\u00bd\u00be\u00ac|\u00af~\u00b4\u00d7\u00e9ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5\u00e8JKLMNOPQR\u00b9\u00fb\u00fc\u00a6\u00fa\u00ff\u00e7\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1147_P100-1997", "ibm-1147", "IBM01147", "CCSID01147", "CP01147", "cp1147", "ebcdic-fr-297+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1148_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1[.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df]$*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5~stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1148_P100-1997", "ibm-1148", "IBM01148", "CCSID01148", "CP01148", "cp1148", "ebcdic-international-500+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1149_P100-1997",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00de.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u00c6$*);\u00d6-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00f0:#\u00d0'=\"\u00d8abcdefghi\u00ab\u00bb`\u00fd{\u00b1\u00b0jklmnopqr\u00aa\u00ba}\u00b8]\u20ac\u00b5\u00f6stuvwxyz\u00a1\u00bf@\u00dd[\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\\\u00d7\u00feABCDEFGHI\u00ad\u00f4~\u00f2\u00f3\u00f5\u00e6JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\u00b4\u00f7STUVWXYZ\u00b2\u00d4^\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1149_P100-1997", "ibm-1149", "IBM01149", "CCSID01149", "CP01149", "cp1149", "ebcdic-is-871+euro"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1153_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u0163\u00e1\u0103\u010d\u00e7\u0107[.<(+!&\u00e9\u0119\u00eb\u016f\u00ed\u00ee\u013e\u013a\u00df]$*);^-/\u00c2\u00c4\u02dd\u00c1\u0102\u010c\u00c7\u0106|,%_>?\u02c7\u00c9\u0118\u00cb\u016e\u00cd\u00ce\u013d\u0139`:#@'=\"\u02d8abcdefghi\u015b\u0148\u0111\u00fd\u0159\u015f\u00b0jklmnopqr\u0142\u0144\u0161\u00b8\u02db\u20ac\u0105~stuvwxyz\u015a\u0147\u0110\u00dd\u0158\u015e\u02d9\u0104\u017c\u0162\u017b\u00a7\u017e\u017a\u017d\u0179\u0141\u0143\u0160\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u0155\u00f3\u0151}JKLMNOPQR\u011a\u0171\u00fc\u0165\u00fa\u011b\\\u00f7STUVWXYZ\u010f\u00d4\u00d6\u0154\u00d3\u01500123456789\u010e\u0170\u00dc\u0164\u00da\u009f",
|
||||
Aliases: []string{"ibm-1153_P100-1999", "ibm-1153"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1154_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0452\u0453\u0451\u0454\u0455\u0456\u0457\u0458[.<(+!&\u0459\u045a\u045b\u045c\u045e\u045f\u042a\u2116\u0402]$*);^-/\u0403\u0401\u0404\u0405\u0406\u0407\u0408\u0409|,%_>?\u040a\u040b\u040c\u00ad\u040e\u040f\u044e\u0430\u0431`:#@'=\"\u0446abcdefghi\u0434\u0435\u0444\u0433\u0445\u0438\u0439jklmnopqr\u043a\u043b\u043c\u043d\u043e\u043f\u044f~stuvwxyz\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413{ABCDEFGHI\u0425\u0418\u0419\u041a\u041b\u041c}JKLMNOPQR\u041d\u041e\u041f\u042f\u0420\u0421\\\u20acSTUVWXYZ\u0422\u0423\u0416\u0412\u042c\u042b0123456789\u0417\u0428\u042d\u0429\u0427\u009f",
|
||||
Aliases: []string{"ibm-1154_P100-1999", "ibm-1154"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1155_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5{\u00f1\u00c7.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u011e\u0130*);^-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5[\u00d1\u015f,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u0131:\u00d6\u015e'=\u00dc\u00d8abcdefghi\u00ab\u00bb}`\u00a6\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5\u00f6stuvwxyz\u00a1\u00bf]$@\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e7ABCDEFGHI\u00ad\u00f4~\u00f2\u00f3\u00f5\u011fJKLMNOPQR\u00b9\u00fb\\\u00f9\u00fa\u00ff\u00fc\u00f7STUVWXYZ\u00b2\u00d4#\u00d2\u00d3\u00d50123456789\u00b3\u00db\"\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1155_P100-1999", "ibm-1155"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1156_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0161\u00e4\u0105\u012f\u016b\u00e5\u0113\u017e\u00a2.<(+|&\u00e9\u0119\u0117\u010d\u0173\u201e\u201c\u0123\u00df!$*);\u00ac-/\u0160\u00c4\u0104\u012e\u016a\u00c5\u0112\u017d\u00a6,%_>?\u00f8\u00c9\u0118\u0116\u010c\u0172\u012a\u013b\u0122`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u0101\u017c\u0144\u00b1\u00b0jklmnopqr\u0156\u0157\u00e6\u0137\u00c6\u20ac\u00b5~stuvwxyz\u201d\u017a\u0100\u017b\u0143\u00ae^\u00a3\u012b\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u0179\u0136\u013c\u00d7{ABCDEFGHI\u00ad\u014d\u00f6\u0146\u00f3\u00f5}JKLMNOPQR\u00b9\u0107\u00fc\u0142\u015b\u2019\\\u00f7STUVWXYZ\u00b2\u014c\u00d6\u0145\u00d3\u00d50123456789\u00b3\u0106\u00dc\u0141\u015a\u009f",
|
||||
Aliases: []string{"ibm-1156_P100-1999", "ibm-1156"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1157_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2{\u00e0\u00e1\u00e3}\u00e7\u00f1\u00a7.<(+!&`\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df\u20ac\u00c5*);^-/\u00c2#\u00c0\u00c1\u00c3$\u00c7\u00d1\u00f6,%_>?\u00f8\\\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc\u00e9:\u00c4\u00d6'=\"\u00d8abcdefghi\u00ab\u00bb\u0161\u00fd\u017e\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6]\u00b5\u00fcstuvwxyz\u00a1\u00bf\u0160\u00dd\u017d\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9[\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u00a8\u00b4\u00d7\u00e4ABCDEFGHI\u00ad\u00f4\u00a6\u00f2\u00f3\u00f5\u00e5JKLMNOPQR\u00b9\u00fb~\u00f9\u00fa\u00ff\u00c9\u00f7STUVWXYZ\u00b2\u00d4@\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1157_P100-1999", "ibm-1157"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1158_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0452\u0491\u0451\u0454\u0455\u0456\u0457\u0458[.<(+!&\u0459\u045a\u045b\u045c\u045e\u045f\u042a\u2116\u0402]$*);^-/\u0490\u0401\u0404\u0405\u0406\u0407\u0408\u0409|,%_>?\u040a\u040b\u040c\u00ad\u040e\u040f\u044e\u0430\u0431`:#@'=\"\u0446abcdefghi\u0434\u0435\u0444\u0433\u0445\u0438\u0439jklmnopqr\u043a\u043b\u043c\u043d\u043e\u043f\u044f~stuvwxyz\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413{ABCDEFGHI\u0425\u0418\u0419\u041a\u041b\u041c}JKLMNOPQR\u041d\u041e\u041f\u042f\u0420\u0421\\\u20acSTUVWXYZ\u0422\u0423\u0416\u0412\u042c\u042b0123456789\u0417\u0428\u042d\u0429\u0427\u009f",
|
||||
Aliases: []string{"ibm-1158_P100-1999", "ibm-1158"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1160_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07[\u00a2.<(+|&\u0e48\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e]!$*);\u00ac-/\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15^\u00a6,%_>?\u0e3f\u0e4e\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c`:#@'=\"\u0e4fabcdefghi\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e5ajklmnopqr\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e5b~stuvwxyz\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34{ABCDEFGHI\u0e49\u0e35\u0e36\u0e37\u0e38\u0e39}JKLMNOPQR\u0e3a\u0e40\u0e41\u0e42\u0e43\u0e44\\\u0e4aSTUVWXYZ\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a0123456789\u0e4b\u0e4c\u0e4d\u0e4b\u20ac\u009f",
|
||||
Aliases: []string{"ibm-1160_P100-1999", "ibm-1160"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1162_P100-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u20ac\u0081\u0082\u0083\u0084\u2026\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u0e01\u0e02\u0e03\u0e04\u0e05\u0e06\u0e07\u0e08\u0e09\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e1b\u0e1c\u0e1d\u0e1e\u0e1f\u0e20\u0e21\u0e22\u0e23\u0e24\u0e25\u0e26\u0e27\u0e28\u0e29\u0e2a\u0e2b\u0e2c\u0e2d\u0e2e\u0e2f\u0e30\u0e31\u0e32\u0e33\u0e34\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\ufffd\ufffd\ufffd\ufffd\u0e3f\u0e40\u0e41\u0e42\u0e43\u0e44\u0e45\u0e46\u0e47\u0e48\u0e49\u0e4a\u0e4b\u0e4c\u0e4d\u0e4e\u0e4f\u0e50\u0e51\u0e52\u0e53\u0e54\u0e55\u0e56\u0e57\u0e58\u0e59\u0e5a\u0e5b\ufffd\ufffd\ufffd\ufffd",
|
||||
Aliases: []string{"ibm-1162_P100-1999", "ibm-1162"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1164_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u0103\u00e5\u00e7\u00f1[.<(+!&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u0303\u00df]$*);^-/\u00c2\u00c4\u00c0\u00c1\u0102\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u20ab`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u0111\u0309\u0300\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u0152\u00c6\u20ac\u00b5~stuvwxyz\u00a1\u00bf\u0110\u0323\u0301\u00ae\u00a2\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be\u00ac|\u00af\u0153\u0178\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u01b0\u00f3\u01a1}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u01af\u00d3\u01a00123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ibm-1164_P100-1999", "ibm-1164"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-4517_P100-2005",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\ufe7c\ufe7d\u0640\u200b\ufe80\ufe81\ufe82\ufe83\u00b0.<(+!&\ufe84\ufe85\ufffd\ufffd\ufe8b\ufe8d\ufe8e\ufe8f\ufe91\u00a7$*);^-/\ufe93\ufe95\ufe97\ufe99\ufe9b\ufe9d\ufe9f\ufea1\u00fa,%_>?\ufea3\ufea5\ufea7\ufea9\ufeab\ufead\ufeaf\ufeb1\ufeb3\u00a3:\u00b5\u00e1'=\"\ufeb5abcdefghi\ufeb7\ufeb9\ufebb\ufebd\ufebf\ufec3\ufec7jklmnopqr\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\u00a8stuvwxyz\ufed0\ufed1\ufed3\ufed5\ufed7\ufed9\ufedb\ufedd\ufef5\ufef6\ufef7\ufef8\ufffd\ufffd\ufefb\ufefc\ufedf\ufee1\ufee3\ufee5\ufee7\ufee9\u00e9ABCDEFGHI\u00ad\ufeeb\ufffd\ufeec\ufffd\ufeed\u00e8JKLMNOPQR\ufeef\ufef0\ufef1\ufef2\ufef3\ufffd\u00e7\u2007STUVWXYZ\u00f7\u060c\ufffd\u00d7\u061f\u061b0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-4517_P100-2005", "ibm-4517"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-4899_P100-1998",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd$.<(+|\u05d0\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd!\u00a2*);\u00ac-/\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd,%_>?\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd:#@'=\"\ufffd\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\ufffd\ufffd\u20ac\ufffd\u20aa\ufffd\ufffd\ufffd\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdABCDEFGHI\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdJKLMNOPQR\ufffd\u202d\u202e\u202c\ufffd\ufffd\ufffd\ufffdSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\u202a\u202b\u200e\u200f\u009f",
|
||||
Aliases: []string{"ibm-4899_P100-1998", "ibm-4899"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-4909_P100-1999",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0\u2018\u2019\u00a3\u20ac\ufffd\u00a6\u00a7\u00a8\u00a9\ufffd\u00ab\u00ac\u00ad\ufffd\u2015\u00b0\u00b1\u00b2\u00b3\u00b4\u0385\u0386\u0387\u0388\u0389\u038a\u00bb\u038c\u00bd\u038e\u038f\u0390\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\ufffd\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\ufffd",
|
||||
Aliases: []string{"ibm-4909_P100-1999", "ibm-4909"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-4971_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399[.<(+!&\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3]$*);^-/\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab|,%_>?\u00a8\u0386\u0388\u0389\u00a0\u038a\u038c\u038e\u038f`:#@'=\"\u0385abcdefghi\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u00b0jklmnopqr\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u00b4~stuvwxyz\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u00a3\u03ac\u03ad\u03ae\u03ca\u03af\u03cc\u03cd\u03cb\u03ce\u03c2\u03c4\u03c5\u03c6\u03c7\u03c8{ABCDEFGHI\u00ad\u03c9\u0390\u03b0\u2018\u2015}JKLMNOPQR\u00b1\u00bd\ufffd\u0387\u2019\u00a6\\\ufffdSTUVWXYZ\u00b2\u00a7\ufffd\ufffd\u00ab\u00ac0123456789\u00b3\u00a9\u20ac\ufffd\u00bb\u009f",
|
||||
Aliases: []string{"ibm-4971_P100-1999", "ibm-4971"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-5123_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \ufffd\uff61\uff62\uff63\uff64\uff65\uff66\uff67\uff68\u00a2.<(+|&\uff69\uff6a\uff6b\uff6c\uff6d\uff6e\uff6f\uff70\uff71!$*);\u00ac-/\uff72\uff73\uff74\uff75\uff76\uff77\uff78\uff79\ufffd,%_>?\uff7a\uff7b\uff7c\uff7d\uff7e\uff7f\uff80\uff81\uff82`:#@'=\"\ufffdabcdefghi\uff83\uff84\uff85\uff86\uff87\uff88\ufffdjklmnopqr\uff89\uff8a\uff8b\uff8c\uff8d\uff8e\u203e~stuvwxyz\uff8f\uff90\uff91[\uff92\uff93^\u00a3\u00a5\uff94\uff95\uff96\uff97\uff98\uff99\uff9a\uff9b\uff9c\uff9d]\uff9e\uff9f{ABCDEFGHI\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd}JKLMNOPQR\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\\\u20acSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-5123_P100-1999", "ibm-5123"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-8482_P100-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \uff61\uff62\uff63\uff64\uff65\uff66\uff67\uff68\uff69\u00a3.<(+|&\uff6a\uff6b\uff6c\uff6d\uff6e\uff6f\ufffd\uff70\ufffd!\u00a5*);\u00ac-/abcdefgh\ufffd,%_>?[ijklmnop`:#@'=\"]\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78\uff79\uff7aq\uff7b\uff7c\uff7d\uff7e\uff7f\uff80\uff81\uff82\uff83\uff84\uff85\uff86\uff87\uff88\uff89r\ufffd\uff8a\uff8b\uff8c~\u203e\uff8d\uff8e\uff8f\uff90\uff91\uff92\uff93\uff94\uff95s\uff96\uff97\uff98\uff99^\u00a2\\tuvwxyz\uff9a\uff9b\uff9c\uff9d\uff9e\uff9f{ABCDEFGHI\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd}JKLMNOPQR\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd$\u20acSTUVWXYZ\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\ufffd\ufffd\ufffd\ufffd\ufffd\u009f",
|
||||
Aliases: []string{"ibm-8482_P100-1999", "ibm-8482"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-9067_X100-2005",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399[.<(+!&\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3]$*);^-/\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab|,%_>?\u00a8\u0386\u0388\u0389\u00a0\u038a\u038c\u038e\u038f`:#@'=\"\u0385abcdefghi\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u00b0jklmnopqr\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u00b4~stuvwxyz\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u00a3\u03ac\u03ad\u03ae\u03ca\u03af\u03cc\u03cd\u03cb\u03ce\u03c2\u03c4\u03c5\u03c6\u03c7\u03c8{ABCDEFGHI\u00ad\u03c9\u0390\u03b0\u2018\u2015}JKLMNOPQR\u00b1\u00bd\ufffd\u0387\u2019\u00a6\\\u20afSTUVWXYZ\u00b2\u00a7\u037a\ufffd\u00ab\u00ac0123456789\u00b3\u00a9\u20ac\ufffd\u00bb\u009f",
|
||||
Aliases: []string{"ibm-9067_X100-2005", "ibm-9067"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-12712_P100-1998",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u00a2.<(+|&\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1!$*);\u00ac-/\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u00a6,%_>?\ufffd\u05ea\ufffd\ufffd\u00a0\ufffd\ufffd\ufffd\u2017`:#@'=\"\ufffdabcdefghi\u00ab\u00bb\ufffd\ufffd\ufffd\u00b1\u00b0jklmnopqr\ufffd\ufffd\u20ac\u00b8\u20aa\u00a4\u00b5~stuvwxyz\ufffd\ufffd\ufffd\ufffd\ufffd\u00ae^\u00a3\u00a5\u2022\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u203e\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\ufffd\ufffd\ufffd\ufffd\ufffd}JKLMNOPQR\u00b9\u202d\u202e\u202c\ufffd\ufffd\\\u00f7STUVWXYZ\u00b2\ufffd\ufffd\ufffd\ufffd\ufffd0123456789\u00b3\u202a\u202b\u200e\u200f\u009f",
|
||||
Aliases: []string{"ibm-12712_P100-1998", "ibm-12712", "ebcdic-he"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-16804_X110-1999",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\u0085\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u0651\ufe7d\u0640\u200b\u0621\u0622\ufe82\u0623\u00a2.<(+|&\ufe84\u0624\ufffd\ufffd\u0626\u0627\ufe8e\u0628\ufe91!$*);\u00ac-/\u0629\u062a\ufe97\u062b\ufe9b\u062c\ufe9f\u062d\u00a6,%_>?\ufea3\u062e\ufea7\u062f\u0630\u0631\u0632\u0633\ufeb3\u060c:#@'=\"\u0634abcdefghi\ufeb7\u0635\ufebb\u0636\ufebf\u0637\u0638jklmnopqr\u0639\ufeca\ufecb\ufecc\u063a\ufece\ufecf\u00f7stuvwxyz\ufed0\u0641\ufed3\u0642\ufed7\u0643\ufedb\u0644\ufef5\ufef6\ufef7\ufef8\ufffd\ufffd\ufefb\ufefc\ufedf\u0645\ufee3\u0646\ufee7\u0647\u061bABCDEFGHI\u00ad\ufeeb\ufffd\ufeec\ufffd\u0648\u061fJKLMNOPQR\u0649\ufef0\u064a\ufef2\ufef3\u0660\u00d7\u2007STUVWXYZ\u0661\u0662\ufffd\u0663\u0664\u06650123456789\u20ac\u0666\u0667\u0668\u0669\u009f",
|
||||
Aliases: []string{"ibm-16804_X110-1999", "ibm-16804", "ebcdic-ar"},
|
||||
},
|
||||
{
|
||||
Name: "KOI8-R",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u2500\u2502\u250c\u2510\u2514\u2518\u251c\u2524\u252c\u2534\u253c\u2580\u2584\u2588\u258c\u2590\u2591\u2592\u2593\u2320\u25a0\u2219\u221a\u2248\u2264\u2265\u00a0\u2321\u00b0\u00b2\u00b7\u00f7\u2550\u2551\u2552\u0451\u2553\u2554\u2555\u2556\u2557\u2558\u2559\u255a\u255b\u255c\u255d\u255e\u255f\u2560\u2561\u0401\u2562\u2563\u2564\u2565\u2566\u2567\u2568\u2569\u256a\u256b\u256c\u00a9\u044e\u0430\u0431\u0446\u0434\u0435\u0444\u0433\u0445\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u044f\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413\u0425\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u042f\u0420\u0421\u0422\u0423\u0416\u0412\u042c\u042b\u0417\u0428\u042d\u0429\u0427\u042a",
|
||||
Aliases: []string{"csKOI8R"},
|
||||
},
|
||||
{
|
||||
Name: "KOI8-U",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u2500\u2502\u250c\u2510\u2514\u2518\u251c\u2524\u252c\u2534\u253c\u2580\u2584\u2588\u258c\u2590\u2591\u2592\u2593\u2320\u25a0\u2219\u221a\u2248\u2264\u2265\u00a0\u2321\u00b0\u00b2\u00b7\u00f7\u2550\u2551\u2552\u0451\u0454\u2554\u0456\u0457\u2557\u2558\u2559\u255a\u255b\u0491\u255d\u255e\u255f\u2560\u2561\u0401\u0404\u2563\u0406\u0407\u2566\u2567\u2568\u2569\u256a\u0490\u256c\u00a9\u044e\u0430\u0431\u0446\u0434\u0435\u0444\u0433\u0445\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u044f\u0440\u0441\u0442\u0443\u0436\u0432\u044c\u044b\u0437\u0448\u044d\u0449\u0447\u044a\u042e\u0410\u0411\u0426\u0414\u0415\u0424\u0413\u0425\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u042f\u0420\u0421\u0422\u0423\u0416\u0412\u042c\u042b\u0417\u0428\u042d\u0429\u0427\u042a",
|
||||
},
|
||||
{
|
||||
Name: "ibm-1051_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\ufffd\u00c0\u00c2\u00c8\u00ca\u00cb\u00ce\u00cf\u00b4`\u02c6\u00a8\u02dc\u00d9\u00db\u00a3\u203e\u00dd\u00fd\u02da\u00c7\u00e7\u00d1\u00f1\u00a1\u00bf\u00a4\u00a3\u00a5\u00a7\u0192\u00a2\u00e2\u00ea\u00f4\u00fb\u00e1\u00e9\u00f3\u00fa\u00e0\u00e8\u00f2\u00f9\u00e4\u00eb\u00f6\u00fc\u00c5\u00ee\u00d8\u00c6\u00e5\u00ed\u00f8\u00e6\u00c4\u00ec\u00d6\u00dc\u00c9\u00ef\u00df\u00d4\u00c1\u00c3\u00e3\u00d0\u00f0\u00cd\u00cc\u00d3\u00d2\u00d5\u00f5\u0160\u0161\u00da\u0178\u00ff\u00de\u00fe\u00b7\u03bc\u00b6\u00be-\u00bc\u00bd\u00aa\u00ba\u00ab\u25a0\u00bb\u00b1\ufffd",
|
||||
Aliases: []string{"ibm-1051_P100-1995", "ibm-1051", "hp-roman8", "roman8", "r8", "csHPRoman8"},
|
||||
},
|
||||
{
|
||||
Name: "ibm-1276_P100-1995",
|
||||
SubstitutionChar: '?',
|
||||
Repertoire: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&\u2019()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\u2018abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\ufffd\u00a1\u00a2\u00a3\u2044\u00a5\u0192\u00a7\u00a4'\u201c\u00ab\u2039\u203a\ufb01\ufb02\ufffd\u2013\u2020\u2021\u00b7\ufffd\u00b6\u2022\u201a\u201e\u201d\u00bb\u2026\u2030\ufffd\u00bf\ufffd`\u00b4\u02c6\u02dc\u00af\u02d8\u02d9\u00a8\ufffd\u02da\u00b8\ufffd\u02dd\u02db\u02c7\u2014\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u00c6\ufffd\u00aa\ufffd\ufffd\ufffd\ufffd\u0141\u00d8\u0152\u00ba\ufffd\ufffd\ufffd\ufffd\ufffd\u00e6\ufffd\ufffd\ufffd\u0131\ufffd\ufffd\u0142\u00f8\u0153\u00df\ufffd\ufffd\ufffd\ufffd",
|
||||
Aliases: []string{"ibm-1276_P100-1995", "ibm-1276", "Adobe-Standard-Encoding", "csAdobeStandardEncoding"},
|
||||
},
|
||||
{
|
||||
Name: "ebcdic-xml-us",
|
||||
SubstitutionChar: 0x6f,
|
||||
Repertoire: "\x00\x01\x02\x03\u009c\t\u0086\x7f\u0097\u008d\u008e\v\f\r\x0e\x0f\x10\x11\x12\x13\u009d\n\b\u0087\x18\x19\u0092\u008f\x1c\x1d\x1e\x1f\u0080\u0081\u0082\u0083\u0084\n\x17\x1b\u0088\u0089\u008a\u008b\u008c\x05\x06\a\u0090\u0091\x16\u0093\u0094\u0095\u0096\x04\u0098\u0099\u009a\u009b\x14\x15\u009e\x1a \u00a0\u00e2\u00e4\u00e0\u00e1\u00e3\u00e5\u00e7\u00f1\u00a2.<(+|&\u00e9\u00ea\u00eb\u00e8\u00ed\u00ee\u00ef\u00ec\u00df!$*);\u00ac-/\u00c2\u00c4\u00c0\u00c1\u00c3\u00c5\u00c7\u00d1\u00a6,%_>?\u00f8\u00c9\u00ca\u00cb\u00c8\u00cd\u00ce\u00cf\u00cc`:#@'=\"\u00d8abcdefghi\u00ab\u00bb\u00f0\u00fd\u00fe\u00b1\u00b0jklmnopqr\u00aa\u00ba\u00e6\u00b8\u00c6\u20ac\u00b5~stuvwxyz\u00a1\u00bf\u00d0\u00dd\u00de\u00ae^\u00a3\u00a5\u00b7\u00a9\u00a7\u00b6\u00bc\u00bd\u00be[]\u00af\u00a8\u00b4\u00d7{ABCDEFGHI\u00ad\u00f4\u00f6\u00f2\u00f3\u00f5}JKLMNOPQR\u00b9\u00fb\u00fc\u00f9\u00fa\u00ff\\\u00f7STUVWXYZ\u00b2\u00d4\u00d6\u00d2\u00d3\u00d50123456789\u00b3\u00db\u00dc\u00d9\u00da\u009f",
|
||||
Aliases: []string{"ebcdic-xml-us"},
|
||||
},
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for ASCII and ISO-8859-1
|
||||
|
||||
func init() {
|
||||
for i := 0; i < len(asciiCharsets); i++ {
|
||||
RegisterCharset(&asciiCharsets[i])
|
||||
}
|
||||
}
|
||||
|
||||
var asciiCharsets = []Charset{
|
||||
{
|
||||
Name: "US-ASCII",
|
||||
NewDecoder: func() Decoder { return decodeASCIIRune },
|
||||
NewEncoder: func() Encoder { return encodeASCIIRune },
|
||||
Aliases: []string{"ASCII", "US", "ISO646-US", "IBM367", "cp367", "ANSI_X3.4-1968", "iso-ir-6", "ANSI_X3.4-1986", "ISO_646.irv:1991", "csASCII"},
|
||||
},
|
||||
{
|
||||
Name: "ISO-8859-1",
|
||||
NewDecoder: func() Decoder { return decodeLatin1Rune },
|
||||
NewEncoder: func() Encoder { return encodeLatin1Rune },
|
||||
Aliases: []string{"latin1", "ISO Latin 1", "IBM819", "cp819", "ISO_8859-1:1987", "iso-ir-100", "l1", "csISOLatin1"},
|
||||
},
|
||||
}
|
||||
|
||||
func decodeASCIIRune(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b > 127 {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
func encodeASCIIRune(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if c < 128 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func decodeLatin1Rune(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
return rune(p[0]), 1, SUCCESS
|
||||
}
|
||||
|
||||
func encodeLatin1Rune(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if c < 256 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,89 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for Big 5 encoding.
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "Big5",
|
||||
Aliases: []string{"csBig5"},
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeBig5Rune
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
big5Once.Do(reverseBig5Table)
|
||||
return encodeBig5Rune
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeBig5Rune(p []byte) (r rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b < 128 {
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
c := int(p[0])<<8 + int(p[1])
|
||||
c = int(big5ToUnicode[c])
|
||||
if c > 0 {
|
||||
return rune(c), 2, SUCCESS
|
||||
}
|
||||
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeBig5Rune(p []byte, r rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if r < 128 {
|
||||
p[0] = byte(r)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if r < 0x10000 {
|
||||
c := unicodeToBig5[r]
|
||||
if c > 0 {
|
||||
p[0] = byte(c >> 8)
|
||||
p[1] = byte(c)
|
||||
return 2, SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
var big5Once sync.Once
|
||||
|
||||
var unicodeToBig5 []uint16
|
||||
|
||||
func reverseBig5Table() {
|
||||
unicodeToBig5 = make([]uint16, 65536)
|
||||
|
||||
for big5, unicode := range big5ToUnicode {
|
||||
if unicode > 0 {
|
||||
unicodeToBig5[unicode] = uint16(big5)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
// This package is a character-set conversion library for Go.
|
||||
//
|
||||
// (DEPRECATED: use code.google.com/p/go.text/encoding, perhaps along with
|
||||
// code.google.com/p/go.net/html/charset)
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Status is the type for the status return value from a Decoder or Encoder.
|
||||
type Status int
|
||||
|
||||
const (
|
||||
// SUCCESS means that the character was converted with no problems.
|
||||
SUCCESS = Status(iota)
|
||||
|
||||
// INVALID_CHAR means that the source contained invalid bytes, or that the character
|
||||
// could not be represented in the destination encoding.
|
||||
// The Encoder or Decoder should have output a substitute character.
|
||||
INVALID_CHAR
|
||||
|
||||
// NO_ROOM means there were not enough input bytes to form a complete character,
|
||||
// or there was not enough room in the output buffer to write a complete character.
|
||||
// No bytes were written, and no internal state was changed in the Encoder or Decoder.
|
||||
NO_ROOM
|
||||
|
||||
// STATE_ONLY means that bytes were read or written indicating a state transition,
|
||||
// but no actual character was processed. (Examples: byte order marks, ISO-2022 escape sequences)
|
||||
STATE_ONLY
|
||||
)
|
||||
|
||||
// A Decoder is a function that decodes a character set, one character at a time.
|
||||
// It works much like utf8.DecodeRune, but has an aditional status return value.
|
||||
type Decoder func(p []byte) (c rune, size int, status Status)
|
||||
|
||||
// An Encoder is a function that encodes a character set, one character at a time.
|
||||
// It works much like utf8.EncodeRune, but has an additional status return value.
|
||||
type Encoder func(p []byte, c rune) (size int, status Status)
|
||||
|
||||
// A Charset represents a character set that can be converted, and contains functions
|
||||
// to create Converters to encode and decode strings in that character set.
|
||||
type Charset struct {
|
||||
// Name is the character set's canonical name.
|
||||
Name string
|
||||
|
||||
// Aliases returns a list of alternate names.
|
||||
Aliases []string
|
||||
|
||||
// NewDecoder returns a Decoder to convert from the charset to Unicode.
|
||||
NewDecoder func() Decoder
|
||||
|
||||
// NewEncoder returns an Encoder to convert from Unicode to the charset.
|
||||
NewEncoder func() Encoder
|
||||
}
|
||||
|
||||
// The charsets are stored in charsets under their canonical names.
|
||||
var charsets = make(map[string]*Charset)
|
||||
|
||||
// aliases maps their aliases to their canonical names.
|
||||
var aliases = make(map[string]string)
|
||||
|
||||
// simplifyName converts a name to lower case and removes non-alphanumeric characters.
|
||||
// This is how the names are used as keys to the maps.
|
||||
func simplifyName(name string) string {
|
||||
var buf bytes.Buffer
|
||||
for _, c := range name {
|
||||
switch {
|
||||
case unicode.IsDigit(c):
|
||||
buf.WriteRune(c)
|
||||
case unicode.IsLetter(c):
|
||||
buf.WriteRune(unicode.ToLower(c))
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// RegisterCharset adds a charset to the charsetMap.
|
||||
func RegisterCharset(cs *Charset) {
|
||||
name := cs.Name
|
||||
charsets[name] = cs
|
||||
aliases[simplifyName(name)] = name
|
||||
for _, alias := range cs.Aliases {
|
||||
aliases[simplifyName(alias)] = name
|
||||
}
|
||||
}
|
||||
|
||||
// GetCharset fetches a charset by name.
|
||||
// If the name is not found, it returns nil.
|
||||
func GetCharset(name string) *Charset {
|
||||
return charsets[aliases[simplifyName(name)]]
|
||||
}
|
||||
|
||||
// NewDecoder returns a Decoder to decode the named charset.
|
||||
// If the name is not found, it returns nil.
|
||||
func NewDecoder(name string) Decoder {
|
||||
cs := GetCharset(name)
|
||||
if cs == nil {
|
||||
return nil
|
||||
}
|
||||
return cs.NewDecoder()
|
||||
}
|
||||
|
||||
// NewEncoder returns an Encoder to encode the named charset.
|
||||
func NewEncoder(name string) Encoder {
|
||||
cs := GetCharset(name)
|
||||
if cs == nil {
|
||||
return nil
|
||||
}
|
||||
return cs.NewEncoder()
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// ConvertString converts a string from UTF-8 to e's encoding.
|
||||
func (e Encoder) ConvertString(s string) string {
|
||||
dest := make([]byte, len(s)+10)
|
||||
destPos := 0
|
||||
|
||||
for _, rune := range s {
|
||||
retry:
|
||||
size, status := e(dest[destPos:], rune)
|
||||
|
||||
if status == NO_ROOM {
|
||||
newDest := make([]byte, len(dest)*2)
|
||||
copy(newDest, dest)
|
||||
dest = newDest
|
||||
goto retry
|
||||
}
|
||||
|
||||
if status == STATE_ONLY {
|
||||
destPos += size
|
||||
goto retry
|
||||
}
|
||||
|
||||
destPos += size
|
||||
}
|
||||
|
||||
return string(dest[:destPos])
|
||||
}
|
||||
|
||||
// ConvertString converts a string from d's encoding to UTF-8.
|
||||
func (d Decoder) ConvertString(s string) string {
|
||||
bytes := []byte(s)
|
||||
runes := make([]rune, len(s))
|
||||
destPos := 0
|
||||
|
||||
for len(bytes) > 0 {
|
||||
c, size, status := d(bytes)
|
||||
|
||||
if status == STATE_ONLY {
|
||||
bytes = bytes[size:]
|
||||
continue
|
||||
}
|
||||
|
||||
if status == NO_ROOM {
|
||||
c = 0xfffd
|
||||
size = len(bytes)
|
||||
status = INVALID_CHAR
|
||||
}
|
||||
|
||||
bytes = bytes[size:]
|
||||
runes[destPos] = c
|
||||
destPos++
|
||||
}
|
||||
|
||||
return string(runes[:destPos])
|
||||
}
|
||||
|
||||
// ConvertStringOK converts a string from UTF-8 to e's encoding. It also
|
||||
// returns a boolean indicating whether every character was converted
|
||||
// successfully.
|
||||
func (e Encoder) ConvertStringOK(s string) (result string, ok bool) {
|
||||
dest := make([]byte, len(s)+10)
|
||||
destPos := 0
|
||||
ok = true
|
||||
|
||||
for i, r := range s {
|
||||
// The following test is copied from utf8.ValidString.
|
||||
if r == utf8.RuneError && ok {
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
size, status := e(dest[destPos:], r)
|
||||
|
||||
switch status {
|
||||
case NO_ROOM:
|
||||
newDest := make([]byte, len(dest)*2)
|
||||
copy(newDest, dest)
|
||||
dest = newDest
|
||||
goto retry
|
||||
|
||||
case STATE_ONLY:
|
||||
destPos += size
|
||||
goto retry
|
||||
|
||||
case INVALID_CHAR:
|
||||
ok = false
|
||||
}
|
||||
|
||||
destPos += size
|
||||
}
|
||||
|
||||
return string(dest[:destPos]), ok
|
||||
}
|
||||
|
||||
// ConvertStringOK converts a string from d's encoding to UTF-8.
|
||||
// It also returns a boolean indicating whether every character was converted
|
||||
// successfully.
|
||||
func (d Decoder) ConvertStringOK(s string) (result string, ok bool) {
|
||||
bytes := []byte(s)
|
||||
runes := make([]rune, len(s))
|
||||
destPos := 0
|
||||
ok = true
|
||||
|
||||
for len(bytes) > 0 {
|
||||
c, size, status := d(bytes)
|
||||
|
||||
switch status {
|
||||
case STATE_ONLY:
|
||||
bytes = bytes[size:]
|
||||
continue
|
||||
|
||||
case NO_ROOM:
|
||||
c = 0xfffd
|
||||
size = len(bytes)
|
||||
ok = false
|
||||
|
||||
case INVALID_CHAR:
|
||||
ok = false
|
||||
}
|
||||
|
||||
bytes = bytes[size:]
|
||||
runes[destPos] = c
|
||||
destPos++
|
||||
}
|
||||
|
||||
return string(runes[:destPos]), ok
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Converters for Microsoft's version of the EUC-JP encoding
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "cp51932",
|
||||
Aliases: []string{"windows-51932"},
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeCP51932
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
msJISTable.Reverse()
|
||||
return encodeCP51932
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeCP51932(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
switch {
|
||||
case b < 0x80:
|
||||
return rune(b), 1, SUCCESS
|
||||
|
||||
case b == 0x8e:
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
b2 := p[1]
|
||||
if b2 < 0xa1 || b2 > 0xdf {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(b2) + (0xff61 - 0xa1), 2, SUCCESS
|
||||
|
||||
case 0xa1 <= b && b <= 0xfe:
|
||||
return msJISTable.DecodeHigh(p)
|
||||
}
|
||||
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeCP51932(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c < 0x80 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c > 0xffff {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if 0xff61 <= c && c <= 0xff9f {
|
||||
p[0] = 0x8e
|
||||
p[1] = byte(c - (0xff61 - 0xa1))
|
||||
return 2, SUCCESS
|
||||
}
|
||||
|
||||
return msJISTable.EncodeHigh(p, c)
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// decoding HTML entities
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// EntityDecoder returns a Decoder that decodes HTML character entities.
|
||||
// If there is no valid character entity at the current position, it returns INVALID_CHAR.
|
||||
// So it needs to be combined with another Decoder via FallbackDecoder.
|
||||
func EntityDecoder() Decoder {
|
||||
var leftover rune // leftover rune from two-rune entity
|
||||
return func(p []byte) (r rune, size int, status Status) {
|
||||
if leftover != 0 {
|
||||
r = leftover
|
||||
leftover = 0
|
||||
return r, 0, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
if p[0] != '&' {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if len(p) < 3 {
|
||||
return 0, 1, NO_ROOM
|
||||
}
|
||||
|
||||
r, size, status = 0xfffd, 1, INVALID_CHAR
|
||||
n := 1 // number of bytes read so far
|
||||
|
||||
if p[n] == '#' {
|
||||
n++
|
||||
c := p[n]
|
||||
hex := false
|
||||
if c == 'x' || c == 'X' {
|
||||
hex = true
|
||||
n++
|
||||
}
|
||||
|
||||
var x rune
|
||||
for n < len(p) {
|
||||
c = p[n]
|
||||
n++
|
||||
if hex {
|
||||
if '0' <= c && c <= '9' {
|
||||
x = 16*x + rune(c) - '0'
|
||||
continue
|
||||
} else if 'a' <= c && c <= 'f' {
|
||||
x = 16*x + rune(c) - 'a' + 10
|
||||
continue
|
||||
} else if 'A' <= c && c <= 'F' {
|
||||
x = 16*x + rune(c) - 'A' + 10
|
||||
continue
|
||||
}
|
||||
} else if '0' <= c && c <= '9' {
|
||||
x = 10*x + rune(c) - '0'
|
||||
continue
|
||||
}
|
||||
if c != ';' {
|
||||
n--
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if n == len(p) && p[n-1] != ';' {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
size = n
|
||||
if p[n-1] == ';' {
|
||||
n--
|
||||
}
|
||||
if hex {
|
||||
n--
|
||||
}
|
||||
n--
|
||||
// Now n is the number of actual digits read.
|
||||
if n == 0 {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if 0x80 <= x && x <= 0x9F {
|
||||
// Replace characters from Windows-1252 with UTF-8 equivalents.
|
||||
x = replacementTable[x-0x80]
|
||||
} else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
|
||||
// Replace invalid characters with the replacement character.
|
||||
return 0xfffd, size, INVALID_CHAR
|
||||
}
|
||||
|
||||
r = x
|
||||
status = SUCCESS
|
||||
return
|
||||
}
|
||||
|
||||
// Look for a named entity in EntityList.
|
||||
|
||||
possible := entityList
|
||||
for len(possible) > 0 {
|
||||
if len(p) <= n {
|
||||
leftover = 0
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
c := p[n]
|
||||
|
||||
// Narrow down the selection in possible to those items that have c in the
|
||||
// appropriate byte.
|
||||
first := sort.Search(len(possible), func(i int) bool {
|
||||
e := possible[i].name
|
||||
if len(e) < n {
|
||||
return false
|
||||
}
|
||||
return e[n-1] >= c
|
||||
})
|
||||
possible = possible[first:]
|
||||
last := sort.Search(len(possible), func(i int) bool {
|
||||
return possible[i].name[n-1] > c
|
||||
})
|
||||
possible = possible[:last]
|
||||
|
||||
n++
|
||||
if len(possible) > 0 && len(possible[0].name) == n-1 {
|
||||
r, leftover = possible[0].r1, possible[0].r2
|
||||
size = n
|
||||
status = SUCCESS
|
||||
// but don't return yet, since we need the longest match
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// This table is copied from /src/pkg/html/escape.go in the Go source
|
||||
//
|
||||
// These replacements permit compatibility with old numeric entities that
|
||||
// assumed Windows-1252 encoding.
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
|
||||
var replacementTable = [...]rune{
|
||||
'\u20AC', // First entry is what 0x80 should be replaced with.
|
||||
'\u0081',
|
||||
'\u201A',
|
||||
'\u0192',
|
||||
'\u201E',
|
||||
'\u2026',
|
||||
'\u2020',
|
||||
'\u2021',
|
||||
'\u02C6',
|
||||
'\u2030',
|
||||
'\u0160',
|
||||
'\u2039',
|
||||
'\u0152',
|
||||
'\u008D',
|
||||
'\u017D',
|
||||
'\u008F',
|
||||
'\u0090',
|
||||
'\u2018',
|
||||
'\u2019',
|
||||
'\u201C',
|
||||
'\u201D',
|
||||
'\u2022',
|
||||
'\u2013',
|
||||
'\u2014',
|
||||
'\u02DC',
|
||||
'\u2122',
|
||||
'\u0161',
|
||||
'\u203A',
|
||||
'\u0153',
|
||||
'\u009D',
|
||||
'\u017E',
|
||||
'\u0178', // Last entry is 0x9F.
|
||||
// 0x00->'\uFFFD' is handled programmatically.
|
||||
// 0x0D->'\u000D' is a no-op.
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Converters for the EUC-JP encoding
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "EUC-JP",
|
||||
Aliases: []string{"extended_unix_code_packed_format_for_japanese", "cseucpkdfmtjapanese"},
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeEucJP
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
jis0208Table.Reverse()
|
||||
jis0212Table.Reverse()
|
||||
return encodeEucJP
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeEucJP(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
switch {
|
||||
case b < 0x80:
|
||||
return rune(b), 1, SUCCESS
|
||||
|
||||
case b == 0x8e:
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
b2 := p[1]
|
||||
if b2 < 0xa1 || b2 > 0xdf {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(b2) + (0xff61 - 0xa1), 2, SUCCESS
|
||||
|
||||
case b == 0x8f:
|
||||
if len(p) < 3 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
c, size, status = jis0212Table.DecodeHigh(p[1:3])
|
||||
if status == SUCCESS {
|
||||
size = 3
|
||||
}
|
||||
return
|
||||
|
||||
case 0xa1 <= b && b <= 0xfe:
|
||||
return jis0208Table.DecodeHigh(p)
|
||||
}
|
||||
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeEucJP(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c < 0x80 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c > 0xffff {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if 0xff61 <= c && c <= 0xff9f {
|
||||
p[0] = 0x8e
|
||||
p[1] = byte(c - (0xff61 - 0xa1))
|
||||
return 2, SUCCESS
|
||||
}
|
||||
|
||||
size, status = jis0208Table.EncodeHigh(p, c)
|
||||
if status == SUCCESS {
|
||||
return size, status
|
||||
}
|
||||
|
||||
size, status = jis0212Table.EncodeHigh(p[1:], c)
|
||||
switch status {
|
||||
case SUCCESS:
|
||||
p[0] = 0x8f
|
||||
return size + 1, SUCCESS
|
||||
|
||||
case INVALID_CHAR:
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
return size, status
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,89 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for the EUC-KR encoding.
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "EUC-KR",
|
||||
Aliases: []string{
|
||||
"ibm-1363",
|
||||
"KS_C_5601-1987",
|
||||
"KS_C_5601-1989",
|
||||
"KSC_5601",
|
||||
"Korean",
|
||||
"iso-ir-149",
|
||||
"cp1363",
|
||||
"5601",
|
||||
"ksc",
|
||||
"windows-949",
|
||||
"ibm-970",
|
||||
"cp970",
|
||||
"970",
|
||||
"cp949",
|
||||
},
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeEucKr
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
eucKrOnce.Do(reverseEucKrTable)
|
||||
return encodeEucKr
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeEucKr(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b < 0x80 {
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
euc := int(b)<<8 + int(p[1])
|
||||
c = rune(eucKrToUnicode[euc])
|
||||
|
||||
if c == 0 {
|
||||
return utf8.RuneError, 2, INVALID_CHAR
|
||||
}
|
||||
return c, 2, SUCCESS
|
||||
}
|
||||
|
||||
func encodeEucKr(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c < 0x80 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c > 0xffff {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
euc := unicodeToEucKr[c]
|
||||
if euc == 0 {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
p[0] = byte(euc >> 8)
|
||||
p[1] = byte(euc)
|
||||
return 2, SUCCESS
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// FallbackDecoder combines a series of Decoders into one.
|
||||
// If the first Decoder returns a status of INVALID_CHAR, the others are tried as well.
|
||||
//
|
||||
// Note: if the text to be decoded ends with a sequence of bytes that is not a valid character in the first charset,
|
||||
// but it could be the beginning of a valid character, the FallbackDecoder will give a status of NO_ROOM instead of
|
||||
// falling back to the other Decoders.
|
||||
func FallbackDecoder(decoders ...Decoder) Decoder {
|
||||
return func(p []byte) (c rune, size int, status Status) {
|
||||
for _, d := range decoders {
|
||||
c, size, status = d(p)
|
||||
if status != INVALID_CHAR {
|
||||
return
|
||||
}
|
||||
}
|
||||
return 0, 1, INVALID_CHAR
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,156 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Converters for GB18030 encoding.
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "GB18030",
|
||||
NewDecoder: func() Decoder {
|
||||
gb18030Once.Do(buildGB18030Tables)
|
||||
return decodeGB18030Rune
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
gb18030Once.Do(buildGB18030Tables)
|
||||
return encodeGB18030Rune
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeGB18030Rune(p []byte) (r rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b < 128 {
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if p[0] < 0x81 || p[0] > 0xfe {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if p[1] >= 0x40 {
|
||||
// 2-byte character
|
||||
c := uint16(p[0])<<8 + uint16(p[1])
|
||||
r = rune(gbkToUnicode[c])
|
||||
if r == 0 {
|
||||
r = gbkToUnicodeExtra[c]
|
||||
}
|
||||
|
||||
if r != 0 {
|
||||
return r, 2, SUCCESS
|
||||
}
|
||||
} else if p[1] >= 0x30 {
|
||||
// 4-byte character
|
||||
if len(p) < 4 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
if p[2] < 0x81 || p[2] > 0xfe || p[3] < 0x30 || p[3] > 0x39 {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
code := uint32(p[0])<<24 + uint32(p[1])<<16 + uint32(p[2])<<8 + uint32(p[3])
|
||||
lin := gb18030Linear(code)
|
||||
|
||||
if lin <= maxGB18030Linear {
|
||||
r = rune(gb18030LinearToUnicode[lin])
|
||||
if r != 0 {
|
||||
return r, 4, SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
for _, rng := range gb18030Ranges {
|
||||
if lin >= rng.firstGB && lin <= rng.lastGB {
|
||||
return rng.firstRune + rune(lin) - rune(rng.firstGB), 4, SUCCESS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeGB18030Rune(p []byte, r rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if r < 128 {
|
||||
p[0] = byte(r)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
var c uint16
|
||||
if r < 0x10000 {
|
||||
c = unicodeToGBK[r]
|
||||
} else {
|
||||
c = unicodeToGBKExtra[r]
|
||||
}
|
||||
|
||||
if c != 0 {
|
||||
p[0] = byte(c >> 8)
|
||||
p[1] = byte(c)
|
||||
return 2, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 4 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if r < 0x10000 {
|
||||
f := unicodeToGB18030[r]
|
||||
if f != 0 {
|
||||
p[0] = byte(f >> 24)
|
||||
p[1] = byte(f >> 16)
|
||||
p[2] = byte(f >> 8)
|
||||
p[3] = byte(f)
|
||||
return 4, SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
for _, rng := range gb18030Ranges {
|
||||
if r >= rng.firstRune && r <= rng.lastRune {
|
||||
lin := rng.firstGB + uint32(r) - uint32(rng.firstRune)
|
||||
p[0] = byte(lin/(10*126*10)) + 0x81
|
||||
p[1] = byte(lin/(126*10)%10) + 0x30
|
||||
p[2] = byte(lin/10%126) + 0x81
|
||||
p[3] = byte(lin%10) + 0x30
|
||||
return 4, SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
p[0] = 0x1a
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
var gb18030Once sync.Once
|
||||
|
||||
// Mapping from gb18039Linear values to Unicode.
|
||||
var gb18030LinearToUnicode []uint16
|
||||
|
||||
var unicodeToGB18030 []uint32
|
||||
|
||||
func buildGB18030Tables() {
|
||||
gb18030LinearToUnicode = make([]uint16, maxGB18030Linear+1)
|
||||
unicodeToGB18030 = make([]uint32, 65536)
|
||||
for _, data := range gb18030Data {
|
||||
gb18030LinearToUnicode[gb18030Linear(data.gb18030)] = data.unicode
|
||||
unicodeToGB18030[data.unicode] = data.gb18030
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,78 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for GBK encoding.
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "GBK",
|
||||
Aliases: []string{"GB2312"}, // GBK is a superset of GB2312.
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeGBKRune
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
return encodeGBKRune
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeGBKRune(p []byte) (r rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b < 128 {
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
c := uint16(p[0])<<8 + uint16(p[1])
|
||||
r = rune(gbkToUnicode[c])
|
||||
if r == 0 {
|
||||
r = gbkToUnicodeExtra[c]
|
||||
}
|
||||
|
||||
if r != 0 {
|
||||
return r, 2, SUCCESS
|
||||
}
|
||||
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeGBKRune(p []byte, r rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if r < 128 {
|
||||
p[0] = byte(r)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
var c uint16
|
||||
if r < 0x10000 {
|
||||
c = unicodeToGBK[r]
|
||||
} else {
|
||||
c = unicodeToGBKExtra[r]
|
||||
}
|
||||
|
||||
if c != 0 {
|
||||
p[0] = byte(c >> 8)
|
||||
p[1] = byte(c)
|
||||
return 2, SUCCESS
|
||||
}
|
||||
|
||||
p[0] = 0x1a
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// converters for ISO-2022-JP encoding
|
||||
|
||||
const esc = 27
|
||||
|
||||
func init() {
|
||||
type jpEncoding int
|
||||
const (
|
||||
ascii jpEncoding = iota
|
||||
jisX0201Roman
|
||||
jisX0208
|
||||
)
|
||||
|
||||
RegisterCharset(&Charset{
|
||||
Name: "ISO-2022-JP",
|
||||
NewDecoder: func() Decoder {
|
||||
encoding := ascii
|
||||
return func(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b == esc {
|
||||
if len(p) < 3 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
switch p[1] {
|
||||
case '(':
|
||||
switch p[2] {
|
||||
case 'B':
|
||||
encoding = ascii
|
||||
return 0, 3, STATE_ONLY
|
||||
|
||||
case 'J':
|
||||
encoding = jisX0201Roman
|
||||
return 0, 3, STATE_ONLY
|
||||
}
|
||||
|
||||
case '$':
|
||||
switch p[2] {
|
||||
case '@', 'B':
|
||||
encoding = jisX0208
|
||||
return 0, 3, STATE_ONLY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch encoding {
|
||||
case ascii:
|
||||
if b > 127 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(b), 1, SUCCESS
|
||||
|
||||
case jisX0201Roman:
|
||||
if b > 127 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
switch b {
|
||||
case '\\':
|
||||
return 0xA5, 1, SUCCESS
|
||||
case '~':
|
||||
return 0x203E, 1, SUCCESS
|
||||
}
|
||||
return rune(b), 1, SUCCESS
|
||||
|
||||
case jisX0208:
|
||||
return jis0208Table.DecodeLow(p)
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
jis0208Table.Reverse()
|
||||
encoding := ascii
|
||||
return func(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c < 128 {
|
||||
if encoding != ascii {
|
||||
if len(p) < 4 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
p[0], p[1], p[2] = esc, '(', 'B'
|
||||
p[3] = byte(c)
|
||||
encoding = ascii
|
||||
return 4, SUCCESS
|
||||
}
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if c > 65535 {
|
||||
return 0, INVALID_CHAR
|
||||
}
|
||||
jis := jis0208Table.FromUnicode[c]
|
||||
if jis == [2]byte{0, 0} && c != rune(jis0208Table.Data[0][0]) {
|
||||
return 0, INVALID_CHAR
|
||||
}
|
||||
|
||||
if encoding != jisX0208 {
|
||||
if len(p) < 3 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
p[0], p[1], p[2] = esc, '$', 'B'
|
||||
encoding = jisX0208
|
||||
return 3, STATE_ONLY
|
||||
}
|
||||
|
||||
p[0] = jis[0] + 0x21
|
||||
p[1] = jis[1] + 0x21
|
||||
return 2, SUCCESS
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
var jis0201ToUnicode = [256]uint16{
|
||||
0x20: 0x0020, // SPACE
|
||||
0x21: 0x0021, // EXCLAMATION MARK
|
||||
0x22: 0x0022, // QUOTATION MARK
|
||||
0x23: 0x0023, // NUMBER SIGN
|
||||
0x24: 0x0024, // DOLLAR SIGN
|
||||
0x25: 0x0025, // PERCENT SIGN
|
||||
0x26: 0x0026, // AMPERSAND
|
||||
0x27: 0x0027, // APOSTROPHE
|
||||
0x28: 0x0028, // LEFT PARENTHESIS
|
||||
0x29: 0x0029, // RIGHT PARENTHESIS
|
||||
0x2A: 0x002A, // ASTERISK
|
||||
0x2B: 0x002B, // PLUS SIGN
|
||||
0x2C: 0x002C, // COMMA
|
||||
0x2D: 0x002D, // HYPHEN-MINUS
|
||||
0x2E: 0x002E, // FULL STOP
|
||||
0x2F: 0x002F, // SOLIDUS
|
||||
0x30: 0x0030, // DIGIT ZERO
|
||||
0x31: 0x0031, // DIGIT ONE
|
||||
0x32: 0x0032, // DIGIT TWO
|
||||
0x33: 0x0033, // DIGIT THREE
|
||||
0x34: 0x0034, // DIGIT FOUR
|
||||
0x35: 0x0035, // DIGIT FIVE
|
||||
0x36: 0x0036, // DIGIT SIX
|
||||
0x37: 0x0037, // DIGIT SEVEN
|
||||
0x38: 0x0038, // DIGIT EIGHT
|
||||
0x39: 0x0039, // DIGIT NINE
|
||||
0x3A: 0x003A, // COLON
|
||||
0x3B: 0x003B, // SEMICOLON
|
||||
0x3C: 0x003C, // LESS-THAN SIGN
|
||||
0x3D: 0x003D, // EQUALS SIGN
|
||||
0x3E: 0x003E, // GREATER-THAN SIGN
|
||||
0x3F: 0x003F, // QUESTION MARK
|
||||
0x40: 0x0040, // COMMERCIAL AT
|
||||
0x41: 0x0041, // LATIN CAPITAL LETTER A
|
||||
0x42: 0x0042, // LATIN CAPITAL LETTER B
|
||||
0x43: 0x0043, // LATIN CAPITAL LETTER C
|
||||
0x44: 0x0044, // LATIN CAPITAL LETTER D
|
||||
0x45: 0x0045, // LATIN CAPITAL LETTER E
|
||||
0x46: 0x0046, // LATIN CAPITAL LETTER F
|
||||
0x47: 0x0047, // LATIN CAPITAL LETTER G
|
||||
0x48: 0x0048, // LATIN CAPITAL LETTER H
|
||||
0x49: 0x0049, // LATIN CAPITAL LETTER I
|
||||
0x4A: 0x004A, // LATIN CAPITAL LETTER J
|
||||
0x4B: 0x004B, // LATIN CAPITAL LETTER K
|
||||
0x4C: 0x004C, // LATIN CAPITAL LETTER L
|
||||
0x4D: 0x004D, // LATIN CAPITAL LETTER M
|
||||
0x4E: 0x004E, // LATIN CAPITAL LETTER N
|
||||
0x4F: 0x004F, // LATIN CAPITAL LETTER O
|
||||
0x50: 0x0050, // LATIN CAPITAL LETTER P
|
||||
0x51: 0x0051, // LATIN CAPITAL LETTER Q
|
||||
0x52: 0x0052, // LATIN CAPITAL LETTER R
|
||||
0x53: 0x0053, // LATIN CAPITAL LETTER S
|
||||
0x54: 0x0054, // LATIN CAPITAL LETTER T
|
||||
0x55: 0x0055, // LATIN CAPITAL LETTER U
|
||||
0x56: 0x0056, // LATIN CAPITAL LETTER V
|
||||
0x57: 0x0057, // LATIN CAPITAL LETTER W
|
||||
0x58: 0x0058, // LATIN CAPITAL LETTER X
|
||||
0x59: 0x0059, // LATIN CAPITAL LETTER Y
|
||||
0x5A: 0x005A, // LATIN CAPITAL LETTER Z
|
||||
0x5B: 0x005B, // LEFT SQUARE BRACKET
|
||||
0x5C: 0x00A5, // YEN SIGN
|
||||
0x5D: 0x005D, // RIGHT SQUARE BRACKET
|
||||
0x5E: 0x005E, // CIRCUMFLEX ACCENT
|
||||
0x5F: 0x005F, // LOW LINE
|
||||
0x60: 0x0060, // GRAVE ACCENT
|
||||
0x61: 0x0061, // LATIN SMALL LETTER A
|
||||
0x62: 0x0062, // LATIN SMALL LETTER B
|
||||
0x63: 0x0063, // LATIN SMALL LETTER C
|
||||
0x64: 0x0064, // LATIN SMALL LETTER D
|
||||
0x65: 0x0065, // LATIN SMALL LETTER E
|
||||
0x66: 0x0066, // LATIN SMALL LETTER F
|
||||
0x67: 0x0067, // LATIN SMALL LETTER G
|
||||
0x68: 0x0068, // LATIN SMALL LETTER H
|
||||
0x69: 0x0069, // LATIN SMALL LETTER I
|
||||
0x6A: 0x006A, // LATIN SMALL LETTER J
|
||||
0x6B: 0x006B, // LATIN SMALL LETTER K
|
||||
0x6C: 0x006C, // LATIN SMALL LETTER L
|
||||
0x6D: 0x006D, // LATIN SMALL LETTER M
|
||||
0x6E: 0x006E, // LATIN SMALL LETTER N
|
||||
0x6F: 0x006F, // LATIN SMALL LETTER O
|
||||
0x70: 0x0070, // LATIN SMALL LETTER P
|
||||
0x71: 0x0071, // LATIN SMALL LETTER Q
|
||||
0x72: 0x0072, // LATIN SMALL LETTER R
|
||||
0x73: 0x0073, // LATIN SMALL LETTER S
|
||||
0x74: 0x0074, // LATIN SMALL LETTER T
|
||||
0x75: 0x0075, // LATIN SMALL LETTER U
|
||||
0x76: 0x0076, // LATIN SMALL LETTER V
|
||||
0x77: 0x0077, // LATIN SMALL LETTER W
|
||||
0x78: 0x0078, // LATIN SMALL LETTER X
|
||||
0x79: 0x0079, // LATIN SMALL LETTER Y
|
||||
0x7A: 0x007A, // LATIN SMALL LETTER Z
|
||||
0x7B: 0x007B, // LEFT CURLY BRACKET
|
||||
0x7C: 0x007C, // VERTICAL LINE
|
||||
0x7D: 0x007D, // RIGHT CURLY BRACKET
|
||||
0x7E: 0x203E, // OVERLINE
|
||||
0xA1: 0xFF61, // HALFWIDTH IDEOGRAPHIC FULL STOP
|
||||
0xA2: 0xFF62, // HALFWIDTH LEFT CORNER BRACKET
|
||||
0xA3: 0xFF63, // HALFWIDTH RIGHT CORNER BRACKET
|
||||
0xA4: 0xFF64, // HALFWIDTH IDEOGRAPHIC COMMA
|
||||
0xA5: 0xFF65, // HALFWIDTH KATAKANA MIDDLE DOT
|
||||
0xA6: 0xFF66, // HALFWIDTH KATAKANA LETTER WO
|
||||
0xA7: 0xFF67, // HALFWIDTH KATAKANA LETTER SMALL A
|
||||
0xA8: 0xFF68, // HALFWIDTH KATAKANA LETTER SMALL I
|
||||
0xA9: 0xFF69, // HALFWIDTH KATAKANA LETTER SMALL U
|
||||
0xAA: 0xFF6A, // HALFWIDTH KATAKANA LETTER SMALL E
|
||||
0xAB: 0xFF6B, // HALFWIDTH KATAKANA LETTER SMALL O
|
||||
0xAC: 0xFF6C, // HALFWIDTH KATAKANA LETTER SMALL YA
|
||||
0xAD: 0xFF6D, // HALFWIDTH KATAKANA LETTER SMALL YU
|
||||
0xAE: 0xFF6E, // HALFWIDTH KATAKANA LETTER SMALL YO
|
||||
0xAF: 0xFF6F, // HALFWIDTH KATAKANA LETTER SMALL TU
|
||||
0xB0: 0xFF70, // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
|
||||
0xB1: 0xFF71, // HALFWIDTH KATAKANA LETTER A
|
||||
0xB2: 0xFF72, // HALFWIDTH KATAKANA LETTER I
|
||||
0xB3: 0xFF73, // HALFWIDTH KATAKANA LETTER U
|
||||
0xB4: 0xFF74, // HALFWIDTH KATAKANA LETTER E
|
||||
0xB5: 0xFF75, // HALFWIDTH KATAKANA LETTER O
|
||||
0xB6: 0xFF76, // HALFWIDTH KATAKANA LETTER KA
|
||||
0xB7: 0xFF77, // HALFWIDTH KATAKANA LETTER KI
|
||||
0xB8: 0xFF78, // HALFWIDTH KATAKANA LETTER KU
|
||||
0xB9: 0xFF79, // HALFWIDTH KATAKANA LETTER KE
|
||||
0xBA: 0xFF7A, // HALFWIDTH KATAKANA LETTER KO
|
||||
0xBB: 0xFF7B, // HALFWIDTH KATAKANA LETTER SA
|
||||
0xBC: 0xFF7C, // HALFWIDTH KATAKANA LETTER SI
|
||||
0xBD: 0xFF7D, // HALFWIDTH KATAKANA LETTER SU
|
||||
0xBE: 0xFF7E, // HALFWIDTH KATAKANA LETTER SE
|
||||
0xBF: 0xFF7F, // HALFWIDTH KATAKANA LETTER SO
|
||||
0xC0: 0xFF80, // HALFWIDTH KATAKANA LETTER TA
|
||||
0xC1: 0xFF81, // HALFWIDTH KATAKANA LETTER TI
|
||||
0xC2: 0xFF82, // HALFWIDTH KATAKANA LETTER TU
|
||||
0xC3: 0xFF83, // HALFWIDTH KATAKANA LETTER TE
|
||||
0xC4: 0xFF84, // HALFWIDTH KATAKANA LETTER TO
|
||||
0xC5: 0xFF85, // HALFWIDTH KATAKANA LETTER NA
|
||||
0xC6: 0xFF86, // HALFWIDTH KATAKANA LETTER NI
|
||||
0xC7: 0xFF87, // HALFWIDTH KATAKANA LETTER NU
|
||||
0xC8: 0xFF88, // HALFWIDTH KATAKANA LETTER NE
|
||||
0xC9: 0xFF89, // HALFWIDTH KATAKANA LETTER NO
|
||||
0xCA: 0xFF8A, // HALFWIDTH KATAKANA LETTER HA
|
||||
0xCB: 0xFF8B, // HALFWIDTH KATAKANA LETTER HI
|
||||
0xCC: 0xFF8C, // HALFWIDTH KATAKANA LETTER HU
|
||||
0xCD: 0xFF8D, // HALFWIDTH KATAKANA LETTER HE
|
||||
0xCE: 0xFF8E, // HALFWIDTH KATAKANA LETTER HO
|
||||
0xCF: 0xFF8F, // HALFWIDTH KATAKANA LETTER MA
|
||||
0xD0: 0xFF90, // HALFWIDTH KATAKANA LETTER MI
|
||||
0xD1: 0xFF91, // HALFWIDTH KATAKANA LETTER MU
|
||||
0xD2: 0xFF92, // HALFWIDTH KATAKANA LETTER ME
|
||||
0xD3: 0xFF93, // HALFWIDTH KATAKANA LETTER MO
|
||||
0xD4: 0xFF94, // HALFWIDTH KATAKANA LETTER YA
|
||||
0xD5: 0xFF95, // HALFWIDTH KATAKANA LETTER YU
|
||||
0xD6: 0xFF96, // HALFWIDTH KATAKANA LETTER YO
|
||||
0xD7: 0xFF97, // HALFWIDTH KATAKANA LETTER RA
|
||||
0xD8: 0xFF98, // HALFWIDTH KATAKANA LETTER RI
|
||||
0xD9: 0xFF99, // HALFWIDTH KATAKANA LETTER RU
|
||||
0xDA: 0xFF9A, // HALFWIDTH KATAKANA LETTER RE
|
||||
0xDB: 0xFF9B, // HALFWIDTH KATAKANA LETTER RO
|
||||
0xDC: 0xFF9C, // HALFWIDTH KATAKANA LETTER WA
|
||||
0xDD: 0xFF9D, // HALFWIDTH KATAKANA LETTER N
|
||||
0xDE: 0xFF9E, // HALFWIDTH KATAKANA VOICED SOUND MARK
|
||||
0xDF: 0xFF9F, // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A kutenTable holds the data for a double-byte character set, arranged by ku
|
||||
// (区, zone) and ten (点, position). These can be converted to various actual
|
||||
// encoding schemes.
|
||||
type kutenTable struct {
|
||||
// Data[ku][ten] is the unicode value for the character at that zone and
|
||||
// position.
|
||||
Data [94][94]uint16
|
||||
|
||||
// FromUnicode holds the ku and ten for each Unicode code point.
|
||||
// It is not available until Reverse() has been called.
|
||||
FromUnicode [][2]byte
|
||||
|
||||
// once is used to synchronize the generation of FromUnicode.
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// Reverse generates FromUnicode.
|
||||
func (t *kutenTable) Reverse() {
|
||||
t.once.Do(func() {
|
||||
t.FromUnicode = make([][2]byte, 65536)
|
||||
for ku := range t.Data {
|
||||
for ten, unicode := range t.Data[ku] {
|
||||
t.FromUnicode[unicode] = [2]byte{byte(ku), byte(ten)}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// DecodeLow decodes a character from an encoding that does not have the high
|
||||
// bit set.
|
||||
func (t *kutenTable) DecodeLow(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
ku := p[0] - 0x21
|
||||
ten := p[1] - 0x21
|
||||
if ku > 93 || ten > 93 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
u := t.Data[ku][ten]
|
||||
if u == 0 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(u), 2, SUCCESS
|
||||
}
|
||||
|
||||
// DecodeHigh decodes a character from an encoding that has the high bit set.
|
||||
func (t *kutenTable) DecodeHigh(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
ku := p[0] - 0xa1
|
||||
ten := p[1] - 0xa1
|
||||
if ku > 93 || ten > 93 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
u := t.Data[ku][ten]
|
||||
if u == 0 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
return rune(u), 2, SUCCESS
|
||||
}
|
||||
|
||||
// EncodeHigh encodes a character in an encoding that has the high bit set.
|
||||
func (t *kutenTable) EncodeHigh(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
if c > 0xffff {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
kuten := t.FromUnicode[c]
|
||||
if kuten == [2]byte{0, 0} && c != rune(t.Data[0][0]) {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
p[0] = kuten[0] + 0xa1
|
||||
p[1] = kuten[1] + 0xa1
|
||||
return 2, SUCCESS
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var nameTests = map[string]string{
|
||||
"utf8": "utf8",
|
||||
"ISO 8859-1": "iso88591",
|
||||
"Big5": "big5",
|
||||
"": "",
|
||||
}
|
||||
|
||||
func TestSimplifyName(t *testing.T) {
|
||||
for name, simple := range nameTests {
|
||||
if simple != simplifyName(name) {
|
||||
t.Errorf("%s came out as %s instead of as %s", name, simplifyName(name), simple)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testData = []struct {
|
||||
utf8, other, otherEncoding string
|
||||
}{
|
||||
{"Résumé", "Résumé", "utf8"},
|
||||
{"Résumé", "R\xe9sum\xe9", "latin-1"},
|
||||
{"これは漢字です。", "S0\x8c0o0\"oW[g0Y0\x020", "UTF-16LE"},
|
||||
{"これは漢字です。", "0S0\x8c0oo\"[W0g0Y0\x02", "UTF-16BE"},
|
||||
{"これは漢字です。", "\xfe\xff0S0\x8c0oo\"[W0g0Y0\x02", "UTF-16"},
|
||||
{"𝄢𝄞𝄪𝄫", "\xfe\xff\xd8\x34\xdd\x22\xd8\x34\xdd\x1e\xd8\x34\xdd\x2a\xd8\x34\xdd\x2b", "UTF-16"},
|
||||
{"Hello, world", "Hello, world", "ASCII"},
|
||||
{"Gdańsk", "Gda\xf1sk", "ISO-8859-2"},
|
||||
{"Ââ Čč Đđ Ŋŋ Õõ Šš Žž Åå Ää", "\xc2\xe2 \xc8\xe8 \xa9\xb9 \xaf\xbf \xd5\xf5 \xaa\xba \xac\xbc \xc5\xe5 \xc4\xe4", "ISO-8859-10"},
|
||||
{"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "ISO-8859-11"},
|
||||
{"latviešu", "latvie\xf0u", "ISO-8859-13"},
|
||||
{"Seònaid", "Se\xf2naid", "ISO-8859-14"},
|
||||
{"€1 is cheap", "\xa41 is cheap", "ISO-8859-15"},
|
||||
{"românește", "rom\xe2ne\xbate", "ISO-8859-16"},
|
||||
{"nutraĵo", "nutra\xbco", "ISO-8859-3"},
|
||||
{"Kalâdlit", "Kal\xe2dlit", "ISO-8859-4"},
|
||||
{"русский", "\xe0\xe3\xe1\xe1\xda\xd8\xd9", "ISO-8859-5"},
|
||||
{"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "ISO-8859-7"},
|
||||
{"Kağan", "Ka\xf0an", "ISO-8859-9"},
|
||||
{"Résumé", "R\x8esum\x8e", "macintosh"},
|
||||
{"Gdańsk", "Gda\xf1sk", "windows-1250"},
|
||||
{"русский", "\xf0\xf3\xf1\xf1\xea\xe8\xe9", "windows-1251"},
|
||||
{"Résumé", "R\xe9sum\xe9", "windows-1252"},
|
||||
{"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "windows-1253"},
|
||||
{"Kağan", "Ka\xf0an", "windows-1254"},
|
||||
{"עִבְרִית", "\xf2\xc4\xe1\xc0\xf8\xc4\xe9\xfa", "windows-1255"},
|
||||
{"العربية", "\xc7\xe1\xda\xd1\xc8\xed\xc9", "windows-1256"},
|
||||
{"latviešu", "latvie\xf0u", "windows-1257"},
|
||||
{"Việt", "Vi\xea\xf2t", "windows-1258"},
|
||||
{"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "windows-874"},
|
||||
{"русский", "\xd2\xd5\xd3\xd3\xcb\xc9\xca", "KOI8-R"},
|
||||
{"українська", "\xd5\xcb\xd2\xc1\xa7\xce\xd3\xd8\xcb\xc1", "KOI8-U"},
|
||||
{"Hello 常用國字標準字體表", "Hello \xb1`\xa5\u03b0\xea\xa6r\xbc\u0437\u01e6r\xc5\xe9\xaa\xed", "big5"},
|
||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gbk"},
|
||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gb18030"},
|
||||
{"עִבְרִית", "\x81\x30\xfb\x30\x81\x30\xf6\x34\x81\x30\xf9\x33\x81\x30\xf6\x30\x81\x30\xfb\x36\x81\x30\xf6\x34\x81\x30\xfa\x31\x81\x30\xfb\x38", "gb18030"},
|
||||
{"㧯", "\x82\x31\x89\x38", "gb18030"},
|
||||
{"これは漢字です。", "\x82\xb1\x82\xea\x82\xcd\x8a\xbf\x8e\x9a\x82\xc5\x82\xb7\x81B", "SJIS"},
|
||||
{"Hello, 世界!", "Hello, \x90\xa2\x8aE!", "SJIS"},
|
||||
{"イウエオカ", "\xb2\xb3\xb4\xb5\xb6", "SJIS"},
|
||||
{"これは漢字です。", "\xa4\xb3\xa4\xec\xa4\u03f4\xc1\xbb\xfa\xa4\u01e4\xb9\xa1\xa3", "EUC-JP"},
|
||||
{"これは漢字です。", "\xa4\xb3\xa4\xec\xa4\u03f4\xc1\xbb\xfa\xa4\u01e4\xb9\xa1\xa3", "CP51932"},
|
||||
{"Thông tin bạn đồng hànhỌ", "Th\xabng tin b\xb9n \xae\xe5ng h\xb5nhO\xe4", "TCVN3"},
|
||||
{"Hello, 世界!", "Hello, \x1b$B@$3&\x1b(B!", "ISO-2022-JP"},
|
||||
{"네이트 | 즐거움의 시작, 슈파스(Spaβ) NATE", "\xb3\xd7\xc0\xcc\xc6\xae | \xc1\xf1\xb0\xc5\xbf\xf2\xc0\xc7 \xbd\xc3\xc0\xdb, \xbd\xb4\xc6\xc4\xbd\xba(Spa\xa5\xe2) NATE", "EUC-KR"},
|
||||
}
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
for _, data := range testData {
|
||||
d := NewDecoder(data.otherEncoding)
|
||||
if d == nil {
|
||||
t.Errorf("Could not create decoder for %s", data.otherEncoding)
|
||||
continue
|
||||
}
|
||||
|
||||
str := d.ConvertString(data.other)
|
||||
|
||||
if str != data.utf8 {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", str, data.utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeTranslate(t *testing.T) {
|
||||
for _, data := range testData {
|
||||
d := NewDecoder(data.otherEncoding)
|
||||
if d == nil {
|
||||
t.Errorf("Could not create decoder for %s", data.otherEncoding)
|
||||
continue
|
||||
}
|
||||
|
||||
_, cdata, _ := d.Translate([]byte(data.other), true)
|
||||
str := string(cdata)
|
||||
|
||||
if str != data.utf8 {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", str, data.utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
for _, data := range testData {
|
||||
e := NewEncoder(data.otherEncoding)
|
||||
if e == nil {
|
||||
t.Errorf("Could not create encoder for %s", data.otherEncoding)
|
||||
continue
|
||||
}
|
||||
|
||||
str := e.ConvertString(data.utf8)
|
||||
|
||||
if str != data.other {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", str, data.other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
for _, data := range testData {
|
||||
d := NewDecoder(data.otherEncoding)
|
||||
if d == nil {
|
||||
t.Errorf("Could not create decoder for %s", data.otherEncoding)
|
||||
continue
|
||||
}
|
||||
|
||||
b := bytes.NewBufferString(data.other)
|
||||
r := d.NewReader(b)
|
||||
result, _ := ioutil.ReadAll(r)
|
||||
str := string(result)
|
||||
|
||||
if str != data.utf8 {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", str, data.utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter(t *testing.T) {
|
||||
for _, data := range testData {
|
||||
e := NewEncoder(data.otherEncoding)
|
||||
if e == nil {
|
||||
t.Errorf("Could not create encoder for %s", data.otherEncoding)
|
||||
continue
|
||||
}
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
w := e.NewWriter(b)
|
||||
w.Write([]byte(data.utf8))
|
||||
str := b.String()
|
||||
|
||||
if str != data.other {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", str, data.other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFallback(t *testing.T) {
|
||||
mixed := "résum\xe9 " // The space is needed because of the issue mentioned in the Note: in fallback.go
|
||||
pure := "résumé "
|
||||
d := FallbackDecoder(NewDecoder("utf8"), NewDecoder("ISO-8859-1"))
|
||||
result := d.ConvertString(mixed)
|
||||
if result != pure {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", result, pure)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEntities(t *testing.T) {
|
||||
escaped := "¬it; I'm ∉ I tell you‚ ≪⃒ "
|
||||
plain := "¬it; I'm ∉ I tell you\u201a \u226A\u20D2 "
|
||||
d := FallbackDecoder(EntityDecoder(), NewDecoder("ISO-8859-1"))
|
||||
result := d.ConvertString(escaped)
|
||||
if result != plain {
|
||||
t.Errorf("Unexpected value: %#v (expected %#v)", result, plain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertStringOK(t *testing.T) {
|
||||
d := NewDecoder("ASCII")
|
||||
if d == nil {
|
||||
t.Fatal("Could not create decoder for ASCII")
|
||||
}
|
||||
|
||||
str, ok := d.ConvertStringOK("hello")
|
||||
if !ok {
|
||||
t.Error("Spurious error found while decoding")
|
||||
}
|
||||
if str != "hello" {
|
||||
t.Errorf("expected %#v, got %#v", "hello", str)
|
||||
}
|
||||
|
||||
str, ok = d.ConvertStringOK("\x80")
|
||||
if ok {
|
||||
t.Error(`Failed to detect error decoding "\x80"`)
|
||||
}
|
||||
|
||||
e := NewEncoder("ISO-8859-3")
|
||||
if e == nil {
|
||||
t.Fatal("Could not create encoder for ISO-8859-1")
|
||||
}
|
||||
|
||||
str, ok = e.ConvertStringOK("nutraĵo")
|
||||
if !ok {
|
||||
t.Error("spurious error while encoding")
|
||||
}
|
||||
if str != "nutra\xbco" {
|
||||
t.Errorf("expected %#v, got %#v", "nutra\xbco", str)
|
||||
}
|
||||
|
||||
str, ok = e.ConvertStringOK("\x80abc")
|
||||
if ok {
|
||||
t.Error("failed to detect invalid UTF-8 while encoding")
|
||||
}
|
||||
|
||||
str, ok = e.ConvertStringOK("русский")
|
||||
if ok {
|
||||
t.Error("failed to detect characters that couldn't be encoded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadCharset(t *testing.T) {
|
||||
d := NewDecoder("this is not a valid charset")
|
||||
if d != nil {
|
||||
t.Fatal("got a non-nil decoder for an invalid charset")
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gogits/gogs/modules/mahonia"
|
||||
)
|
||||
|
||||
// An iconv workalike using mahonia.
|
||||
|
||||
var from = flag.String("f", "utf-8", "source character set")
|
||||
var to = flag.String("t", "utf-8", "destination character set")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var r io.Reader = os.Stdin
|
||||
var w io.Writer = os.Stdout
|
||||
|
||||
if *from != "utf-8" {
|
||||
decode := mahonia.NewDecoder(*from)
|
||||
if decode == nil {
|
||||
log.Fatalf("Could not create decoder for %s", *from)
|
||||
}
|
||||
r = decode.NewReader(r)
|
||||
}
|
||||
|
||||
if *to != "utf-8" {
|
||||
encode := mahonia.NewEncoder(*to)
|
||||
if encode == nil {
|
||||
log.Fatalf("Could not create decoder for %s", *to)
|
||||
}
|
||||
w = encode.NewWriter(w)
|
||||
}
|
||||
|
||||
io.Copy(w, r)
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Generic converters for multibyte character sets.
|
||||
|
||||
// An mbcsTrie contains the data to convert from the character set to Unicode.
|
||||
// If a character would be encoded as "\x01\x02\x03", its unicode value would be found at t.children[1].children[2].children[3].rune
|
||||
// children either is nil or has 256 elements.
|
||||
type mbcsTrie struct {
|
||||
// For leaf nodes, the Unicode character that is represented.
|
||||
char rune
|
||||
|
||||
// For non-leaf nodes, the trie to decode the remainder of the character.
|
||||
children []mbcsTrie
|
||||
}
|
||||
|
||||
// A MBCSTable holds the data to convert to and from Unicode.
|
||||
type MBCSTable struct {
|
||||
toUnicode mbcsTrie
|
||||
fromUnicode map[rune]string
|
||||
}
|
||||
|
||||
// AddCharacter adds a character to the table. rune is its Unicode code point,
|
||||
// and bytes contains the bytes used to encode it in the character set.
|
||||
func (table *MBCSTable) AddCharacter(c rune, bytes string) {
|
||||
if table.fromUnicode == nil {
|
||||
table.fromUnicode = make(map[rune]string)
|
||||
}
|
||||
|
||||
table.fromUnicode[c] = bytes
|
||||
|
||||
trie := &table.toUnicode
|
||||
for i := 0; i < len(bytes); i++ {
|
||||
if trie.children == nil {
|
||||
trie.children = make([]mbcsTrie, 256)
|
||||
}
|
||||
|
||||
b := bytes[i]
|
||||
trie = &trie.children[b]
|
||||
}
|
||||
|
||||
trie.char = c
|
||||
}
|
||||
|
||||
func (table *MBCSTable) Decoder() Decoder {
|
||||
return func(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
status = NO_ROOM
|
||||
return
|
||||
}
|
||||
|
||||
if p[0] == 0 {
|
||||
return 0, 1, SUCCESS
|
||||
}
|
||||
|
||||
trie := &table.toUnicode
|
||||
for trie.char == 0 {
|
||||
if trie.children == nil {
|
||||
return 0xfffd, 1, INVALID_CHAR
|
||||
}
|
||||
if len(p) < size+1 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
trie = &trie.children[p[size]]
|
||||
size++
|
||||
}
|
||||
|
||||
c = trie.char
|
||||
status = SUCCESS
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (table *MBCSTable) Encoder() Encoder {
|
||||
return func(p []byte, c rune) (size int, status Status) {
|
||||
bytes := table.fromUnicode[c]
|
||||
if bytes == "" {
|
||||
if len(p) > 0 {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
} else {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
}
|
||||
|
||||
if len(p) < len(bytes) {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
return copy(p, bytes), SUCCESS
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,151 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// This file is based on bufio.Reader in the Go standard library,
|
||||
// which has the following copyright notice:
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBufSize = 4096
|
||||
)
|
||||
|
||||
// Reader implements character-set decoding for an io.Reader object.
|
||||
type Reader struct {
|
||||
buf []byte
|
||||
rd io.Reader
|
||||
decode Decoder
|
||||
r, w int
|
||||
err error
|
||||
}
|
||||
|
||||
// NewReader creates a new Reader that uses the receiver to decode text.
|
||||
func (d Decoder) NewReader(rd io.Reader) *Reader {
|
||||
b := new(Reader)
|
||||
b.buf = make([]byte, defaultBufSize)
|
||||
b.rd = rd
|
||||
b.decode = d
|
||||
return b
|
||||
}
|
||||
|
||||
// fill reads a new chunk into the buffer.
|
||||
func (b *Reader) fill() {
|
||||
// Slide existing data to beginning.
|
||||
if b.r > 0 {
|
||||
copy(b.buf, b.buf[b.r:b.w])
|
||||
b.w -= b.r
|
||||
b.r = 0
|
||||
}
|
||||
|
||||
// Read new data.
|
||||
n, e := b.rd.Read(b.buf[b.w:])
|
||||
b.w += n
|
||||
if e != nil {
|
||||
b.err = e
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads data into p.
|
||||
// It returns the number of bytes read into p.
|
||||
// It calls Read at most once on the underlying Reader,
|
||||
// hence n may be less than len(p).
|
||||
// At EOF, the count will be zero and err will be os.EOF.
|
||||
func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
filled := false
|
||||
if n == 0 {
|
||||
return 0, b.err
|
||||
}
|
||||
if b.w == b.r {
|
||||
if b.err != nil {
|
||||
return 0, b.err
|
||||
}
|
||||
if n > len(b.buf) {
|
||||
// Large read, empty buffer.
|
||||
// Allocate a larger buffer for efficiency.
|
||||
b.buf = make([]byte, n)
|
||||
}
|
||||
b.fill()
|
||||
filled = true
|
||||
if b.w == b.r {
|
||||
return 0, b.err
|
||||
}
|
||||
}
|
||||
|
||||
i := 0
|
||||
for i < n {
|
||||
rune, size, status := b.decode(b.buf[b.r:b.w])
|
||||
|
||||
if status == STATE_ONLY {
|
||||
b.r += size
|
||||
continue
|
||||
}
|
||||
|
||||
if status == NO_ROOM {
|
||||
if b.err != nil {
|
||||
rune = 0xfffd
|
||||
size = b.w - b.r
|
||||
if size == 0 {
|
||||
break
|
||||
}
|
||||
status = INVALID_CHAR
|
||||
} else if filled {
|
||||
break
|
||||
} else {
|
||||
b.fill()
|
||||
filled = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if i+utf8.RuneLen(rune) > n {
|
||||
break
|
||||
}
|
||||
|
||||
b.r += size
|
||||
if rune < 128 {
|
||||
p[i] = byte(rune)
|
||||
i++
|
||||
} else {
|
||||
i += utf8.EncodeRune(p[i:], rune)
|
||||
}
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// ReadRune reads a single Unicode character and returns the
|
||||
// rune and its size in bytes.
|
||||
func (b *Reader) ReadRune() (c rune, size int, err error) {
|
||||
read:
|
||||
c, size, status := b.decode(b.buf[b.r:b.w])
|
||||
|
||||
if status == NO_ROOM && b.err == nil {
|
||||
b.fill()
|
||||
goto read
|
||||
}
|
||||
|
||||
if status == STATE_ONLY {
|
||||
b.r += size
|
||||
goto read
|
||||
}
|
||||
|
||||
if b.r == b.w {
|
||||
return 0, 0, b.err
|
||||
}
|
||||
|
||||
if status == NO_ROOM {
|
||||
c = 0xfffd
|
||||
size = b.w - b.r
|
||||
status = INVALID_CHAR
|
||||
}
|
||||
|
||||
b.r += size
|
||||
return c, size, nil
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for the Shift-JIS encoding.
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterCharset(&Charset{
|
||||
Name: "Shift_JIS",
|
||||
Aliases: []string{"MS_Kanji", "csShiftJIS", "SJIS", "ibm-943", "windows-31j", "cp932", "windows-932"},
|
||||
NewDecoder: func() Decoder {
|
||||
return decodeSJIS
|
||||
},
|
||||
NewEncoder: func() Encoder {
|
||||
shiftJISOnce.Do(reverseShiftJISTable)
|
||||
return encodeSJIS
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func decodeSJIS(p []byte) (c rune, size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
b := p[0]
|
||||
if b < 0x80 {
|
||||
return rune(b), 1, SUCCESS
|
||||
}
|
||||
|
||||
if 0xa1 <= b && b <= 0xdf {
|
||||
return rune(b) + (0xff61 - 0xa1), 1, SUCCESS
|
||||
}
|
||||
|
||||
if b == 0x80 || b == 0xa0 {
|
||||
return utf8.RuneError, 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
|
||||
jis := int(b)<<8 + int(p[1])
|
||||
c = rune(shiftJISToUnicode[jis])
|
||||
|
||||
if c == 0 {
|
||||
return utf8.RuneError, 2, INVALID_CHAR
|
||||
}
|
||||
return c, 2, SUCCESS
|
||||
}
|
||||
|
||||
func encodeSJIS(p []byte, c rune) (size int, status Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c < 0x80 {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if 0xff61 <= c && c <= 0xff9f {
|
||||
// half-width katakana
|
||||
p[0] = byte(c - (0xff61 - 0xa1))
|
||||
return 1, SUCCESS
|
||||
}
|
||||
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
|
||||
if c > 0xffff {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
jis := unicodeToShiftJIS[c]
|
||||
if jis == 0 {
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
p[0] = byte(jis >> 8)
|
||||
p[1] = byte(jis)
|
||||
return 2, SUCCESS
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
package mahonia
|
||||
|
||||
// Converters for TCVN3 encoding.
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
onceTCVN3 sync.Once
|
||||
dataTCVN3 = struct {
|
||||
UnicodeToWord map[rune][2]byte
|
||||
WordToUnicode [256]struct {
|
||||
r rune
|
||||
m *[256]rune
|
||||
}
|
||||
}{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
p := new(Charset)
|
||||
p.Name = "TCVN3"
|
||||
p.NewDecoder = func() Decoder {
|
||||
onceTCVN3.Do(buildTCVN3Tables)
|
||||
return decodeTCVN3
|
||||
}
|
||||
p.NewEncoder = func() Encoder {
|
||||
onceTCVN3.Do(buildTCVN3Tables)
|
||||
return encodeTCVN3
|
||||
}
|
||||
RegisterCharset(p)
|
||||
}
|
||||
|
||||
func decodeTCVN3(p []byte) (rune, int, Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, 0, NO_ROOM
|
||||
}
|
||||
item := &dataTCVN3.WordToUnicode[p[0]]
|
||||
if item.m != nil && len(p) > 1 {
|
||||
if r := item.m[p[1]]; r != 0 {
|
||||
return r, 2, SUCCESS
|
||||
}
|
||||
}
|
||||
if item.r != 0 {
|
||||
return item.r, 1, SUCCESS
|
||||
}
|
||||
if p[0] < 0x80 {
|
||||
return rune(p[0]), 1, SUCCESS
|
||||
}
|
||||
return '?', 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func encodeTCVN3(p []byte, c rune) (int, Status) {
|
||||
if len(p) == 0 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
if c < rune(0x80) {
|
||||
p[0] = byte(c)
|
||||
return 1, SUCCESS
|
||||
}
|
||||
if v, ok := dataTCVN3.UnicodeToWord[c]; ok {
|
||||
if v[1] != 0 {
|
||||
if len(p) < 2 {
|
||||
return 0, NO_ROOM
|
||||
}
|
||||
p[0] = v[0]
|
||||
p[1] = v[1]
|
||||
return 2, SUCCESS
|
||||
} else {
|
||||
p[0] = v[0]
|
||||
return 1, SUCCESS
|
||||
}
|
||||
}
|
||||
p[0] = '?'
|
||||
return 1, INVALID_CHAR
|
||||
}
|
||||
|
||||
func buildTCVN3Tables() {
|
||||
dataTCVN3.UnicodeToWord = map[rune][2]byte{
|
||||
// one byte
|
||||
0x00C2: {0xA2, 0x00},
|
||||
0x00CA: {0xA3, 0x00},
|
||||
0x00D4: {0xA4, 0x00},
|
||||
0x00E0: {0xB5, 0x00},
|
||||
0x00E1: {0xB8, 0x00},
|
||||
0x00E2: {0xA9, 0x00},
|
||||
0x00E3: {0xB7, 0x00},
|
||||
0x00E8: {0xCC, 0x00},
|
||||
0x00E9: {0xD0, 0x00},
|
||||
0x00EA: {0xAA, 0x00},
|
||||
0x00EC: {0xD7, 0x00},
|
||||
0x00ED: {0xDD, 0x00},
|
||||
0x00F2: {0xDF, 0x00},
|
||||
0x00F3: {0xE3, 0x00},
|
||||
0x00F4: {0xAB, 0x00},
|
||||
0x00F5: {0xE2, 0x00},
|
||||
0x00F9: {0xEF, 0x00},
|
||||
0x00FA: {0xF3, 0x00},
|
||||
0x00FD: {0xFD, 0x00},
|
||||
0x0102: {0xA1, 0x00},
|
||||
0x0103: {0xA8, 0x00},
|
||||
0x0110: {0xA7, 0x00},
|
||||
0x0111: {0xAE, 0x00},
|
||||
0x0129: {0xDC, 0x00},
|
||||
0x0169: {0xF2, 0x00},
|
||||
0x01A0: {0xA5, 0x00},
|
||||
0x01A1: {0xAC, 0x00},
|
||||
0x01AF: {0xA6, 0x00},
|
||||
0x01B0: {0xAD, 0x00},
|
||||
0x1EA1: {0xB9, 0x00},
|
||||
0x1EA3: {0xB6, 0x00},
|
||||
0x1EA5: {0xCA, 0x00},
|
||||
0x1EA7: {0xC7, 0x00},
|
||||
0x1EA9: {0xC8, 0x00},
|
||||
0x1EAB: {0xC9, 0x00},
|
||||
0x1EAD: {0xCB, 0x00},
|
||||
0x1EAF: {0xBE, 0x00},
|
||||
0x1EB1: {0xBB, 0x00},
|
||||
0x1EB3: {0xBC, 0x00},
|
||||
0x1EB5: {0xBD, 0x00},
|
||||
0x1EB7: {0xC6, 0x00},
|
||||
0x1EB9: {0xD1, 0x00},
|
||||
0x1EBB: {0xCE, 0x00},
|
||||
0x1EBD: {0xCF, 0x00},
|
||||
0x1EBF: {0xD5, 0x00},
|
||||
0x1EC1: {0xD2, 0x00},
|
||||
0x1EC3: {0xD3, 0x00},
|
||||
0x1EC5: {0xD4, 0x00},
|
||||
0x1EC7: {0xD6, 0x00},
|
||||
0x1EC9: {0xD8, 0x00},
|
||||
0x1ECB: {0xDE, 0x00},
|
||||
0x1ECD: {0xE4, 0x00},
|
||||
0x1ECF: {0xE1, 0x00},
|
||||
0x1ED1: {0xE8, 0x00},
|
||||
0x1ED3: {0xE5, 0x00},
|
||||
0x1ED5: {0xE6, 0x00},
|
||||
0x1ED7: {0xE7, 0x00},
|
||||
0x1ED9: {0xE9, 0x00},
|
||||
0x1EDB: {0xED, 0x00},
|
||||
0x1EDD: {0xEA, 0x00},
|
||||
0x1EDF: {0xEB, 0x00},
|
||||
0x1EE1: {0xEC, 0x00},
|
||||
0x1EE3: {0xEE, 0x00},
|
||||
0x1EE5: {0xF4, 0x00},
|
||||
0x1EE7: {0xF1, 0x00},
|
||||
0x1EE9: {0xF8, 0x00},
|
||||
0x1EEB: {0xF5, 0x00},
|
||||
0x1EED: {0xF6, 0x00},
|
||||
0x1EEF: {0xF7, 0x00},
|
||||
0x1EF1: {0xF9, 0x00},
|
||||
0x1EF3: {0xFA, 0x00},
|
||||
0x1EF5: {0xFE, 0x00},
|
||||
0x1EF7: {0xFB, 0x00},
|
||||
0x1EF9: {0xFC, 0x00},
|
||||
// two bytes
|
||||
0x00C0: {0x41, 0xB5},
|
||||
0x00C1: {0x41, 0xB8},
|
||||
0x00C3: {0x41, 0xB7},
|
||||
0x00C8: {0x45, 0xCC},
|
||||
0x00C9: {0x45, 0xD0},
|
||||
0x00CC: {0x49, 0xD7},
|
||||
0x00CD: {0x49, 0xDD},
|
||||
0x00D2: {0x4F, 0xDF},
|
||||
0x00D3: {0x4F, 0xE3},
|
||||
0x00D5: {0x4F, 0xE2},
|
||||
0x00D9: {0x55, 0xEF},
|
||||
0x00DA: {0x55, 0xF3},
|
||||
0x00DD: {0x59, 0xFD},
|
||||
0x0128: {0x49, 0xDC},
|
||||
0x0168: {0x55, 0xF2},
|
||||
0x1EA0: {0x41, 0xB9},
|
||||
0x1EA2: {0x41, 0xB6},
|
||||
0x1EA4: {0xA2, 0xCA},
|
||||
0x1EA6: {0xA2, 0xC7},
|
||||
0x1EA8: {0xA2, 0xC8},
|
||||
0x1EAA: {0xA2, 0xC9},
|
||||
0x1EAC: {0xA2, 0xCB},
|
||||
0x1EAE: {0xA1, 0xBE},
|
||||
0x1EB0: {0xA1, 0xBB},
|
||||
0x1EB2: {0xA1, 0xBC},
|
||||
0x1EB4: {0xA1, 0xBD},
|
||||
0x1EB6: {0xA1, 0xC6},
|
||||
0x1EB8: {0x45, 0xD1},
|
||||
0x1EBA: {0x45, 0xCE},
|
||||
0x1EBC: {0x45, 0xCF},
|
||||
0x1EBE: {0xA3, 0xD5},
|
||||
0x1EC0: {0xA3, 0xD2},
|
||||
0x1EC2: {0xA3, 0xD3},
|
||||
0x1EC4: {0xA3, 0xD4},
|
||||
0x1EC6: {0xA3, 0xD6},
|
||||
0x1EC8: {0x49, 0xD8},
|
||||
0x1ECA: {0x49, 0xDE},
|
||||
0x1ECC: {0x4F, 0xE4},
|
||||
0x1ECE: {0x4F, 0xE1},
|
||||
0x1ED0: {0xA4, 0xE8},
|
||||
0x1ED2: {0xA4, 0xE5},
|
||||
0x1ED4: {0xA4, 0xE6},
|
||||
0x1ED6: {0xA4, 0xE7},
|
||||
0x1ED8: {0xA4, 0xE9},
|
||||
0x1EDA: {0xA5, 0xED},
|
||||
0x1EDC: {0xA5, 0xEA},
|
||||
0x1EDE: {0xA5, 0xEB},
|
||||
0x1EE0: {0xA5, 0xEC},
|
||||
0x1EE2: {0xA5, 0xEE},
|
||||
0x1EE4: {0x55, 0xF4},
|
||||
0x1EE6: {0x55, 0xF1},
|
||||
0x1EE8: {0xA6, 0xF8},
|
||||
0x1EEA: {0xA6, 0xF5},
|
||||
0x1EEC: {0xA6, 0xF6},
|
||||
0x1EEE: {0xA6, 0xF7},
|
||||
0x1EF0: {0xA6, 0xF9},
|
||||
0x1EF2: {0x59, 0xFA},
|
||||
0x1EF4: {0x59, 0xFE},
|
||||
0x1EF6: {0x59, 0xFB},
|
||||
0x1EF8: {0x59, 0xFC},
|
||||
}
|
||||
for r, b := range dataTCVN3.UnicodeToWord {
|
||||
item := &dataTCVN3.WordToUnicode[b[0]]
|
||||
if b[1] == 0 {
|
||||
item.r = r
|
||||
} else {
|
||||
if item.m == nil {
|
||||
item.m = new([256]rune)
|
||||
}
|
||||
item.m[b[1]] = r
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user