|
1 | | -import { exists, readFile } from 'hexo-fs'; |
2 | | -import { basename, extname, join, posix } from 'path'; |
| 1 | +import { basename, extname, join } from 'path'; |
| 2 | +import { url_for } from 'hexo-util'; |
3 | 3 | import type Hexo from '../../hexo'; |
4 | 4 |
|
5 | 5 | const rCaptionTitleFile = /(.*)?(?:\s+|^)(\/*\S+)/; |
@@ -47,32 +47,31 @@ export = (ctx: Hexo) => function includeCodeTag(args: string[]) { |
47 | 47 | // If the language is not defined, use file extension instead |
48 | 48 | lang = lang || extname(path).substring(1); |
49 | 49 |
|
50 | | - const src = join(ctx.source_dir, codeDir, path); |
| 50 | + const source = join(codeDir, path).replace(/\\/g, '/'); |
51 | 51 |
|
52 | | - // If the title is not defined, use file name instead |
53 | | - const title = match[1] || basename(path); |
54 | | - const caption = `<span>${title}</span><a href="${posix.join(ctx.config.root, codeDir, path)}">view raw</a>`; |
55 | | - |
56 | | - return exists(src).then(exist => { |
57 | | - if (exist) return readFile(src); |
58 | | - }).then(code => { |
59 | | - if (!code) return; |
| 52 | + // Prevent path traversal: https://github.com/hexojs/hexo/issues/5250 |
| 53 | + const Page = ctx.model('Page'); |
| 54 | + const doc = Page.findOne({ source }); |
| 55 | + if (!doc) return; |
60 | 56 |
|
61 | | - const lines = code.split('\n'); |
62 | | - code = lines.slice(from, to).join('\n').trim(); |
| 57 | + let code = doc.content; |
| 58 | + const lines = code.split('\n'); |
| 59 | + code = lines.slice(from, to).join('\n').trim(); |
63 | 60 |
|
64 | | - if (ctx.extend.highlight.query(ctx.config.syntax_highlighter)) { |
65 | | - const options = { |
66 | | - lang, |
67 | | - caption, |
68 | | - lines_length: lines.length |
69 | | - }; |
70 | | - return ctx.extend.highlight.exec(ctx.config.syntax_highlighter, { |
71 | | - context: ctx, |
72 | | - args: [code, options] |
73 | | - }); |
74 | | - } |
| 61 | + // If the title is not defined, use file name instead |
| 62 | + const title = match[1] || basename(path); |
| 63 | + const caption = `<span>${title}</span><a href="${url_for.call(ctx, doc.path)}">view raw</a>`; |
75 | 64 |
|
76 | | - return `<pre><code>${code}</code></pre>`; |
77 | | - }); |
| 65 | + if (ctx.extend.highlight.query(ctx.config.syntax_highlighter)) { |
| 66 | + const options = { |
| 67 | + lang, |
| 68 | + caption, |
| 69 | + lines_length: lines.length |
| 70 | + }; |
| 71 | + return ctx.extend.highlight.exec(ctx.config.syntax_highlighter, { |
| 72 | + context: ctx, |
| 73 | + args: [code, options] |
| 74 | + }); |
| 75 | + } |
| 76 | + return `<pre><code>${code}</code></pre>`; |
78 | 77 | }; |
0 commit comments