Xterm.js: Suportar escapes de hiperlink ansi

Criado em 28 nov. 2017  ·  29Comentários  ·  Fonte: xtermjs/xterm.js

Emuladores de terminal estão começando a oferecer suporte a hiperlinks . Embora muitos terminais tenham detectado URLs e vinculado-os, permitindo que você clique com o botão direito do mouse ou clique com o botão direito do mouse neles para abrir um navegador, você foi forçado a imprimir os URLs longos e desagradáveis ​​na tela. Na primavera de 2017, alguns terminais começaram a oferecer suporte a links do tipo HTML, onde o texto do link e o destino podiam ser especificados separadamente.

Exemplo de iTerm2 3.1:
screen shot 2017-11-28 at 12 08 20

areapi arelinks help wanted typenhancement

Comentários muito úteis

O iTerm2 mostra o URL assim:

screen shot 2017-11-28 at 14 50 20

Isso também é semelhante a como o Chrome mostra o URL quando você passa o mouse sobre os links.

Todos 29 comentários

Boa ideia, RP bem-vindo!

Pode se tornar um padrão e tornar a análise mais fácil.
Problema relacionado: https://github.com/xtermjs/xterm.js/issues/583

O maior benefício é que podemos vincular o texto sem ter que enviar spam para o terminal com um URL longo. Por exemplo, pode-se criar um link para a documentação em mensagens de erro sem torná-lo muito detalhado.

Isso deve ser implementado com cuidado, você precisa ser capaz de passar o mouse sobre o link para ver aonde ele leva, caso contrário, você pode vincular usuários sem saber a sites maliciosos. Isso já é um grande problema no phishing de e-mail.

Por exemplo, você poderia fazer um link que tivesse o título "login.facebook.com", mas na verdade vinculá-lo a login.faceboook.com, tendo uma página que parece exatamente a mesma, mas salvando a senha do usuário no login.

O iTerm2 mostra o URL assim:

screen shot 2017-11-28 at 14 50 20

Isso também é semelhante a como o Chrome mostra o URL quando você passa o mouse sobre os links.

Se / quando isso for implementado, envie um problema ou RP para supports-hyperlinks , que tem como objetivo detectar o suporte para esse recurso.

@jamestalmage isso provavelmente precisará ser deixado para os embedders xterm.js, no momento o ambiente é propriedade dos emuladores de terminal que usam xterm.js. Por exemplo, Hyper e VS Code, cada um definido individualmente TERM_PROGRAM .

@Tyriar - Nesse caso, talvez apenas inclua uma referência a supports-hyperlinks no commit que o direciona, e nas notas de lançamento quando for alargado. Não tenho certeza se existem supports-hyperlinks equivalentes para outras línguas, mas se houver, provavelmente vale a pena mencioná-los também.

Tenho uma implementação de prova de conceito:

links.txt

Existe um problema fundamental em que esses links não são armazenados no buffer de nenhuma maneira real, então eles desaparecem se a janela for redimensionada. Em vez disso, as informações do link são armazenadas em MouseZoneManager que é apagado por _mouseZoneManager.clearAll .

Acredito que uma solução real tem que esperar até que a reimplementação do Buffer seja concluída. Precisamos de um mecanismo para anotar células e / ou intervalos de células, que seja estável no redimensionamento.

(Ou talvez eu esteja apenas perdendo alguma coisa, por ser novo nesta base de código.)

Acredito que uma solução real tem que esperar até que a reimplementação do Buffer seja concluída. Precisamos de um mecanismo para anotar células e / ou intervalos de células, que seja estável no redimensionamento.

@PerBothner sim, você provavelmente está certo. Outra coisa que precisamos pensar antes que isso seja distribuível é como a URL subjacente é exposta a partir de xterm.js para que os incorporadores possam exibi-la na IU. Provavelmente também desejaríamos desativá-lo por padrão por motivos de segurança (já que o URL não seria exibido por padrão).

Eu atualizei meu patch e coloquei em um branch: https://github.com/PerBothner/xterm.js/tree/hyperlinks

