chore(i18n,learn): processed translations (#45504)
This commit is contained in:
@@ -16,7 +16,7 @@ dashedName: anonymous-message-board
|
||||
- 使用 [我們的 Replit 啓動項目](https://replit.com/github/freeCodeCamp/boilerplate-project-messageboard)來完成你的項目。
|
||||
- 使用一個你喜歡的站點生成器來完成項目。 需要確定包含了我們 GitHub 倉庫的所有文件。
|
||||
|
||||
完成本項目後,請將一個正常運行的 demo(項目演示)託管在可以公開訪問的平臺。 然後將 URL 提交到 `Solution Link` 中。 此外,還可以將項目的源碼提交到 `GitHub Link` 中。
|
||||
完成本項目後,請將一個正常運行的 demo(項目演示)託管在可以公開訪問的平臺。 然後將 URL 提交到 `Solution Link` 中。 此外,還可以提交一個指向項目源碼的 `GitHub Link`。
|
||||
|
||||
# --instructions--
|
||||
|
||||
@@ -116,49 +116,270 @@ async (getUserInput) => {
|
||||
你可以向 `/api/replies/{board}` 發送一個 POST 請求,其中包括字段 `text`、`delete_password` & `thread_id`。 這將更新 `bumped_on` 日期到評論日期。 在主題的 `replies` 數組中,將保存一個對象,至少有 `_id`、`text`、`created_on`、`delete_password`、& `reported` 這些屬性。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
const body = await fetch(url + '/api/threads/fcc_test');
|
||||
const thread = await body.json();
|
||||
|
||||
const date = new Date();
|
||||
const text = `fcc_test_reply_${date}`;
|
||||
const delete_password = 'delete_me';
|
||||
const thread_id = thread[0]._id;
|
||||
const replyCount = thread[0].replies.length;
|
||||
|
||||
const data = { text, delete_password, thread_id };
|
||||
const res = await fetch(url + '/api/replies/fcc_test', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
if (res.ok) {
|
||||
const checkData = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
|
||||
const parsed = await checkData.json();
|
||||
try {
|
||||
assert.equal(parsed.replies.length, replyCount + 1);
|
||||
assert.equal(parsed.replies[0].text, text);
|
||||
assert.equal(parsed._id, thread_id);
|
||||
assert.equal(parsed.bumped_on, parsed.replies[0].created_on);
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以向 `/api/threads/{board}` 發送一個 GET 請求。 返回的將是一個數組,包括論壇上最近的 10 個被回覆的主題,及每個主題最新的 3 個回帖。 `reported` 和 `delete_password` 字段將不會被髮送到客戶端。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
const res = await fetch(url + '/api/threads/fcc_test');
|
||||
|
||||
if (res.ok) {
|
||||
const threads = await res.json();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.isAtMost(threads.length, 10);
|
||||
for (let i = 0; i < threads.length; i++) {
|
||||
assert.containsAllKeys(threads[i], ["_id", "text", "created_on", "bumped_on", "replies"]);
|
||||
assert.isAtMost(threads[i].replies.length, 3);
|
||||
assert.notExists(threads[i].delete_password);
|
||||
assert.notExists(threads[i].reported);
|
||||
for (let j = 0; j < threads[i].replies.length; j++) {
|
||||
assert.notExists(threads[i].replies[j].delete_password);
|
||||
assert.notExists(threads[i].replies[j].reported);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以向 `/api/replies/{board}?thread_id={thread_id}` 發送一個 GET 請求。 返回的將是帶有所有的回覆的整個主題,不包括與之前測試相同的客戶端字段。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
let res = await fetch(url + '/api/threads/fcc_test');
|
||||
const threads = await res.json();
|
||||
const thread_id = threads[0]._id;
|
||||
res = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
|
||||
|
||||
if (res.ok) {
|
||||
const thread = await res.json();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.isObject(thread);
|
||||
assert.containsAllKeys(thread, ["_id", "text", "created_on", "bumped_on", "replies"]);
|
||||
assert.isArray(thread.replies);
|
||||
assert.notExists(thread.delete_password);
|
||||
assert.notExists(thread.reported);
|
||||
for (let i = 0; i < thread.replies.length; i++) {
|
||||
assert.notExists(thread.replies[i].delete_password);
|
||||
assert.notExists(thread.replies[i].reported);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以向 `/api/threads/{board}` 發送一個 DELETE 請求,並傳遞 `thread_id` & `delete_password` 來刪除該線程。 返回的將是字符串 `incorrect password` 或 `success`。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
let res = await fetch(url + '/api/threads/fcc_test');
|
||||
const threads = await res.json();
|
||||
const thread_id = threads[0]._id;
|
||||
let data = { thread_id, delete_password: "wrong_password" };
|
||||
const res_invalid = await fetch(url + '/api/threads/fcc_test', {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
data = { thread_id, delete_password: "delete_me" };
|
||||
res = await fetch(url + '/api/threads/fcc_test', {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const deleted = await res.text();
|
||||
const not_deleted = await res_invalid.text();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(deleted, "success");
|
||||
assert.equal(not_deleted, "incorrect password");
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以向 `/api/replies/{board}` 發送一個 DELETE 請求,並傳遞 `thread_id`、`reply_id`、& `delete_password`。 返回的將是字符串 `incorrect password` 或 `success`。 成功後,`reply_id` 的文本將更改爲 `[deleted]`。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
|
||||
const thread_data = {
|
||||
text: "fcc_test_thread",
|
||||
delete_password: "delete_me",
|
||||
};
|
||||
await fetch(`${url}/api/threads/fcc_test`, {
|
||||
method: "POST",
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(thread_data)
|
||||
});
|
||||
let res = await fetch(`${url}/api/threads/fcc_test`);
|
||||
let threads = await res.json();
|
||||
const thread_id = threads[0]._id;
|
||||
|
||||
const reply_data = { thread_id, text: "fcc_test_reply", delete_password: "delete_me" };
|
||||
await fetch(`${url}/api/replies/fcc_test`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(reply_data)
|
||||
});
|
||||
res = await fetch(`${url}/api/threads/fcc_test`);
|
||||
threads = await res.json();
|
||||
const reply_id = threads[0].replies[0]._id;
|
||||
|
||||
const data = { thread_id, reply_id, delete_password: "delete_me" };
|
||||
res = await fetch(url + '/api/replies/fcc_test', {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const deleted = await res.text();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(deleted, "success");
|
||||
res = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
|
||||
const thread = await res.json();
|
||||
assert.equal(thread._id, thread_id);
|
||||
assert.equal(thread.replies[0]._id, reply_id);
|
||||
assert.equal(thread.replies[0].text, "[deleted]");
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以向 `/api/threads/{board}` 發送一個 PUT 請求,並傳遞 `thread_id`。 返回的將是字符串 `success`。 `thread_id` 回覆的 `reported` 值將改爲 `true`。
|
||||
你可以向 `/api/threads/{board}` 發送一個 PUT 請求,並傳遞 `thread_id`。 返回的將是字符串 `reported`。 `thread_id` 回覆的 `reported` 值將改爲 `true`。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
|
||||
let res = await fetch(`${url}/api/threads/fcc_test`);
|
||||
const threads = await res.json();
|
||||
const report_id = threads[0]._id;
|
||||
const data = { report_id };
|
||||
|
||||
res = await fetch(`${url}/api/threads/fcc_test`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const reported = await res.text();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(reported, "reported");
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
你可以通過向 `/api/replies/{board}` 發送 PUT 請求並傳遞 `thread_id` & `reply_id`。 返回的將是字符串 `success`。 `reply_id` 的 `reported` 值將被改變爲 `true`。
|
||||
你可以通過向 `/api/replies/{board}` 發送 PUT 請求並傳遞 `thread_id` & `reply_id`。 返回的將是字符串 `reported`。 `reply_id` 的 `reported` 值將被改變爲 `true`。
|
||||
|
||||
```js
|
||||
async (getUserInput) => {
|
||||
const url = getUserInput('url');
|
||||
|
||||
let res = await fetch(`${url}/api/threads/fcc_test`);
|
||||
const threads = await res.json();
|
||||
const thread_id = threads[0]._id;
|
||||
const reply_id = threads[0].replies[0]._id;
|
||||
const data = { thread_id, reply_id };
|
||||
|
||||
res = await fetch(`${url}/api/replies/fcc_test`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const reported = await res.text();
|
||||
try {
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(reported, "reported");
|
||||
} catch (err) {
|
||||
throw new Error(err.responseText || err.message);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
所有 10 項功能測試都已完成並通過。
|
||||
|
||||
```js
|
||||
|
||||
async (getUserInput) => {
|
||||
const tests = await fetch(getUserInput('url') + '/_api/get-tests');
|
||||
const parsed = await tests.json();
|
||||
assert.isTrue(parsed.length >= 10);
|
||||
parsed.forEach((test) => {
|
||||
assert.equal(test.state, 'passed');
|
||||
assert.isAtLeast(test.assertions.length, 1);
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
@@ -9,22 +9,74 @@ dashedName: port-scanner
|
||||
|
||||
# --description--
|
||||
|
||||
你將通過使用我們的 [Replit 入門代碼](https://replit.com/github/freeCodeCamp/boilerplate-port-scanner) 來完成本項目。
|
||||
|
||||
我們仍在開發 Python 課程的交互式教學部分。 目前,你可以在 YouTube 上通過 freeCodeCamp.org 上傳的一些視頻學習這個項目相關的知識。
|
||||
|
||||
- [Python for Everybody 視頻課程](https://www.freecodecamp.org/news/python-for-everybody/)(14 小時)
|
||||
|
||||
- [Learn Python 視頻課程](https://www.freecodecamp.org/news/learn-python-video-course/)(10 小時)
|
||||
|
||||
# --instructions--
|
||||
|
||||
使用 Python 創建一個端口掃描器。
|
||||
|
||||
你可以訪問 [Replit 上的完整項目描述和啓動代碼](https://replit.com/github/freeCodeCamp/boilerplate-port-scanner)。
|
||||
在 `port_scanner.py` 文件中,創建一個名爲 `get_open_ports` 的函數,它接受一個 `target` 參數和一個 `port_range` 參數。 `target` 可以是 URL 或 IP 地址。 `port_range` 是兩個數字的列表,表示要檢查的端口範圍的第一個和最後一個數字。
|
||||
|
||||
在打開鏈接之後 fork 該項目。 根據 “README.md” 中的指示完成整個項目,然後在下面提交你的項目鏈接。
|
||||
以下是如何調用該函數的示例:
|
||||
|
||||
Python 課程的交互式教學部分仍在開發當中。 目前,freeCodeCamp YouTube 頻道上的一些視頻將會教授你這個項目要求的一些 Python 技能。
|
||||
```py
|
||||
get_open_ports("209.216.230.240", [440, 445])
|
||||
get_open_ports("www.stackoverflow.com", [79, 82])
|
||||
```
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href='https://www.freecodecamp.org/news/python-for-everybody/'>Python for Everybody 視頻課程</a>(14 小時)
|
||||
</li>
|
||||
<li>
|
||||
<a href='https://www.freecodecamp.org/news/learn-python-basics-in-depth-video-course/'>Learn Python 視頻課程</a>(2 小時)
|
||||
</li>
|
||||
</ul>
|
||||
該函數應返回給定範圍內的開放端口列表。
|
||||
|
||||
`get_open_ports` 函數還應採用可選的第三個參數 `True` 來表示“詳細”模式。 如果將其設置爲 true,則該函數應返回描述性字符串而不是端口列表。
|
||||
|
||||
以下是詳細模式下應返回的字符串格式(`{}` 中的文本表示應顯示的信息):
|
||||
|
||||
```bash
|
||||
Open ports for {URL} ({IP address})
|
||||
PORT SERVICE
|
||||
{port} {service name}
|
||||
{port} {service name}
|
||||
```
|
||||
|
||||
你可以使用 `common_ports.py` 中的字典爲每個端口獲取正確的服務名稱。
|
||||
|
||||
例如,如果函數是這樣調用的:
|
||||
|
||||
```py
|
||||
port_scanner.get_open_ports("scanme.nmap.org", [20, 80], True)
|
||||
```
|
||||
|
||||
它應該返回以下內容:
|
||||
|
||||
```bash
|
||||
Open ports for scanme.nmap.org (45.33.32.156)
|
||||
PORT SERVICE
|
||||
22 ssh
|
||||
80 http
|
||||
```
|
||||
|
||||
確保包含正確的間距和換行符。
|
||||
|
||||
如果傳入 `get_open_ports` 函數的 URL 無效,該函數應返回字符串:“Error: Invalid hostname”。
|
||||
|
||||
如果傳入 `get_open_ports` 函數的 IP 地址無效,該函數應返回字符串:“Error: Invalid IP address”。
|
||||
|
||||
## 開發
|
||||
|
||||
在 `port_scanner.py` 中編寫你的代碼。 對於開發,你可以使用 `main.py` 來測試你的代碼。 單擊“運行”按鈕,`main.py` 將運行。
|
||||
|
||||
## 測試
|
||||
|
||||
這個項目的單元測試在 `test_module.py` 中。 爲了你的方便,我們將測試從 `test_module.py` 導入到 `main.py`。 只要你點擊“運行”按鈕,測試就會自動運行。
|
||||
|
||||
## 提交
|
||||
|
||||
複製項目的 URL 並將其提交給 freeCodeCamp。
|
||||
|
||||
# --hints--
|
||||
|
||||
|
@@ -9,22 +9,51 @@ dashedName: sha-1-password-cracker
|
||||
|
||||
# --description--
|
||||
|
||||
你將通過使用我們的 [Replit 入門代碼](https://replit.com/github/freeCodeCamp/boilerplate-SHA-1-password-cracker) 來完成本項目。
|
||||
|
||||
我們仍在開發 Python 課程的交互式教學部分。 目前,你可以在 YouTube 上通過 freeCodeCamp.org 上傳的一些視頻學習這個項目相關的知識。
|
||||
|
||||
- [Python for Everybody 視頻課程](https://www.freecodecamp.org/news/python-for-everybody/)(14 小時)
|
||||
|
||||
- [Learn Python 視頻課程](https://www.freecodecamp.org/news/learn-python-video-course/)(10 小時)
|
||||
|
||||
# --instructions--
|
||||
|
||||
密碼不應以純文本形式存儲。 它們應該存儲爲哈希值,以防萬一密碼列表被泄露。 然而,並不是所有的哈希都是一樣的。
|
||||
|
||||
在這個項目中,你將通過創建一個密碼破解器來找出使用 SHA-1 散列的密碼,從而瞭解到良好安全的重要性。
|
||||
|
||||
你可以訪問 [Replit 上的完整項目描述和啓動代碼](https://replit.com/github/freeCodeCamp/boilerplate-SHA-1-password-cracker)。
|
||||
創建一個函數,該函數接受密碼的 SHA-1 哈希值,如果它是使用的前 10,000 個密碼之一,則返回該密碼。 如果 SHA-1 哈希不是數據庫中的密碼,則返回“密碼不在數據庫中”。
|
||||
|
||||
進入該鏈接後,fork 該項目。 一旦你根據 “README.md” 中的說明完成了項目,請在下面提交你的項目鏈接。
|
||||
該函數應該對 `top-10000-passwords.txt` 中的每個密碼進行散列,並將其與傳遞給函數的散列進行比較。
|
||||
|
||||
我們仍在開發 Python 課程的交互式教學部分。 目前,freeCodeCamp.org YouTube 頻道上的一些視頻可以教你這個項目所需的一些 Python 技能。
|
||||
該函數應採用名爲 `use_salts` 的可選第二個參數。 如果設置爲 true,則文件 `known-salts.txt` 中的每個 salt 字符串,都應該在散列之前,和將它與傳遞給函數的哈希值進行比較之前,添加到 `top-10000-passwords.txt` 中的每個密碼的之前和之後。
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href='https://www.freecodecamp.org/news/python-for-everybody/'>Python for Everybody 視頻課程</a>(14 小時)
|
||||
</li>
|
||||
<li>
|
||||
<a href='https://www.freecodecamp.org/news/learn-python-basics-in-depth-video-course/'>Learn Python 視頻課程</a>(2 小時)
|
||||
</li>
|
||||
</ul>
|
||||
以下是一些用於測試該功能的散列密碼:
|
||||
|
||||
- `b305921a3723cd5d70a375cd21a61e60aabb84ec` 應該返回 “sammy123”
|
||||
- `c7ab388a5ebefbf4d550652f1eb4d833e5316e3e` 應該返回 “abacab”
|
||||
- `5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8` 應該返回 “password”
|
||||
|
||||
以下是一些散列密碼,用於在 `use_salts` 設置爲 `True` 時測試該功能:
|
||||
|
||||
- `53d8b3dc9d39f0184144674e310185e41a87ffd5` 應該返回 “superman”
|
||||
- `da5a4e8cf89539e66097acd2f8af128acae2f8ae` 應該返回 “q1w2e3r4t5”
|
||||
- `ea3f62d498e3b98557f9f9cd0d905028b3b019e1` 應該返回 “bubbles1”
|
||||
|
||||
`hashlib` 庫已經爲你導入。 你應該在你的代碼中使用它。 [在此瞭解更多關於 “hashlib” 的信息](https://docs.python.org/3/library/hashlib.html)
|
||||
|
||||
## 開發
|
||||
|
||||
在 `password_cracker.py` 中編寫你的代碼。 對於開發,你可以使用 `main.py` 來測試你的代碼。 單擊“運行”按鈕,`main.py` 將運行。
|
||||
|
||||
## 測試
|
||||
|
||||
此項目的單元測試在 `test_module.py` 中。 爲了你的方便,我們將測試從 `test_module.py` 導入到 `main.py`。 只要你點擊“運行”按鈕,測試就會自動運行。
|
||||
|
||||
## 提交
|
||||
|
||||
複製項目的 URL 並將其提交給 freeCodeCamp。
|
||||
|
||||
# --hints--
|
||||
|
||||
|
Reference in New Issue
Block a user