Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gzupanda
code-server
提交
9fdfacb3
C
code-server
项目概览
gzupanda
/
code-server
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
code-server
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
9fdfacb3
编写于
7月 19, 2019
作者:
A
Asher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Quality check
上级
e8cb6ffa
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
191 addition
and
426 deletion
+191
-426
scripts/nbin-shim.js
scripts/nbin-shim.js
+2
-6
src/api.ts
src/api.ts
+8
-34
src/channel.ts
src/channel.ts
+2
-14
src/cli.ts
src/cli.ts
+11
-22
src/connection.ts
src/connection.ts
+8
-32
src/protocol.ts
src/protocol.ts
+1
-4
src/server.ts
src/server.ts
+47
-117
src/tar.ts
src/tar.ts
+100
-164
src/uriTransformerHttp.js
src/uriTransformerHttp.js
+1
-2
src/uriTransformerHttps.js
src/uriTransformerHttps.js
+1
-3
src/util.ts
src/util.ts
+10
-28
未找到文件。
scripts/nbin-shim.js
浏览文件 @
9fdfacb3
/* global require, global, process, __dirname */
if
(
!
global
.
NBIN_LOADED
)
{
try
{
const
nbin
=
require
(
"
nbin
"
);
nbin
.
shimNativeFs
(
"
{{ROOT_PATH}}
"
);
global
.
NBIN_LOADED
=
true
;
const
path
=
require
(
"
path
"
);
const
rg
=
require
(
"
vscode-ripgrep
"
);
rg
.
binaryRgPath
=
rg
.
rgPath
;
rg
.
rgPath
=
path
.
join
(
require
(
"
os
"
).
tmpdir
(),
`code-server/
${
path
.
basename
(
rg
.
binaryRgPath
)}
`
,
`code-server/
${
path
.
basename
(
rg
.
binaryRgPath
)}
`
);
}
catch
(
error
)
{
// Not in the binary.
}
}
catch
(
error
)
{
/* Not in the binary. */
}
}
src/api.ts
浏览文件 @
9fdfacb3
...
...
@@ -60,7 +60,6 @@ export const vscodeApi = (serviceCollection: ServiceCollection): typeof vscode =
FileSystemError
:
extHostTypes
.
FileSystemError
,
FileType
:
FileType
,
Uri
:
URI
,
commands
:
{
executeCommand
:
(
commandId
:
string
,
...
args
:
any
[]):
any
=>
{
return
commandService
.
executeCommand
(
commandId
,
...
args
);
...
...
@@ -69,7 +68,6 @@ export const vscodeApi = (serviceCollection: ServiceCollection): typeof vscode =
return
CommandsRegistry
.
registerCommand
(
id
,
command
);
},
},
window
:
{
registerTreeDataProvider
:
(
id
:
string
,
dataProvider
:
ITreeViewDataProvider
):
void
=>
{
const
view
=
viewsRegistry
.
getView
(
id
);
...
...
@@ -81,7 +79,6 @@ export const vscodeApi = (serviceCollection: ServiceCollection): typeof vscode =
notificationService
.
error
(
message
);
},
},
workspace
:
{
registerFileSystemProvider
:
(
scheme
:
string
,
provider
:
vscode
.
FileSystemProvider
):
IDisposable
=>
{
return
fileService
.
registerProvider
(
scheme
,
new
FileSystemProvider
(
provider
));
...
...
@@ -95,7 +92,6 @@ export const vscodeApi = (serviceCollection: ServiceCollection): typeof vscode =
*/
export
const
coderApi
=
(
serviceCollection
:
ServiceCollection
):
typeof
coder
=>
{
const
getService
=
<
T
>
(
id
:
ServiceIdentifier
<
T
>
):
T
=>
serviceCollection
.
get
<
T
>
(
id
)
as
T
;
return
{
workbench
:
{
action
:
Action
,
...
...
@@ -103,13 +99,8 @@ export const coderApi = (serviceCollection: ServiceCollection): typeof coder =>
commandRegistry
:
CommandsRegistry
,
actionsRegistry
:
Registry
.
as
<
IWorkbenchActionRegistry
>
(
ActionExtensions
.
WorkbenchActions
),
registerView
:
(
viewId
,
viewName
,
containerId
,
containerName
,
icon
):
void
=>
{
const
viewContainersRegistry
=
Registry
.
as
<
IViewContainersRegistry
>
(
ViewsExtensions
.
ViewContainersRegistry
);
const
viewsRegistry
=
Registry
.
as
<
IViewsRegistry
>
(
ViewsExtensions
.
ViewsRegistry
);
const
container
=
viewContainersRegistry
.
registerViewContainer
(
containerId
);
const
cssClass
=
`extensionViewlet-
${
containerId
}
`
;
const
id
=
`workbench.view.extension.
${
containerId
}
`
;
class
CustomViewlet
extends
ViewContainerViewlet
{
public
constructor
(
@
IConfigurationService
configurationService
:
IConfigurationService
,
...
...
@@ -127,44 +118,32 @@ export const coderApi = (serviceCollection: ServiceCollection): typeof coder =>
}
}
const
viewletDescriptor
=
new
ViewletDescriptor
(
CustomViewlet
as
any
,
id
,
containerName
,
cssClass
,
undefined
,
URI
.
parse
(
icon
),
Registry
.
as
<
ViewletRegistry
>
(
ViewletExtensions
.
Viewlets
).
registerViewlet
(
new
ViewletDescriptor
(
CustomViewlet
as
any
,
id
,
containerName
,
cssClass
,
undefined
,
URI
.
parse
(
icon
)),
);
Registry
.
as
<
ViewletRegistry
>
(
ViewletExtensions
.
Viewlets
).
registerViewlet
(
viewletDescriptor
);
const
registry
=
Registry
.
as
<
IWorkbenchActionRegistry
>
(
ActionExtensions
.
WorkbenchActions
);
registry
.
registerWorkbenchAction
(
Registry
.
as
<
IWorkbenchActionRegistry
>
(
ActionExtensions
.
WorkbenchActions
).
registerWorkbenchAction
(
new
SyncActionDescriptor
(
OpenCustomViewletAction
as
any
,
id
,
localize
(
"
showViewlet
"
,
"
Show {0}
"
,
containerName
)),
"
View: Show {0}
"
,
localize
(
"
view
"
,
"
View
"
),
);
// Generate CSS to show the icon in the activity bar
// Generate CSS to show the icon in the activity bar
.
const
iconClass
=
`.monaco-workbench .activitybar .monaco-action-bar .action-label.
${
cssClass
}
`
;
createCSSRule
(
iconClass
,
`-webkit-mask: url('
${
icon
}
') no-repeat 50% 50%`
);
const
views
=
[{
const
container
=
Registry
.
as
<
IViewContainersRegistry
>
(
ViewsExtensions
.
ViewContainersRegistry
).
registerViewContainer
(
containerId
);
Registry
.
as
<
IViewsRegistry
>
(
ViewsExtensions
.
ViewsRegistry
).
registerViews
([{
id
:
viewId
,
name
:
viewName
,
ctorDescriptor
:
{
ctor
:
CustomTreeViewPanel
},
treeView
:
getService
(
IInstantiationService
).
createInstance
(
CustomTreeView
as
any
,
viewId
,
container
),
}]
as
ITreeViewDescriptor
[];
viewsRegistry
.
registerViews
(
views
,
container
);
}]
as
ITreeViewDescriptor
[],
container
);
},
// Even though the enums are exactly the same, Typescript says they are
// not assignable to each other, so use `any`. I don't know if there is a
// way around this.
menuRegistry
:
MenuRegistry
as
any
,
statusbarService
:
getService
(
IStatusbarService
)
as
any
,
notificationService
:
getService
(
INotificationService
),
terminalService
:
getService
(
ITerminalService
),
onFileCreate
:
(
cb
):
void
=>
{
getService
<
IFileService
>
(
IFileService
).
onAfterOperation
((
e
)
=>
{
if
(
e
.
operation
===
FileOperation
.
CREATE
)
{
...
...
@@ -198,7 +177,6 @@ export const coderApi = (serviceCollection: ServiceCollection): typeof coder =>
}
});
},
onModelAdded
:
(
cb
):
void
=>
{
getService
<
IModelService
>
(
IModelService
).
onModelAdded
((
e
)
=>
{
cb
(
e
.
uri
.
path
,
e
.
getLanguageIdentifier
().
language
);
...
...
@@ -214,7 +192,6 @@ export const coderApi = (serviceCollection: ServiceCollection): typeof coder =>
cb
(
e
.
model
.
uri
.
path
,
e
.
model
.
getLanguageIdentifier
().
language
,
e
.
oldModeId
);
});
},
onTerminalAdded
:
(
cb
):
void
=>
{
getService
<
ITerminalService
>
(
ITerminalService
).
onInstanceCreated
(()
=>
cb
());
},
...
...
@@ -222,7 +199,6 @@ export const coderApi = (serviceCollection: ServiceCollection): typeof coder =>
getService
<
ITerminalService
>
(
ITerminalService
).
onInstanceDisposed
(()
=>
cb
());
},
},
// @ts-ignore
MenuId
:
MenuId
,
Severity
:
Severity
,
...
...
@@ -250,9 +226,7 @@ class FileSystemProvider implements IFileSystemProvider {
public
readonly
capabilities
:
FileSystemProviderCapabilities
;
public
readonly
onDidChangeCapabilities
:
Event
<
void
>
=
Event
.
None
;
public
constructor
(
private
readonly
provider
:
vscode
.
FileSystemProvider
,
)
{
public
constructor
(
private
readonly
provider
:
vscode
.
FileSystemProvider
)
{
this
.
capabilities
=
FileSystemProviderCapabilities
.
Readonly
;
}
...
...
src/channel.ts
浏览文件 @
9fdfacb3
...
...
@@ -43,9 +43,6 @@ class Watcher extends DiskFileSystemProvider {
}
}
/**
* See: src/vs/platform/remote/common/remoteAgentFileSystemChannel.ts.
*/
export
class
FileProviderChannel
implements
IServerChannel
,
IDisposable
{
private
readonly
provider
:
DiskFileSystemProvider
;
private
readonly
watchers
=
new
Map
<
string
,
Watcher
>
();
...
...
@@ -175,9 +172,6 @@ export class FileProviderChannel implements IServerChannel, IDisposable {
}
}
/**
* See: src/vs/workbench/services/remote/common/remoteAgentEnvironmentChannel.ts.
*/
export
class
ExtensionEnvironmentChannel
implements
IServerChannel
{
public
constructor
(
private
readonly
environment
:
IEnvironmentService
,
...
...
@@ -245,7 +239,6 @@ export class ExtensionEnvironmentChannel implements IServerChannel {
};
return
Promise
.
all
([
scanBuiltin
(),
scanInstalled
()]).
then
((
allExtensions
)
=>
{
// It's possible to get duplicates.
const
uniqueExtensions
=
new
Map
<
string
,
IExtensionDescription
>
();
allExtensions
.
forEach
((
multipleExtensions
)
=>
{
multipleExtensions
.
forEach
((
extensions
)
=>
{
...
...
@@ -254,18 +247,13 @@ export class ExtensionEnvironmentChannel implements IServerChannel {
if
(
uniqueExtensions
.
has
(
id
))
{
const
oldPath
=
uniqueExtensions
.
get
(
id
)
!
.
extensionLocation
.
fsPath
;
const
newPath
=
extension
.
extensionLocation
.
fsPath
;
this
.
log
.
warn
(
`Extension
${
id
}
in
${
oldPath
}
has been overridden
${
newPath
}
`
,
);
this
.
log
.
warn
(
`
${
oldPath
}
has been overridden
${
newPath
}
`
);
}
uniqueExtensions
.
set
(
id
,
extension
);
});
});
});
const
finalExtensions
=
<
IExtensionDescription
[]
>
[];
uniqueExtensions
.
forEach
((
e
)
=>
finalExtensions
.
push
(
e
));
return
finalExtensions
;
return
Array
.
from
(
uniqueExtensions
.
values
());
});
}
...
...
src/cli.ts
浏览文件 @
9fdfacb3
...
...
@@ -92,12 +92,7 @@ const main = async (): Promise<void> => {
const
version
=
`
${(
pkg
as
any
).
codeServerVersion
||
"
development
"
}
-vsc
${
pkg
.
version
}
`
;
if
(
args
.
help
)
{
const
executable
=
`
${
product
.
applicationName
}${
os
.
platform
()
===
"
win32
"
?
"
.exe
"
:
""
}
`
;
return
console
.
log
(
buildHelpMessage
(
product
.
nameLong
,
executable
,
version
,
undefined
,
false
,
));
return
console
.
log
(
buildHelpMessage
(
product
.
nameLong
,
executable
,
version
,
undefined
,
false
));
}
if
(
args
.
version
)
{
...
...
@@ -116,26 +111,22 @@ const main = async (): Promise<void> => {
if
(
shouldSpawnCliProcess
())
{
const
cli
=
await
new
Promise
<
IMainCli
>
((
c
,
e
)
=>
require
([
"
vs/code/node/cliProcessMain
"
],
c
,
e
));
await
cli
.
main
(
args
);
// There is some WriteStream instance keeping it open so force an exit.
return
process
.
exit
(
0
);
return
process
.
exit
(
0
);
// There is a WriteStream instance keeping it open.
}
const
extra
=
args
[
"
_
"
]
||
[];
const
options
=
{
host
:
args
.
host
,
allowHttp
:
args
[
"
allow-http
"
],
auth
:
typeof
args
.
auth
!==
"
undefined
"
?
args
.
auth
:
true
,
cert
:
args
.
cert
,
certKey
:
args
[
"
cert-key
"
],
auth
:
typeof
args
.
auth
!==
"
undefined
"
?
args
.
auth
:
true
,
folderUri
:
extra
.
length
>
1
?
extra
[
extra
.
length
-
1
]
:
undefined
,
host
:
args
.
host
,
password
:
process
.
env
.
PASSWORD
,
folderUri
:
args
[
"
_
"
]
&&
args
[
"
_
"
].
length
>
1
?
args
[
"
_
"
][
args
[
"
_
"
].
length
-
1
]
:
undefined
,
};
if
(
!
options
.
host
)
{
options
.
host
=
!
options
.
auth
||
options
.
allowHttp
?
"
localhost
"
:
"
0.0.0.0
"
;
options
.
host
=
!
options
.
auth
||
options
.
allowHttp
?
"
localhost
"
:
"
0.0.0.0
"
;
}
let
usingGeneratedCert
=
false
;
...
...
@@ -152,18 +143,16 @@ const main = async (): Promise<void> => {
usingGeneratedPassword
=
true
;
}
const
webviewPort
=
typeof
args
[
"
webview-port
"
]
!==
"
undefined
"
&&
parseInt
(
args
[
"
webview-port
"
],
10
)
||
8444
;
const
webviewPort
=
args
[
"
webview-port
"
];
const
webviewServer
=
new
WebviewServer
({
...
options
,
port
:
webviewPort
,
port
:
typeof
webviewPort
!==
"
undefined
"
&&
parseInt
(
webviewPort
,
10
)
||
8444
,
socket
:
args
[
"
webview-socket
"
],
});
const
port
=
typeof
args
.
port
!==
"
undefined
"
&&
parseInt
(
args
.
port
,
10
)
||
8443
;
const
server
=
new
MainServer
({
...
options
,
port
,
port
:
typeof
args
.
port
!==
"
undefined
"
&&
parseInt
(
args
.
port
,
10
)
||
8443
,
socket
:
args
.
socket
,
},
webviewServer
,
args
);
...
...
@@ -196,7 +185,7 @@ const main = async (): Promise<void> => {
if
(
!
args
.
socket
&&
args
.
open
)
{
// The web socket doesn't seem to work if using 0.0.0.0.
const
openAddress
=
`http://localhost:
${
port
}
`
;
const
openAddress
=
`http://localhost:
${
server
.
options
.
port
}
`
;
await
open
(
openAddress
).
catch
(
console
.
error
);
console
.
log
(
` - Opened
${
openAddress
}
`
);
}
...
...
src/connection.ts
浏览文件 @
9fdfacb3
...
...
@@ -6,7 +6,7 @@ import { Emitter } from "vs/base/common/event";
import
{
ISocket
}
from
"
vs/base/parts/ipc/common/ipc.net
"
;
import
{
NodeSocket
}
from
"
vs/base/parts/ipc/node/ipc.net
"
;
import
{
ILogService
}
from
"
vs/platform/log/common/log
"
;
import
{
IExtHostReadyMessage
,
IExtHostSocketMessage
}
from
"
vs/workbench/services/extensions/common/extensionHostProtocol
"
;
import
{
IExtHostReadyMessage
}
from
"
vs/workbench/services/extensions/common/extensionHostProtocol
"
;
import
{
Protocol
}
from
"
vs/server/src/protocol
"
;
import
{
uriTransformerPath
}
from
"
vs/server/src/util
"
;
...
...
@@ -15,17 +15,11 @@ export abstract class Connection {
protected
readonly
_onClose
=
new
Emitter
<
void
>
();
public
readonly
onClose
=
this
.
_onClose
.
event
;
protected
disposed
:
boolean
=
false
;
public
constructor
(
protected
protocol
:
Protocol
)
{}
/**
* Set up the connection on a new socket.
*/
public
abstract
reconnect
(
socket
:
ISocket
,
buffer
:
VSBuffer
):
void
;
/**
* Clean up the connection.
*/
protected
abstract
dispose
():
void
;
}
...
...
@@ -62,16 +56,10 @@ export class ManagementConnection extends Connection {
}
}
/**
* Manage the extension host process.
*/
export
class
ExtensionHostConnection
extends
Connection
{
private
process
:
cp
.
ChildProcess
;
public
constructor
(
protocol
:
Protocol
,
buffer
:
VSBuffer
,
private
readonly
log
:
ILogService
,
)
{
public
constructor
(
protocol
:
Protocol
,
buffer
:
VSBuffer
,
private
readonly
log
:
ILogService
)
{
super
(
protocol
);
protocol
.
dispose
();
this
.
process
=
this
.
spawn
(
buffer
);
...
...
@@ -96,23 +84,17 @@ export class ExtensionHostConnection extends Connection {
private
sendInitMessage
(
buffer
:
VSBuffer
):
void
{
const
socket
=
this
.
protocol
.
getUnderlyingSocket
();
socket
.
pause
();
const
initMessage
:
IExtHostSocketMessage
=
{
this
.
process
.
send
({
type
:
"
VSCODE_EXTHOST_IPC_SOCKET
"
,
initialDataChunk
:
(
buffer
.
buffer
as
Buffer
).
toString
(
"
base64
"
),
skipWebSocketFrames
:
this
.
protocol
.
getSocket
()
instanceof
NodeSocket
,
};
this
.
process
.
send
(
initMessage
,
socket
);
},
socket
);
}
private
spawn
(
buffer
:
VSBuffer
):
cp
.
ChildProcess
{
const
proc
=
cp
.
fork
(
getPathFromAmdModule
(
require
,
"
bootstrap-fork
"
),
[
"
--type=extensionHost
"
,
`--uriTransformerPath=
${
uriTransformerPath
()}
`
],
[
"
--type=extensionHost
"
,
`--uriTransformerPath=
${
uriTransformerPath
()}
`
],
{
env
:
{
...
process
.
env
,
...
...
@@ -129,13 +111,8 @@ export class ExtensionHostConnection extends Connection {
proc
.
on
(
"
error
"
,
()
=>
this
.
dispose
());
proc
.
on
(
"
exit
"
,
()
=>
this
.
dispose
());
proc
.
stdout
.
setEncoding
(
"
utf8
"
);
proc
.
stderr
.
setEncoding
(
"
utf8
"
);
proc
.
stdout
.
on
(
"
data
"
,
(
d
)
=>
this
.
log
.
info
(
"
Extension host stdout
"
,
d
));
proc
.
stderr
.
on
(
"
data
"
,
(
d
)
=>
this
.
log
.
error
(
"
Extension host stderr
"
,
d
));
proc
.
stdout
.
setEncoding
(
"
utf8
"
).
on
(
"
data
"
,
(
d
)
=>
this
.
log
.
info
(
"
Extension host stdout
"
,
d
));
proc
.
stderr
.
setEncoding
(
"
utf8
"
).
on
(
"
data
"
,
(
d
)
=>
this
.
log
.
error
(
"
Extension host stderr
"
,
d
));
proc
.
on
(
"
message
"
,
(
event
)
=>
{
if
(
event
&&
event
.
type
===
"
__$console
"
)
{
const
severity
=
this
.
log
[
event
.
severity
]
?
event
.
severity
:
"
info
"
;
...
...
@@ -149,8 +126,7 @@ export class ExtensionHostConnection extends Connection {
this
.
sendInitMessage
(
buffer
);
}
};
proc
.
on
(
"
message
"
,
listen
);
return
proc
;
return
proc
.
on
(
"
message
"
,
listen
)
;
}
}
src/protocol.ts
浏览文件 @
9fdfacb3
...
...
@@ -73,10 +73,7 @@ export class Protocol extends PersistentProtocol {
* TODO: This ignores the authentication process entirely for now.
*/
private
authenticate
(
_message
:
AuthRequest
):
void
{
this
.
sendMessage
({
type
:
"
sign
"
,
data
:
""
,
});
this
.
sendMessage
({
type
:
"
sign
"
,
data
:
""
});
}
/**
...
...
src/server.ts
浏览文件 @
9fdfacb3
...
...
@@ -108,14 +108,11 @@ export interface ServerOptions {
}
export
abstract
class
Server
{
// The underlying web server.
protected
readonly
server
:
http
.
Server
|
https
.
Server
;
protected
rootPath
=
path
.
resolve
(
__dirname
,
"
../../../..
"
);
private
listenPromise
:
Promise
<
string
>
|
undefined
;
public
constructor
(
p
rotected
readonly
options
:
ServerOptions
)
{
public
constructor
(
p
ublic
readonly
options
:
ServerOptions
)
{
if
(
this
.
options
.
cert
&&
this
.
options
.
certKey
)
{
useHttpsTransformer
();
const
httpolyglot
=
require
.
__$__nodeRequire
(
path
.
resolve
(
__dirname
,
"
../node_modules/httpolyglot/lib/index
"
))
as
typeof
import
(
"
httpolyglot
"
);
...
...
@@ -167,8 +164,7 @@ export abstract class Server {
):
Promise
<
Response
>
;
protected
async
getResource
(
filePath
:
string
):
Promise
<
Response
>
{
const
content
=
await
util
.
promisify
(
fs
.
readFile
)(
filePath
);
return
{
content
,
filePath
};
return
{
content
:
await
util
.
promisify
(
fs
.
readFile
)(
filePath
),
filePath
};
}
private
onRequest
=
async
(
request
:
http
.
IncomingMessage
,
response
:
http
.
ServerResponse
):
Promise
<
void
>
=>
{
...
...
@@ -208,12 +204,10 @@ export abstract class Server {
}
else
if
(
base
===
""
)
{
// Happens if it's a plain `domain.com`.
base
=
"
/
"
;
}
if
(
requestPath
===
"
/
"
)
{
// Trailing slash, like `domain.com/login/`.
requestPath
=
""
;
}
else
if
(
requestPath
!==
""
)
{
// "" will become "." with normalize.
base
=
path
.
normalize
(
base
);
if
(
requestPath
!==
""
)
{
// "" will become "." with normalize.
requestPath
=
path
.
normalize
(
requestPath
);
}
base
=
path
.
normalize
(
base
);
switch
(
base
)
{
case
"
/
"
:
...
...
@@ -227,8 +221,7 @@ export abstract class Server {
case
"
/login
"
:
if
(
!
this
.
options
.
auth
)
{
throw
new
HttpError
(
"
Not found
"
,
HttpCode
.
NotFound
);
}
if
(
requestPath
===
""
)
{
}
else
if
(
requestPath
===
""
)
{
return
this
.
tryLogin
(
request
);
}
this
.
ensureGet
(
request
);
...
...
@@ -249,27 +242,19 @@ export abstract class Server {
this
.
ensureGet
(
request
);
return
{
redirect
:
"
https://
"
+
request
.
headers
.
host
+
"
/
"
};
}
if
(
request
.
method
===
"
POST
"
)
{
const
data
=
await
this
.
getData
<
LoginPayload
>
(
request
);
if
(
this
.
authenticate
(
request
,
data
))
{
return
{
redirect
:
"
https://
"
+
request
.
headers
.
host
+
"
/
"
,
headers
:
{
"
Set-Cookie
"
:
`password=
${
data
.
password
}
`
,
}
headers
:
{
"
Set-Cookie
"
:
`password=
${
data
.
password
}
`
}
};
}
let
userAgent
=
request
.
headers
[
"
user-agent
"
];
const
timestamp
=
Math
.
floor
(
new
Date
().
getTime
()
/
1000
);
if
(
Array
.
isArray
(
userAgent
))
{
userAgent
=
userAgent
.
join
(
"
,
"
);
}
console
.
error
(
"
Failed login attempt
"
,
JSON
.
stringify
({
xForwardedFor
:
request
.
headers
[
"
x-forwarded-for
"
],
remoteAddress
:
request
.
connection
.
remoteAddress
,
userAgent
,
timestamp
,
userAgent
:
request
.
headers
[
"
user-agent
"
]
,
timestamp
:
Math
.
floor
(
new
Date
().
getTime
()
/
1000
)
,
}));
return
this
.
getLogin
(
"
Invalid password
"
,
data
);
}
...
...
@@ -279,23 +264,16 @@ export abstract class Server {
private
async
getLogin
(
error
:
string
=
""
,
payload
?:
LoginPayload
):
Promise
<
Response
>
{
const
filePath
=
path
.
join
(
this
.
rootPath
,
"
out/vs/server/src/login/login.html
"
);
let
content
=
await
util
.
promisify
(
fs
.
readFile
)(
filePath
,
"
utf8
"
);
if
(
error
)
{
content
=
content
.
replace
(
"
{{ERROR}}
"
,
error
)
.
replace
(
"
display:none
"
,
"
display:block
"
);
}
if
(
payload
&&
payload
.
password
)
{
content
=
content
.
replace
(
'
value=""
'
,
`value="
${
payload
.
password
}
"`
);
}
const
content
=
(
await
util
.
promisify
(
fs
.
readFile
)(
filePath
,
"
utf8
"
))
.
replace
(
"
{{ERROR}}
"
,
error
)
.
replace
(
"
display:none
"
,
error
?
"
display:block
"
:
"
display:none
"
)
.
replace
(
'
value=""
'
,
`value="
${
payload
&&
payload
.
password
||
""
}
"`
);
return
{
content
,
filePath
};
}
private
ensureGet
(
request
:
http
.
IncomingMessage
):
void
{
if
(
request
.
method
!==
"
GET
"
)
{
throw
new
HttpError
(
`Unsupported method
${
request
.
method
}
`
,
HttpCode
.
BadRequest
,
);
throw
new
HttpError
(
`Unsupported method
${
request
.
method
}
`
,
HttpCode
.
BadRequest
);
}
}
...
...
@@ -357,15 +335,10 @@ export abstract class Server {
}
export
class
MainServer
extends
Server
{
// Used to notify the IPC server that there is a new client.
public
readonly
_onDidClientConnect
=
new
Emitter
<
ClientConnectionEvent
>
();
public
readonly
onDidClientConnect
=
this
.
_onDidClientConnect
.
event
;
// This is separate instead of just extending this class since we can't
// use properties in the super call. This manages channels.
private
readonly
ipc
=
new
IPCServer
(
this
.
onDidClientConnect
);
// Persistent connections. These can reconnect within a timeout.
private
readonly
connections
=
new
Map
<
ConnectionType
,
Map
<
string
,
Connection
>>
();
private
readonly
services
=
new
ServiceCollection
();
...
...
@@ -377,7 +350,6 @@ export class MainServer extends Server {
args
:
ParsedArgs
,
)
{
super
(
options
);
this
.
server
.
on
(
"
upgrade
"
,
async
(
request
,
socket
)
=>
{
const
protocol
=
this
.
createProtocol
(
request
,
socket
);
try
{
...
...
@@ -393,12 +365,10 @@ export class MainServer extends Server {
public
async
listen
():
Promise
<
string
>
{
const
environment
=
(
this
.
services
.
get
(
IEnvironmentService
)
as
EnvironmentService
);
const
mkdirs
=
Promise
.
all
([
environment
.
extensionsPath
,
].
map
((
p
)
=>
mkdirp
(
p
)));
const
[
address
]
=
await
Promise
.
all
([
super
.
listen
(),
mkdirs
,
const
[
address
]
=
await
Promise
.
all
<
string
>
([
super
.
listen
(),
...[
environment
.
extensionsPath
,
].
map
((
p
)
=>
mkdirp
(
p
).
then
(()
=>
p
)),
]);
return
address
;
}
...
...
@@ -426,22 +396,18 @@ export class MainServer extends Server {
private
async
getRoot
(
request
:
http
.
IncomingMessage
,
parsedUrl
:
url
.
UrlWithParsedQuery
):
Promise
<
Response
>
{
const
filePath
=
path
.
join
(
this
.
rootPath
,
"
out/vs/code/browser/workbench/workbench.html
"
);
let
content
=
await
util
.
promisify
(
fs
.
readFile
)(
filePath
,
"
utf8
"
);
const
remoteAuthority
=
request
.
headers
.
host
as
string
;
const
transformer
=
getUriTransformer
(
remoteAuthority
);
await
Promise
.
all
([
let
[
content
]
=
await
Promise
.
all
([
util
.
promisify
(
fs
.
readFile
)(
filePath
,
"
utf8
"
),
this
.
webviewServer
.
listen
(),
this
.
servicesPromise
,
]);
const
webviewEndpoint
=
this
.
webviewServer
.
address
(
request
);
const
cwd
=
process
.
env
.
VSCODE_CWD
||
process
.
cwd
();
const
workspacePath
=
parsedUrl
.
query
.
workspace
as
string
|
undefined
;
const
folderPath
=
!
workspacePath
?
parsedUrl
.
query
.
folder
as
string
|
undefined
||
this
.
options
.
folderUri
||
cwd
:
undefined
;
const
remoteAuthority
=
request
.
headers
.
host
as
string
;
const
transformer
=
getUriTransformer
(
remoteAuthority
);
const
options
:
Options
=
{
WORKBENCH_WEB_CONGIGURATION
:
{
workspaceUri
:
workspacePath
...
...
@@ -463,7 +429,6 @@ export class MainServer extends Server {
Object
.
keys
(
options
).
forEach
((
key
)
=>
{
content
=
content
.
replace
(
`"{{
${
key
}
}}"`
,
`'
${
JSON
.
stringify
(
options
[
key
])}
'`
);
});
content
=
content
.
replace
(
'
{{WEBVIEW_ENDPOINT}}
'
,
webviewEndpoint
);
return
{
content
,
filePath
};
...
...
@@ -473,83 +438,58 @@ export class MainServer extends Server {
if
(
request
.
headers
.
upgrade
!==
"
websocket
"
)
{
throw
new
Error
(
"
HTTP/1.1 400 Bad Request
"
);
}
const
options
=
{
reconnectionToken
:
""
,
reconnection
:
false
,
skipWebSocketFrames
:
false
,
};
if
(
request
.
url
)
{
const
query
=
url
.
parse
(
request
.
url
,
true
).
query
;
if
(
query
.
reconnectionToken
)
{
options
.
reconnectionToken
=
query
.
reconnectionToken
as
string
;
}
if
(
query
.
reconnection
===
"
true
"
)
{
options
.
reconnection
=
true
;
}
if
(
query
.
skipWebSocketFrames
===
"
true
"
)
{
options
.
skipWebSocketFrames
=
true
;
}
}
return
new
Protocol
(
request
.
headers
[
"
sec-websocket-key
"
]
as
string
,
socket
,
options
,
);
const
query
=
request
.
url
?
url
.
parse
(
request
.
url
,
true
).
query
:
{};
return
new
Protocol
(
<
string
>
request
.
headers
[
"
sec-websocket-key
"
],
socket
,
{
reconnectionToken
:
<
string
>
query
.
reconnectionToken
||
""
,
reconnection
:
query
.
reconnection
===
"
true
"
,
skipWebSocketFrames
:
query
.
skipWebSocketFrames
===
"
true
"
,
});
}
private
async
connect
(
message
:
ConnectionTypeRequest
,
protocol
:
Protocol
):
Promise
<
void
>
{
switch
(
message
.
desiredConnectionType
)
{
case
ConnectionType
.
ExtensionHost
:
case
ConnectionType
.
Management
:
const
debugPort
=
await
this
.
getDebugPort
();
const
ok
=
message
.
desiredConnectionType
===
ConnectionType
.
ExtensionHost
?
(
debugPort
?
{
debugPort
}
:
{})
:
{
type
:
"
ok
"
};
if
(
!
this
.
connections
.
has
(
message
.
desiredConnectionType
))
{
this
.
connections
.
set
(
message
.
desiredConnectionType
,
new
Map
());
}
const
connections
=
this
.
connections
.
get
(
message
.
desiredConnectionType
)
!
;
const
token
=
protocol
.
options
.
reconnectionToken
;
const
ok
=
async
()
=>
{
return
message
.
desiredConnectionType
===
ConnectionType
.
ExtensionHost
?
{
debugPort
:
await
this
.
getDebugPort
()
}
:
{
type
:
"
ok
"
};
};
const
token
=
protocol
.
options
.
reconnectionToken
;
if
(
protocol
.
options
.
reconnection
&&
connections
.
has
(
token
))
{
protocol
.
sendMessage
(
ok
);
protocol
.
sendMessage
(
await
ok
()
);
const
buffer
=
protocol
.
readEntireBuffer
();
protocol
.
dispose
();
return
connections
.
get
(
token
)
!
.
reconnect
(
protocol
.
getSocket
(),
buffer
);
}
if
(
protocol
.
options
.
reconnection
||
connections
.
has
(
token
))
{
}
else
if
(
protocol
.
options
.
reconnection
||
connections
.
has
(
token
))
{
throw
new
Error
(
protocol
.
options
.
reconnection
?
"
Unrecognized reconnection token
"
:
"
Duplicate reconnection token
"
);
}
protocol
.
sendMessage
(
ok
);
protocol
.
sendMessage
(
await
ok
()
);
let
connection
:
Connection
;
if
(
message
.
desiredConnectionType
===
ConnectionType
.
Management
)
{
connection
=
new
ManagementConnection
(
protocol
);
this
.
_onDidClientConnect
.
fire
({
protocol
,
onDidClientDisconnect
:
connection
.
onClose
,
protocol
,
onDidClientDisconnect
:
connection
.
onClose
,
});
}
else
{
const
buffer
=
protocol
.
readEntireBuffer
();
connection
=
new
ExtensionHostConnection
(
protocol
,
buffer
,
this
.
services
.
get
(
ILogService
)
as
ILogService
,
protocol
,
buffer
,
this
.
services
.
get
(
ILogService
)
as
ILogService
,
);
}
connections
.
set
(
protocol
.
options
.
reconnectionToken
,
connection
);
connection
.
onClose
(()
=>
{
connections
.
delete
(
protocol
.
options
.
reconnectionToken
);
});
connections
.
set
(
token
,
connection
);
connection
.
onClose
(()
=>
connections
.
delete
(
token
));
break
;
case
ConnectionType
.
Tunnel
:
return
protocol
.
tunnel
();
default
:
throw
new
Error
(
"
Unrecognized connection type
"
);
...
...
@@ -557,14 +497,11 @@ export class MainServer extends Server {
}
private
async
initializeServices
(
args
:
ParsedArgs
):
Promise
<
void
>
{
const
router
=
new
StaticRouter
((
ctx
:
any
)
=>
ctx
.
clientId
===
"
renderer
"
);
const
environmentService
=
new
EnvironmentService
(
args
,
process
.
execPath
);
const
logService
=
new
SpdLogService
(
RemoteExtensionLogFileName
,
environmentService
.
logsPath
,
getLogLevel
(
environmentService
));
this
.
ipc
.
registerChannel
(
"
loglevel
"
,
new
LogLevelSetterChannel
(
logService
));
const
router
=
new
StaticRouter
((
context
:
any
)
=>
{
return
context
.
clientId
===
"
renderer
"
;
});
this
.
services
.
set
(
ILogService
,
logService
);
this
.
services
.
set
(
IEnvironmentService
,
environmentService
);
this
.
services
.
set
(
IConfigurationService
,
new
SyncDescriptor
(
ConfigurationService
,
[
environmentService
.
machineSettingsResource
]));
...
...
@@ -594,11 +531,9 @@ export class MainServer extends Server {
this
.
services
.
set
(
IDialogService
,
new
DialogChannelClient
(
this
.
ipc
.
getChannel
(
"
dialog
"
,
router
)));
this
.
services
.
set
(
IExtensionManagementService
,
new
SyncDescriptor
(
ExtensionManagementService
));
const
instantiationService
=
new
InstantiationService
(
this
.
services
);
this
.
services
.
set
(
ILocalizationsService
,
instantiationService
.
createInstance
(
LocalizationsService
));
return
new
Promise
((
resolve
)
=>
{
await
new
Promise
((
resolve
)
=>
{
const
instantiationService
=
new
InstantiationService
(
this
.
services
);
this
.
services
.
set
(
ILocalizationsService
,
instantiationService
.
createInstance
(
LocalizationsService
));
instantiationService
.
invokeFunction
(()
=>
{
instantiationService
.
createInstance
(
LogsDataCleaner
);
this
.
ipc
.
registerChannel
(
REMOTE_FILE_SYSTEM_CHANNEL_NAME
,
new
FileProviderChannel
(
environmentService
,
logService
));
...
...
@@ -612,9 +547,7 @@ export class MainServer extends Server {
this
.
ipc
.
registerChannel
(
"
gallery
"
,
galleryChannel
);
const
telemetryChannel
=
new
TelemetryChannel
(
telemetryService
);
this
.
ipc
.
registerChannel
(
"
telemetry
"
,
telemetryChannel
);
// tslint:disable-next-line no-unused-expression
new
ErrorTelemetry
(
telemetryService
);
resolve
();
resolve
(
new
ErrorTelemetry
(
telemetryService
));
});
});
}
...
...
@@ -633,9 +566,6 @@ export class WebviewServer extends Server {
requestPath
:
string
,
):
Promise
<
Response
>
{
const
webviewPath
=
path
.
join
(
this
.
rootPath
,
"
out/vs/workbench/contrib/webview/browser/pre
"
);
if
(
requestPath
===
""
)
{
requestPath
=
"
/index.html
"
;
}
return
this
.
getResource
(
path
.
join
(
webviewPath
,
base
,
requestPath
));
return
this
.
getResource
(
path
.
join
(
webviewPath
,
base
,
requestPath
||
"
/index.html
"
));
}
}
src/tar.ts
浏览文件 @
9fdfacb3
import
*
as
fs
from
"
fs
"
;
import
*
as
path
from
"
path
"
;
import
*
as
tarStream
from
"
tar-stream
"
;
import
{
promisify
}
from
"
util
"
;
import
*
as
util
from
"
util
"
;
import
*
as
nls
from
"
vs/nls
"
;
import
*
as
vszip
from
"
vs/base/node/zip
"
;
...
...
@@ -14,7 +14,6 @@ const vszipBuffer = vszip.buffer;
export
interface
IExtractOptions
{
overwrite
?:
boolean
;
/**
* Source path within the TAR/ZIP archive. Only the files
* contained in this path will be extracted.
...
...
@@ -28,197 +27,134 @@ export interface IFile {
localPath
?:
string
;
}
/**
* Override the standard VS Code behavior for zipping extensions to use the TAR
* format instead of ZIP.
*/
export
const
zip
=
(
tarPath
:
string
,
files
:
IFile
[]):
Promise
<
string
>
=>
{
return
new
Promise
<
string
>
((
c
,
e
):
void
=>
{
const
pack
=
tarStream
.
pack
();
const
chunks
:
Buffer
[]
=
[];
const
ended
=
new
Promise
<
Buffer
>
((
res
):
void
=>
{
pack
.
on
(
"
end
"
,
()
=>
{
res
(
Buffer
.
concat
(
chunks
));
});
});
pack
.
on
(
"
data
"
,
(
chunk
)
=>
{
chunks
.
push
(
chunk
as
Buffer
);
});
for
(
let
i
=
0
;
i
<
files
.
length
;
i
++
)
{
const
file
=
files
[
i
];
pack
.
entry
({
name
:
file
.
path
,
},
file
.
contents
);
}
pack
.
finalize
();
ended
.
then
((
buffer
)
=>
{
return
promisify
(
fs
.
writeFile
)(
tarPath
,
buffer
);
}).
then
(()
=>
{
c
(
tarPath
);
}).
catch
((
ex
)
=>
{
e
(
ex
);
});
export
const
tar
=
async
(
tarPath
:
string
,
files
:
IFile
[]):
Promise
<
string
>
=>
{
const
pack
=
tarStream
.
pack
();
const
chunks
:
Buffer
[]
=
[];
const
ended
=
new
Promise
<
Buffer
>
((
resolve
)
=>
{
pack
.
on
(
"
end
"
,
()
=>
resolve
(
Buffer
.
concat
(
chunks
)));
});
pack
.
on
(
"
data
"
,
(
chunk
:
Buffer
)
=>
chunks
.
push
(
chunk
));
for
(
let
i
=
0
;
i
<
files
.
length
;
i
++
)
{
const
file
=
files
[
i
];
pack
.
entry
({
name
:
file
.
path
},
file
.
contents
);
}
pack
.
finalize
();
await
util
.
promisify
(
fs
.
writeFile
)(
tarPath
,
await
ended
);
return
tarPath
;
};
/**
* Override the standard VS Code behavior for extracting archives to first
* attempt to process the archive as a TAR and then fall back to the original
* implementation for processing ZIPs.
*/
export
const
extract
=
(
archivePath
:
string
,
extractPath
:
string
,
options
:
IExtractOptions
=
{},
token
:
CancellationToken
):
Promise
<
void
>
=>
{
return
new
Promise
<
void
>
((
c
,
e
):
void
=>
{
extractTar
(
archivePath
,
extractPath
,
options
,
token
).
then
(
c
).
catch
((
ex
)
=>
{
if
(
!
ex
.
toString
().
includes
(
"
Invalid tar header
"
))
{
e
(
ex
);
return
;
}
vszipExtract
(
archivePath
,
extractPath
,
options
,
token
).
then
(
c
).
catch
(
e
);
});
});
export
const
extract
=
async
(
archivePath
:
string
,
extractPath
:
string
,
options
:
IExtractOptions
=
{},
token
:
CancellationToken
):
Promise
<
void
>
=>
{
try
{
await
extractTar
(
archivePath
,
extractPath
,
options
,
token
);
}
catch
(
error
)
{
if
(
error
.
toString
().
includes
(
"
Invalid tar header
"
))
{
await
vszipExtract
(
archivePath
,
extractPath
,
options
,
token
);
}
}
};
/**
* Override the standard VS Code behavior for buffering archives to first
* process the Buffer as a TAR and then fall back to the original
* implementation for processing ZIPs.
*/
export
const
buffer
=
(
targetPath
:
string
,
filePath
:
string
):
Promise
<
Buffer
>
=>
{
return
new
Promise
<
Buffer
>
((
c
,
e
):
void
=>
{
let
done
:
boolean
=
false
;
extractAssets
(
targetPath
,
new
RegExp
(
filePath
),
(
assetPath
:
string
,
data
:
Buffer
)
=>
{
if
(
path
.
normalize
(
assetPath
)
===
path
.
normalize
(
filePath
))
{
done
=
true
;
c
(
data
);
}
}).
then
(()
=>
{
return
new
Promise
<
Buffer
>
(
async
(
resolve
,
reject
)
=>
{
try
{
let
done
:
boolean
=
false
;
await
extractAssets
(
targetPath
,
new
RegExp
(
filePath
),
(
assetPath
:
string
,
data
:
Buffer
)
=>
{
if
(
path
.
normalize
(
assetPath
)
===
path
.
normalize
(
filePath
))
{
done
=
true
;
resolve
(
data
);
}
});
if
(
!
done
)
{
e
(
"
couldn't find asset
"
+
filePath
);
throw
new
Error
(
"
couldn't find asset
"
+
filePath
);
}
}
).
catch
((
ex
)
=>
{
if
(
!
ex
.
toString
().
includes
(
"
Invalid tar header
"
))
{
e
(
ex
);
re
turn
;
}
catch
(
error
)
{
if
(
error
.
toString
().
includes
(
"
Invalid tar header
"
))
{
vszipBuffer
(
targetPath
,
filePath
).
then
(
resolve
).
catch
(
reject
);
}
else
{
re
ject
(
error
)
;
}
vszipBuffer
(
targetPath
,
filePath
).
then
(
c
).
catch
(
e
);
});
}
});
};
/**
* Override the standard VS Code behavior for extracting assets from archive
* Buffers to use the TAR format instead of ZIP.
*/
const
extractAssets
=
(
tarPath
:
string
,
match
:
RegExp
,
callback
:
(
path
:
string
,
data
:
Buffer
)
=>
void
):
Promise
<
void
>
=>
{
return
new
Promise
<
void
>
(
async
(
c
,
e
):
Promise
<
void
>
=>
{
try
{
const
buffer
=
await
promisify
(
fs
.
readFile
)(
tarPath
);
const
extractor
=
tarStream
.
extract
();
extractor
.
once
(
"
error
"
,
e
);
extractor
.
on
(
"
entry
"
,
(
header
,
stream
,
next
)
=>
{
const
name
=
header
.
name
;
if
(
match
.
test
(
name
))
{
extractData
(
stream
).
then
((
data
)
=>
{
callback
(
name
,
data
);
next
();
}).
catch
(
e
);
stream
.
resume
();
}
else
{
stream
.
on
(
"
end
"
,
()
=>
{
next
();
});
stream
.
resume
();
}
});
extractor
.
on
(
"
finish
"
,
()
=>
{
c
();
});
extractor
.
write
(
buffer
);
extractor
.
end
();
}
catch
(
ex
)
{
e
(
ex
);
}
const
extractAssets
=
async
(
tarPath
:
string
,
match
:
RegExp
,
callback
:
(
path
:
string
,
data
:
Buffer
)
=>
void
):
Promise
<
void
>
=>
{
const
buffer
=
await
util
.
promisify
(
fs
.
readFile
)(
tarPath
);
return
new
Promise
<
void
>
(
async
(
resolve
,
reject
):
Promise
<
void
>
=>
{
const
extractor
=
tarStream
.
extract
();
extractor
.
once
(
"
error
"
,
reject
);
extractor
.
on
(
"
entry
"
,
async
(
header
,
stream
,
next
)
=>
{
const
name
=
header
.
name
;
if
(
match
.
test
(
name
))
{
extractData
(
stream
).
then
((
data
)
=>
{
callback
(
name
,
data
);
next
();
}).
catch
(
reject
);
stream
.
resume
();
}
else
{
stream
.
on
(
"
end
"
,
()
=>
next
());
stream
.
resume
();
}
});
extractor
.
on
(
"
finish
"
,
resolve
);
extractor
.
write
(
buffer
);
extractor
.
end
();
});
};
const
extractData
=
(
stream
:
NodeJS
.
ReadableStream
):
Promise
<
Buffer
>
=>
{
return
new
Promise
<
Buffer
>
((
c
,
e
):
void
=>
{
return
new
Promise
((
resolve
,
reject
):
void
=>
{
const
fileData
:
Buffer
[]
=
[];
stream
.
on
(
"
data
"
,
(
data
)
=>
fileData
.
push
(
data
));
stream
.
on
(
"
end
"
,
()
=>
{
const
fd
=
Buffer
.
concat
(
fileData
);
c
(
fd
);
});
stream
.
on
(
"
error
"
,
e
);
stream
.
on
(
"
end
"
,
()
=>
resolve
(
Buffer
.
concat
(
fileData
)));
stream
.
on
(
"
error
"
,
reject
);
});
};
const
extractTar
=
(
tarPath
:
string
,
targetPath
:
string
,
options
:
IExtractOptions
=
{},
token
:
CancellationToken
):
Promise
<
void
>
=>
{
return
new
Promise
<
void
>
(
async
(
c
,
e
):
Promise
<
void
>
=>
{
try
{
const
sourcePathRegex
=
new
RegExp
(
options
.
sourcePath
?
`^
${
options
.
sourcePath
}
`
:
""
);
const
buffer
=
await
promisify
(
fs
.
readFile
)(
tarPath
);
const
extractor
=
tarStream
.
extract
();
extractor
.
once
(
"
error
"
,
e
);
extractor
.
on
(
"
entry
"
,
(
header
,
stream
,
next
)
=>
{
const
rawName
=
path
.
normalize
(
header
.
name
);
const
nextEntry
=
():
void
=>
{
stream
.
resume
();
next
();
};
if
(
token
.
isCancellationRequested
)
{
return
nextEntry
();
}
if
(
!
sourcePathRegex
.
test
(
rawName
))
{
return
nextEntry
();
}
const
fileName
=
rawName
.
replace
(
sourcePathRegex
,
""
);
const
targetFileName
=
path
.
join
(
targetPath
,
fileName
);
if
(
/
\/
$/
.
test
(
fileName
))
{
stream
.
resume
();
mkdirp
(
targetFileName
).
then
(()
=>
{
next
();
},
e
);
return
;
}
const
extractTar
=
async
(
tarPath
:
string
,
targetPath
:
string
,
options
:
IExtractOptions
=
{},
token
:
CancellationToken
):
Promise
<
void
>
=>
{
const
buffer
=
await
util
.
promisify
(
fs
.
readFile
)(
tarPath
);
return
new
Promise
<
void
>
(
async
(
resolve
,
reject
):
Promise
<
void
>
=>
{
const
sourcePathRegex
=
new
RegExp
(
options
.
sourcePath
?
`^
${
options
.
sourcePath
}
`
:
""
);
const
extractor
=
tarStream
.
extract
();
extractor
.
once
(
"
error
"
,
reject
);
extractor
.
on
(
"
entry
"
,
async
(
header
,
stream
,
next
)
=>
{
const
rawName
=
path
.
normalize
(
header
.
name
);
const
nextEntry
=
():
void
=>
{
stream
.
resume
();
next
();
};
if
(
token
.
isCancellationRequested
||
!
sourcePathRegex
.
test
(
rawName
))
{
return
nextEntry
();
}
const
dirName
=
path
.
dirname
(
fileName
);
const
targetDirName
=
path
.
join
(
targetPath
,
dirName
);
if
(
targetDirName
.
indexOf
(
targetPath
)
!==
0
)
{
e
(
nls
.
localize
(
"
invalid file
"
,
"
Error extracting {0}. Invalid file.
"
,
fileName
));
const
fileName
=
rawName
.
replace
(
sourcePathRegex
,
""
);
const
targetFileName
=
path
.
join
(
targetPath
,
fileName
);
if
(
/
\/
$/
.
test
(
fileName
))
{
return
mkdirp
(
targetFileName
).
then
(
nextEntry
);
}
return
nextEntry
();
}
const
dirName
=
path
.
dirname
(
fileName
);
const
targetDirName
=
path
.
join
(
targetPath
,
dirName
);
if
(
targetDirName
.
indexOf
(
targetPath
)
!==
0
)
{
return
reject
(
nls
.
localize
(
"
invalid file
"
,
"
Error extracting {0}. Invalid file.
"
,
fileName
));
}
return
mkdirp
(
targetDirName
,
undefined
,
token
).
then
(()
=>
{
const
fstream
=
fs
.
createWriteStream
(
targetFileName
,
{
mode
:
header
.
mode
});
fstream
.
once
(
"
close
"
,
()
=>
{
next
();
});
fstream
.
once
(
"
error
"
,
e
);
stream
.
pipe
(
fstream
);
stream
.
resume
();
});
return
mkdirp
(
targetDirName
,
undefined
,
token
).
then
(()
=>
{
const
fstream
=
fs
.
createWriteStream
(
targetFileName
,
{
mode
:
header
.
mode
});
fstream
.
once
(
"
close
"
,
()
=>
next
());
fstream
.
once
(
"
error
"
,
reject
);
stream
.
pipe
(
fstream
);
stream
.
resume
();
});
extractor
.
once
(
"
finish
"
,
c
);
extractor
.
write
(
buffer
);
extractor
.
end
();
}
catch
(
ex
)
{
e
(
ex
);
}
});
extractor
.
once
(
"
finish
"
,
resolve
);
extractor
.
write
(
buffer
);
extractor
.
end
();
});
};
// Override original functionality so we can use tar instead of zip.
const
target
=
vszip
as
typeof
vszip
;
target
.
zip
=
zip
;
target
.
zip
=
tar
;
target
.
extract
=
extract
;
target
.
buffer
=
buffer
;
src/uriTransformerHttp.js
浏览文件 @
9fdfacb3
...
...
@@ -4,8 +4,7 @@ module.exports = (remoteAuthority, https) => {
return
{
transformIncoming
:
(
uri
)
=>
{
switch
(
uri
.
scheme
)
{
case
"
https
"
:
return
{
scheme
:
"
file
"
,
path
:
uri
.
path
};
case
"
http
"
:
return
{
scheme
:
"
file
"
,
path
:
uri
.
path
};
case
"
https
"
:
case
"
http
"
:
return
{
scheme
:
"
file
"
,
path
:
uri
.
path
};
case
"
file
"
:
return
{
scheme
:
"
vscode-local
"
,
path
:
uri
.
path
};
default
:
return
uri
;
}
...
...
src/uriTransformerHttps.js
浏览文件 @
9fdfacb3
module
.
exports
=
(
remoteAuthority
)
=>
{
return
require
(
"
./uriTransformerHttp
"
)(
remoteAuthority
,
true
);
};
module
.
exports
=
(
remoteAuthority
)
=>
require
(
"
./uriTransformerHttp
"
)(
remoteAuthority
,
true
);
src/util.ts
浏览文件 @
9fdfacb3
...
...
@@ -25,8 +25,6 @@ export const generateCertificate = async (): Promise<{ cert: string, certKey: st
util
.
promisify
(
fs
.
exists
)(
paths
.
certKey
),
]);
await
mkdirp
(
tmpdir
);
if
(
!
exists
[
0
]
||
!
exists
[
1
])
{
const
pem
=
require
.
__$__nodeRequire
(
path
.
resolve
(
__dirname
,
"
../node_modules/pem/lib/pem
"
))
as
typeof
import
(
"
pem
"
);
const
certs
=
await
new
Promise
<
import
(
"
pem
"
).
CertificateCreationResult
>
((
resolve
,
reject
):
void
=>
{
...
...
@@ -37,6 +35,7 @@ export const generateCertificate = async (): Promise<{ cert: string, certKey: st
resolve
(
result
);
});
});
await
mkdirp
(
tmpdir
);
await
Promise
.
all
([
util
.
promisify
(
fs
.
writeFile
)(
paths
.
cert
,
certs
.
certificate
),
util
.
promisify
(
fs
.
writeFile
)(
paths
.
certKey
,
certs
.
serviceKey
),
...
...
@@ -46,16 +45,10 @@ export const generateCertificate = async (): Promise<{ cert: string, certKey: st
return
paths
;
};
let
secure
:
boolean
;
export
const
useHttpsTransformer
=
():
void
=>
{
secure
=
true
;
};
let
transformer
:
string
=
"
uriTransformerHttp
"
;
export
const
useHttpsTransformer
=
():
string
=>
transformer
=
"
uriTransformerHttps
"
;
export
const
uriTransformerPath
=
():
string
=>
{
return
getPathFromAmdModule
(
require
,
"
vs/server/src/uriTransformerHttp
"
+
(
secure
?
"
s
"
:
""
),
);
return
getPathFromAmdModule
(
require
,
`vs/server/src/
${
transformer
}
`
);
};
export
const
getUriTransformer
=
(
remoteAuthority
:
string
):
URITransformer
=>
{
...
...
@@ -87,25 +80,16 @@ export const isWsl = async (): Promise<boolean> => {
};
export
const
open
=
async
(
url
:
string
):
Promise
<
void
>
=>
{
let
command
:
string
;
const
args
=
<
string
[]
>
[];
const
options
=
<
cp
.
SpawnOptions
>
{};
const
platform
=
await
isWsl
()
?
"
wsl
"
:
process
.
platform
;
switch
(
platform
)
{
case
"
darwin
"
:
command
=
"
open
"
;
break
;
case
"
win32
"
:
case
"
wsl
"
:
command
=
platform
===
"
wsl
"
?
"
cmd.exe
"
:
"
cmd
"
;
args
.
push
(
"
/c
"
,
"
start
"
,
'
""
'
,
"
/b
"
);
url
=
url
.
replace
(
/&/g
,
"
^&
"
);
default
:
command
=
"
xdg-open
"
;
break
;
let
command
=
platform
===
"
darwin
"
?
"
open
"
:
"
xdg-open
"
;
if
(
platform
===
"
win32
"
||
platform
===
"
wsl
"
)
{
command
=
platform
===
"
wsl
"
?
"
cmd.exe
"
:
"
cmd
"
;
args
.
push
(
"
/c
"
,
"
start
"
,
'
""
'
,
"
/b
"
);
url
=
url
.
replace
(
/&/g
,
"
^&
"
);
}
args
.
push
(
url
);
const
proc
=
cp
.
spawn
(
command
,
args
,
options
);
const
proc
=
cp
.
spawn
(
command
,
[...
args
,
url
],
options
);
await
new
Promise
((
resolve
,
reject
)
=>
{
proc
.
on
(
"
error
"
,
reject
);
proc
.
on
(
"
close
"
,
(
code
)
=>
{
...
...
@@ -125,8 +109,6 @@ export const unpackExecutables = async (): Promise<void> => {
const
destination
=
path
.
join
(
tmpdir
,
path
.
basename
(
rgPath
||
""
));
if
(
rgPath
&&
!
(
await
util
.
promisify
(
fs
.
exists
)(
destination
)))
{
await
mkdirp
(
tmpdir
);
// TODO: I'm not sure why but copyFile doesn't work in the Docker build.
// await util.promisify(fs.copyFile)(rgPath, destination);
await
util
.
promisify
(
fs
.
writeFile
)(
destination
,
await
util
.
promisify
(
fs
.
readFile
)(
rgPath
));
await
util
.
promisify
(
fs
.
chmod
)(
destination
,
"
755
"
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录