Porém, não está pronto para uma solicitação pull - vários problemas mencionados anteriormente não foram resolvidos.

Proposta para a API usar isto:

export class Terminal {
    /**
     * Adds a handler for the ANSI hyperlink escape `\x1b]8;;url\alabel\x1b]8;;`, you should use
     * this API to display the full URL to the user. Note that ANSI hyperlinks will only work if
     * there is a handler for security reasons.
     * <strong i="6">@param</strong> onHover The callback that fires when the mouse enters a link's zone.
     * <strong i="7">@param</strong> onLeave The callback that fires when the mouse leaves a link's zone.
     * <strong i="8">@return</strong> An IDisposable which can be used to disable the handler.
     */
    addAnsiHyperlinkHandler(onHover: (event: MouseEvent, url: string) => void, onLeave: () => void): IDisposable;
}

Comentários de @mofux @jerch sobre o formato da API? Não consigo encontrar esse tópico falando sobre a forma deles, mas talvez devesse ser set vez de add , pois só faz sentido ter 1.

Também pode ser melhor usar algo como ILinkHoverEvent :

interface ILinkHoverEvent {
  // Maybe the cell the mouse is under is also needed?
  x1: number;
  y1: number;
  x2: number;
  y2: number;
  url: string;
}

export class Terminal {
    addAnsiHyperlinkHandler(onHover: (event: ILinkHoverEvent) => void, onLeave: () => void): IDisposable;
}

Outra alternativa:

interface ILinkHoverEvent {
  linkStart: Cell;
  linkEnd: Cell;
  mousePosition: Cell;
  url: string
}

@Tyriar IMO não faz muito sentido criar um manipulador separado para isso. O consumidor provável dessa API seria nosso renderizador que renderiza a url em uma dica de ferramenta se passarmos o mouse sobre o texto vinculado, não é? Talvez faça sentido estender nosso linkificador com os ganchos mencionados acima para onLinkHover e onLinkLeave , e ter esses hiperlinks ansi tratados como fazemos com links da web agora?

O provável consumidor desta API seria nosso renderizador que renderiza o url em uma dica de ferramenta

@mofux Eu estava pensando mais como o addon de pesquisa, o embedder fornece a interface do usuário no estilo que eles quiserem, nós apenas fornecemos os callbacks para fazer isso. É bom notar que isso não permite que você cuide das coisas ainda. Acho que mesclando com a API de link existente e tendo uma configuração ITerminalOptions.enableAnsiHyperlinks para opt-in e detalhes do por quê?

Acho que mesclando com a API de link existente e tendo uma configuração ITerminalOptions.enableAnsiHyperlinks para opt-in e detalhes do por quê?

Como seria a história para os incorporadores oferecerem suporte a esse recurso? Abrir o link (invisível) ao clicar no texto vinculado é potencialmente perigoso - especialmente se não mostrarmos o URL vinculado em nenhum lugar 🤔

Embora mostrar o destino antecipadamente seja realmente bom, não acho que haja um problema em abrir URLs "desconhecidos". Os aspectos de segurança foram discutidos nos comentários sob as especificações. Os navegadores abrem URLs "desconhecidos" o tempo todo, por exemplo, quando há um código JS que altera o alvo pouco antes de abri-lo, geralmente para mostrar um URL "legal" ao usuário, mas na verdade o abre por meio de um redirecionador.

Falando nisso ... algo que não me ocorreu até agora ...

Se xterm.js estiver sendo executado dentro de um navegador real e abrir o link, digamos uma nova guia desse navegador: Acho que vazar a URL de xterm.js por meio do campo Referer é algo com que se preocupar. Não tenho certeza sobre o suporte atual para rel = "noreferrer", mas parece algo que deve ser usado.

Veja esta discussão relacionada de texto flutuante . Esse problema é sobre como anotar seções da saída com "topos de ferramentas" e outros pop-ups de passar o mouse, o que não é a mesma coisa que exibir a URL quando você passa o mouse sobre um link. No entanto, ambos podem querer usar o mesmo mecanismo para exibir o texto instantâneo real. Ambos provavelmente fariam uso de MouseZoneManager .

Temos algum especialista em XSS por perto? Talvez precisemos de uma auditoria, lol.

Para meu conhecimento limitado sobre segurança de navegador, o principal vetor de ataque com xterm.js são os dados que cruzam a fronteira do terminal / navegador:

  • XSS do navegador (JS) para o terminal (dados)
    Isso já é possível e é de responsabilidade do integrador (xterm.js não pode controlar isso de forma alguma). Regra prática - nunca importe scripts de qualquer fonte não confiável na página do terminal ou no websocket pty e, portanto, o sistema que hospeda o pty será perdido. Não permita que conteúdo de usuário não filtrado seja inserido na página e tal - basicamente todas as coisas XSS típicas, ou o pty será perdido.
  • XSS do terminal (dados) para o navegador (JS)
    Essa é uma nova qualidade que podemos inserir com URLs, se não tivermos certeza de que os dados do terminal nunca chegarão ao contexto JS da página de incorporação (portanto, o próprio objeto do terminal). Se isso for possível (vamos supor que por um segundo), um invasor pode obter acesso à página do navegador e, assim, fazer um ataque terminal (dados) - navegador (JS) - terminal (dados). Vamos supor ainda que xterm.js execute muito em portais de serviço de orquestração de nuvem e o administrador use sessões de terminal para máquinas diferentes. Outch. Depois que o invasor obtém acesso à página do navegador de incorporação, todos os serviços em nuvem aos quais o administrador tem acesso estão em perigo.

A questão é - há possibilidades de cruzar a fronteira do terminal (dados) - navegador (JS) com URLs? Novamente, meu conhecimento limitado sobre segurança de navegador não ajuda muito aqui. O único cenário que consigo pensar são os bookmarklets que se injetam no JS da página. Não tenho ideia se podemos evitar isso sempre abrindo coisas em uma nova janela / guia apenas (acho que a sessão ainda vazará, se não apenas http? E quanto à conexão de websocket?) O que me faz pensar que temos que analisar o URL e tire qualquer "conteúdo com aparência de JS", meu Deus ...

Edit: Observe que os websockets perdem a maioria das configurações de segurança do navegador, eles nem mesmo têm uma verificação de origem confiável (vá com a pesquisa longa ajax se você precisar disso lol). Hmm...

os bookmarklets eliminam [...] qualquer "conteúdo que parece JS"

Acho que é uma boa ideia colocar na lista de permissões apenas URLs começando com "http: //", "https: //", talvez "ftp: //" e rejeitar qualquer outra coisa. Ou, pelo menos, coloque na lista negra a falta de esquema, bem como "javascript:".

Em meu branch de hiperlinks, adicionei um patch https://github.com/PerBothner/xterm.js/commit/b2647b90d301c52229d01720800865a0d39f436f para uma função de retorno de chamada configurável em um clique. Isso permite alterar a forma como o link é tratado. Por exemplo, quando DomTerm está configurado para usar meu branch xterm.js após ls --hyperlink=auto clinking na maioria dos nomes de arquivo irá abrir o arquivo no emacs, mas os arquivos html irão abrir o arquivo em seu navegador padrão, dependendo de suas configurações .

(Esteja avisado que há algumas falhas no protótipo. Não sei se isso é específico do protótipo DomTerm.)

Os navegadores abrem URLs "desconhecidos" o tempo todo, por exemplo, quando há um código JS que altera o alvo pouco antes de abri-lo, geralmente para mostrar um URL "legal" ao usuário, mas na verdade o abre por meio de um redirecionador.

@egmontkob em navegadores, você geralmente começa de algum lugar seguro, como um mecanismo de pesquisa que informa claramente quando o domínio está. Para terminais, você precisaria confiar em programas (alguns dos quais podem imprimir conteúdo remoto), até mesmo cat'ing um arquivo pode mostrar um link malicioso. Parece que é melhor estar seguro por padrão e ter uma configuração que apenas descreva os riscos e ofereça atenuações.

Em meu branch de hiperlinks, adicionei um patch PerBothner @ b2647b9 para uma função de retorno de chamada configurável com um clique.

@PerBothner já existe um manipulador aqui no complemento webLinks: https://github.com/xtermjs/xterm.js/blob/509ce5fa3a698ee7847419117e9dd6b979b105bf/src/addons/webLinks/webLinks.ts#Lgly , parece precisar de um bit para uLgly configurar 2 manipuladores de link da web diferentes.

(Desculpe pela resposta tardia - eu fui desviado.)

@Tyriar escreveu "já existe um manipulador aqui no complemento webLinks". O problema é que webLinksInit cria um ILinkMatcher e associa o manipulador fornecido a um ILinkMatcher específico, que contém um conjunto de regexes para corresponder. Mas como especificamos o manipulador de links para hiperlinks criados por uma sequência de escape e, portanto, não são o resultado de uma correspondência de regex? Esse manipulador precisa ser "global", no sentido de não estar associado a nenhum ILinkMatcher ou regex. Definir esse manipulador global / padrão usando webLinksInit ou Terminal.registerLinkMatcher não funciona.

Parece-me que precisamos de um campo linkHandler no Terminal - ter um campo handler em ILinkMatcher não é suficiente. E se tivermos um campo linkHandler em Terminal , faz sentido que esse manipulador seja o padrão usado por registerLinkMatcher. Isso é o que meu patch faz.

Se alguém quiser ajudar nisso, aqui está o que precisa acontecer:

  • Descubra como lidar com as implicações de segurança de ter links que não aparecem como URLs, isso provavelmente é para tornar o recurso ativado e expor um gancho para que os consumidores possam mostrar um pop-up
  • Descubra uma boa API para abrir um link, já temos algo muito semelhante com a API de correspondência de link, isso pode ser generalizado?
  • Adicione a lógica ao analisador e armazene os links em algum lugar, talvez como IMarker s?

Meu branch de hiperlinks https://github.com/PerBothner/xterm.js/tree/hyperlinks pode ser um ponto de partida. (Embora seja um pouco velho, pode não funcionar mais.)

Qual é o status do branch acima? Alguém está trabalhando nisso?
@Tyriar listou bem as etapas necessárias. Alguma dessas etapas foi realizada?

@ Jma353 Não creio que alguém esteja trabalhando ativamente nisso, então sinta-se à vontade para implementar as partes necessárias.

@Tyriar Não li a especificação em todos os detalhes, mas parece que implementá-la envolveria alguns malabarismos do manipulador de analisador, esp. algo como uma sobrecarga temporária de InputHandler.print . É meio estranho que seja feito assim (puxa um pouco o estado terminal para o analisador, um fato que nenhuma outra sequência de escape faz até agora), mas deve ser viável substituindo o manipulador de impressão no meio.

@jerch sim, precisaria de algumas alterações no analisador. Redimensionar links agrupados é um caso que precisamos ter certeza de que funciona também.

O VS Code agora tem suporte para mostrar navegações detalhadas para links, portanto, conectá-lo a isso resolverá o problema:

image

É uma pena que seja uma sequência um pouco estranha, já que nossos ganchos do analisador não cobrem isso. Se eles fizessem, isso poderia ser feito inteiramente como um complemento usando ganchos de analisador, marcadores e as APIs do provedor de links.

@Tyriar Também com # 2751, o armazenamento de

É uma pena que seja uma sequência um pouco estranha, já que nossos ganchos do analisador não cobrem isso. Se eles fizessem, isso poderia ser feito inteiramente como um complemento usando ganchos de analisador, marcadores e as APIs do provedor de links.

Sim, isso é um problema e imho não pode ser resolvido no nível do complemento, mesmo se expormos um gancho do manipulador de impressão. Acho que isso deve ir diretamente para a base de código, além de algumas condições excepcionais (como qualquer ação não impressa antes de o finalizador ser reconhecido deve quebrar a marcação de URL de células e tal).

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

parisk picture parisk  ·  3Comentários

albinekb picture albinekb  ·  4Comentários

Mlocik97-issues picture Mlocik97-issues  ·  3Comentários

jestapinski picture jestapinski  ·  3Comentários

chris-tse picture chris-tse  ·  4Comentários