Ir ao conteúdo
  • Cadastre-se

herbertbahia

Membro Pleno
  • Posts

    542
  • Cadastrado em

  • Última visita

Tudo que herbertbahia postou

  1. Uma abordagem possível é usar um firewall DPI (Deep Packet Inspection), que é capaz de analisar o conteúdo dos pacotes de dados em tempo real e bloquear aqueles que correspondem a padrões maliciosos. No entanto, essa abordagem pode ser complexa e pode afetar outros serviços que usam websockets. Uma abordagem mais simples é bloquear os websockets específicos no nível do aplicativo, por meio de configurações ou código específico. Por exemplo, se o programa que você está executando fornece uma configuração para especificar o endereço do servidor websocket, você pode bloquear o endereço malicioso nessa configuração ou adicioná-lo a uma lista negra. Se o programa não fornecer uma opção de configuração para isso, você pode modificar o código fonte do programa para bloquear os websockets específicos. Outra opção é usar ferramentas de segurança de rede, como IDS (Intrusion Detection Systems) e IPS (Intrusion Prevention Systems), que podem detectar e bloquear tráfego malicioso em tempo real. Essas ferramentas geralmente usam assinaturas e heurísticas para detectar atividades maliciosas e podem ser configuradas para bloquear websockets específicos. Independentemente da abordagem escolhida, é importante monitorar continuamente o tráfego de rede e manter as defesas atualizadas para garantir a segurança do sistema.
  2. Um problema possível é que o método Executar da classe Conexao pode estar retornando um resultado diferente do esperado ou mesmo nenhum resultado, o que pode afetar a contagem dos filmes. Certifique-se de que a consulta SQL esteja correta e esteja retornando o resultado esperado. Outra possibilidade é que o uso da função count pode não estar funcionando corretamente no array $filmes. Verifique se esse array está sendo preenchido corretamente e se o tipo de dados é um array. Uma sugestão para depurar esse problema é verificar o conteúdo das variáveis $filmes e $totalFilmes em cada iteração do loop. Isso pode ajudar a identificar onde está o erro. Espero que isso ajude!
  3. . Algoritmo "MATRIZ 4X4" // Descrição : CADASTRO DE MORADORES // Autor(a) : PABLO MASCARENHAS // Data atual : 26/02/2023 Var // Seção de Declarações das variáveis MORADORES : VETOR[1..4, 1..4] DE caractere I,J : INTEIRO ROTULO : VETOR[1..4] DE CARACTERE Inicio // Seção de Comandos, procedimento, funções, operadores, etc... ESCREVAL("DIGITE O NOME DO CONDOMINIO") ROTULO[1]<- "NUMERO DA CASA:" ROTULO[2]<- "QUANTIDADE DE CARRO:" ROTULO[3]<- "MODELO DO CARRO:" ROTULO[4]<- "PLACA DO CARRO:" ESCREVAL("DIGITE OS DADOS DO MORADOR") PARA I DE 1 ATE 4 FACA ESCREVAL("MORADOR", I+0) LIMPATELA PARA J DE 1 ATE 4 FACA ESCREVA(ROTULO[J]) LEIA(MORADORES[I,J]) FIMPARA ESCREVAL() FIMPARA ESCREVAL("FIM DOS DADOS") ESCREVAL("DADOS DIGITADOS") PARA I DE 1 ATE 4 FACA PARA J DE 1 ATE 4 FACA ESCREVA(MORADORES[I,J], " ") FIMPARA ESCREVAL() FIMPARA Fimalgoritmo
  4. Tente desativar as extensões uma por uma para ver se alguma delas está causando o problema. Para fazer isso, vá em "Extensões" no menu lateral, desative uma extensão e tente selecionar o texto novamente. Repita esse processo até encontrar a extensão problemática. Verifique se o modo de seleção está correto. No canto inferior direito do VS Code, deve haver um botão de alternância para o modo de seleção. Certifique-se de que ele esteja definido para "Seleção" e não "Linha". Verifique se há algum problema com a configuração do mouse. Vá para as configurações do VS Code (por meio de "Arquivo" > "Preferências" > "Configurações") e pesquise por "mouseWheelZoom". Certifique-se de que a configuração está definida como "false". Isso pode ajudar a evitar conflitos entre o mouse e o VS Code. Tente reiniciar o VS Code. Às vezes, isso pode ajudar a resolver o problema temporariamente. Verifique se há atualizações para o VS Code e instale-as, se houver. Isso pode corrigir problemas conhecidos que foram corrigidos em versões posteriores.
  5. Para resolver este exercício, precisamos seguir os seguintes passos: Criar a matriz para armazenar os dados do condomínio. Neste caso, será uma matriz 4x4, em que a primeira coluna armazenará o número da casa, a segunda coluna armazenará a quantidade de carros de cada casa, a terceira coluna armazenará o modelo de cada carro e as duas últimas colunas armazenarão a placa de cada carro. Ler os dados do condomínio, que são o nome do aluno, a quantidade de casas e os dados de cada casa, como quantidade de carros, modelo de cada carro e placa de cada carro. Armazenar os dados lidos na matriz. Imprimir o número da casa e o modelo de cada carro. Imprimir a placa do carro de cada casa e a quantidade de carros de cada casa. Criar uma função que receba o nome completo do aluno, a data de nascimento completa e retorne o nome do aluno, mais a idade expressa em números romanos.
  6. o que você já conseguiu fazer? e qual a sua dificuldade?
  7. Embora a função TransparentBlt() possa ser útil para copiar imagens com transparência, ela pode não ser a melhor escolha para jogos 2D/3D simples, como Wolf3d ou Duke 1. Isso ocorre porque a função foi projetada para ser usada em conjunto com a API GDI, que é otimizada para desenho de gráficos em janelas e não é tão eficiente quanto as bibliotecas de gráficos mais modernas, como o Directx. Além disso, o uso de DIBs (Device-Independent Bitmaps) pode ser rápido, mas pode ter limitações em relação às capacidades de renderização de gráficos mais modernas. Essas limitações podem incluir a falta de suporte para recursos como aceleração de hardware e efeitos gráficos avançados. Portanto, para jogos 2D/3D simples, é recomendável usar bibliotecas gráficas mais modernas, como o Directx, que são otimizadas para jogos e oferecem suporte para recursos avançados de renderização de gráficos.
  8. A função TransparentBlt() é uma função da biblioteca Windows GDI (Graphics Device Interface) que permite copiar uma imagem de origem para uma imagem de destino com transparência. A transparência é determinada por uma máscara de cor especificada pelo desenvolvedor. Para replicar a funcionalidade da função TransparentBlt() de forma rápida, é possível usar um conjunto de técnicas e tecnologias, como o uso de Direct2D ou o uso de bibliotecas gráficas de terceiros. No entanto, para entender como a função TransparentBlt() funciona internamente, é importante saber que a função é implementada internamente pelo Windows usando a API BitBlt() e uma combinação de DIBs (Device Independent Bitmaps) e algoritmos de transparência. A API BitBlt() é usada para realizar uma operação de transferência de bitmap de uma região da memória para outra, e os DIBs são usados para fornecer um formato de imagem independente do dispositivo. Para obter desempenho aprimorado, a função TransparentBlt() usa otimizações específicas da plataforma, como código otimizado em Assembly, suporte a hardware gráfico acelerado e outras técnicas de otimização de desempenho. Assim, para recriar a função TransparentBlt() de forma rápida, é importante entender como as operações gráficas funcionam em um nível mais baixo e como é possível aproveitar as tecnologias e técnicas modernas para otimizar o desempenho da função.
  9. existem vários desses macros grátis hoje em dia no mercado, sendo possível utilizar apenas baixando mas caso queira desenvolver o seu proprio também é possível https://www.techtudo.com.br/tudo-sobre/mouse-and-keyboard-recorder/
  10. sim com certeza é possível automatizar, qual a linguagem de programação que você tem uma noção básica? Eu recomendo você utilizar macro, assim você pode simplesmente gravar os movimentos do seu teclado que sao apertar a tecla para linha de baixo, end, del e space. E depois fazer o macro repetir isto varias vezes até terminar todo texto.
  11. Certamente, aqui estão alguns exemplos de como realizar requisições GET e POST tanto em Java quanto em JavaScript: Java: GET request: import java.net.HttpURLConnection; import java.net.URL; public class JavaGetRequest { public static void main(String[] args) throws Exception { URL url = new URL("https://example.com/api/v1/items"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); int status = con.getResponseCode(); System.out.println(status); // This will print the HTTP status code of the response. } } POST request: import java.net.HttpURLConnection; import java.net.URL; import java.io.DataOutputStream; public class JavaPostRequest { public static void main(String[] args) throws Exception { URL url = new URL("https://example.com/api/v1/items"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/json"); con.setDoOutput(true); String jsonInputString = "{\"item\": \"Item name\", \"quantity\": 10}"; try (DataOutputStream out = new DataOutputStream(con.getOutputStream())) { out.write(jsonInputString.getBytes()); } int status = con.getResponseCode(); System.out.println(status); // This will print the HTTP status code of the response. } } JavaScript: GET request: const https = require('https'); https.get('https://example.com/api/v1/items', (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { console.log(JSON.parse(data)); // This will print the response data as a JSON object. }); }).on("error", (err) => { console.log("Error: " + err.message); }); POST request: const https = require('https'); const options = { hostname: 'example.com', path: '/api/v1/items', method: 'POST', headers: { 'Content-Type': 'application/json' } }; const req = https.request(options, (res) => { console.log(`statusCode: ${res.statusCode}`); res.on('data', (d) => { process.stdout.write(d); }); }); req.on('error', (error) => { console.error(error); }); const data = JSON.stringify({ item: 'Item name', quantity: 10 }); req.write(data); req.end(); espero que ajude
  12. Já que estamos falando de web, você pode tentar começar pela parte de entender os métodos https para ficar menos leigo. A internet gira em torno deles. Confira a seguir os principais métodos: GET: o método GET é usado para recuperar dados do servidor. Ele solicita um recurso específico e retorna a representação desse recurso. POST: o método POST é usado para enviar dados ao servidor para criar ou atualizar um recurso. Ele geralmente é usado para enviar dados de formulário, mas pode ser usado para enviar qualquer tipo de dados. PUT: o método PUT é usado para atualizar um recurso no servidor. Ele substitui completamente o recurso existente pelo novo recurso enviado no corpo da solicitação. DELETE: o método DELETE é usado para excluir um recurso do servidor. Ele solicita a exclusão do recurso identificado pela URI. Por isso para fazer o ajuste de um item no endpoint mencionado voce precisa entender que deve utilizar o metodo post e não os métodos gets. Em seguida aconselho tentar entender os dados dele. Você deverá utilizar um objeto que comtemple os atributos conforme na documentação. Caso não entenda o conceito de objetos ou orientação a objetos recomendo este material https://www.devmedia.com.br/principais-conceitos-da-programacao-orientada-a-objetos/32285 Após a criação da classe com seus devidos atributos aconselho você postar aqui o seu código e posso lhe sugeri uma boa tecnologia para você implementar um serviço para ele.
  13. Existem várias maneiras de criar uma base de dados para um tree view. Tudo depende do tipo de dados que você deseja armazenar e da forma como deseja que eles sejam organizados. Uma opção é usar um banco de dados relacional, como MySQL ou PostgreSQL, para armazenar seus dados hierárquicos. Isso é comumente feito usando um modelo de dados de árvore, que é um modelo de dados hierárquico no qual cada registro contém um campo que identifica seu pai. Existem várias implementações de banco de dados que suportam modelos de dados de árvore, como o Nested Set Model ou o Adjacency List Model. Outra opção é usar um banco de dados NoSQL, como o MongoDB, que é projetado para armazenar dados não estruturados. O MongoDB suporta dados hierárquicos usando documentos aninhados e arrays. Independentemente do tipo de banco de dados que você escolher, é importante garantir que seus dados estejam bem organizados para que seu tree view seja fácil de navegar. Certifique-se de que seus registros estejam claramente organizados em uma hierarquia e que cada registro seja identificado por um ID exclusivo. Além disso, certifique-se de que o banco de dados seja projetado para suportar as consultas que você deseja executar em seu tree view, como ordenação ou filtragem. Quanto à biblioteca jQuery que você encontrou, ela pode ser uma boa opção para exibir seu tree view na interface do usuário, mas você ainda precisará de um meio de armazenar e gerenciar seus dados hierárquicos.
  14. Pelo que entendi do seu código, você está tentando executar um script específico dependendo da seleção do usuário em um menu dinâmico gerado a partir de um arquivo de texto. Depois de executar o script, você deseja remover a linha correspondente do arquivo de texto para que ela não apareça no próximo menu gerado. O seu código atual parece estar quase lá, mas há algumas coisas que precisam ser ajustadas. O primeiro problema é que você está usando o valor do ID como o valor do item de seleção do menu. Isso pode funcionar em alguns casos, mas pode levar a problemas se o valor do ID contiver caracteres que o dialog não pode lidar. Em vez disso, é melhor usar o índice da linha no array options como o valor do item de seleção do menu. Para fazer isso, você pode criar uma variável count no início do script e incrementá-la a cada linha que for adicionada ao array options. Em seguida, você pode usar o valor de count como o valor do item de seleção do menu. Dessa forma, você pode ter certeza de que o valor do item de seleção será sempre um número inteiro válido. Aqui está uma versão modificada do seu script que faz isso: #!/bin/bash # Define o nome do arquivo de relatório report_file="scripts/hmenu/result.txt" # Inicializa o contador count=0 # Lê o arquivo result.txt no subdiretório scripts/hmenu while read line; do # Extrai o ID, o texto e o status da linha id=$(echo $line | awk '{print $1}') text=$(echo $line | awk '{print $2 " " $3 " " $4 " " $5 " " $6 " " $7 " " $8 " " $9}') status=$(echo $line | awk '{print $10}') # Adiciona o item de checkbox ao menu options+=("$count" "$text" "$status") # Incrementa o contador ((count++)) done < "$report_file" # Exibe o menu em forma de checkbox selected=$(dialog --backtitle "Selecione os itens desejados:" \ --checklist " " 20 60 15 "${options[@]}" \ --output-fd 1 \ --separate-output \ --scrollbar \ 3>&1 1>&2 2>&3) # Executa cada item selecionado for item in $selected; do # Obtém a linha correspondente do arquivo line=$(sed -n "${item}p" "$report_file") # Obtém o ID e o comando do item id=$(echo "$line" | awk '{print $1}') command=$(echo "$line" | awk '{$1=""; print $0}') # Executa o comando echo "Executando o código para o Item $id..." eval "$command" # Remove a linha correspondente do arquivo sed -i "${item}d" "$report_file" done
  15. O erro mencionado parece ser relacionado à biblioteca win32api que está sendo importada pelo pywinauto. Esse erro geralmente ocorre quando a biblioteca pywin32 não está instalada ou está instalada em uma versão incompatível com a versão do Python. Para resolver esse erro, tente reinstalar a biblioteca pywin32 com a versão correta correspondente ao seu ambiente Python. Por exemplo, se você está usando o Python 3.9, tente instalar a biblioteca pywin32 para o Python 3.9 usando o pip: pip install pywin32==301 Certifique-se de que a versão pywin32 que você está instalando corresponde à versão correta do seu Python. Se isso não resolver o problema, tente verificar se há conflitos entre as versões do Python instaladas em seu sistema. Você pode tentar executar seu script em um ambiente virtual isolado, criado com o comando venv, para garantir que as dependências do Python estejam instaladas corretamente e em sua versão correta. Se o problema persistir, tente postar mais detalhes sobre seu ambiente Python e as bibliotecas que você está usando, pois isso pode ajudar a diagnosticar o problema com mais precisão.
  16. Para centralizar a data exibida em um componente p:calendar do PrimeFaces, você pode adicionar o atributo inputStyle com a propriedade text-align: center;. Por exemplo: <p:calendar id="nascimento" value="#{comprasMB.data}" pattern="dd-MM-yyyy" mask="true" locale="pt_BR" style="font-size: 12pt !important;" inputStyle="text-align: center;"/>
  17. O que voce quer dizer com utilizar? seria consumir os endpoints? se sim qual a tecnologia voce irá desenvolver para isto? jsf ? jsp? springbot? thymeleaf? ou outra? O que você ja conseguiu desenvolver até o momento?
  18. Olá! Há alguns problemas no código que você apresentou que podem estar impedindo o cálculo correto do desconto do INSS e do IR. Aqui estão algumas sugestões de como corrigi-los: A condição if (salario_bruto <= 1903.98) deve ser a primeira verificação a ser feita, pois se o salário for menor do que esse valor, o desconto do IR é zero e o cálculo deve ser encerrado ali. No código atual, essa verificação só é feita depois das verificações do INSS. Para calcular o desconto do IR, você precisa primeiro subtrair o valor do INSS do salário bruto. No código atual, o desconto do INSS é calculado, mas não é subtraído do salário bruto antes de calcular o desconto do IR. No cálculo do desconto do INSS para salários acima de R$ 5.646,80, o valor do desconto está incorreto. O correto seria subtrair um valor fixo de R$ 621,04. Você precisa declarar as variáveis inss, ir e salario_liquido e inicializá-las com zero. Caso contrário, o valor dessas variáveis pode ser indefinido e o cálculo do salário líquido pode não ser correto. Com essas sugestões em mente, aqui está uma versão corrigida do seu código: #include <iostream> int main(int argc, char** argv) { float salario_bruto, inss, ir, salario_liquido = 0; printf("Digite seu Salario Bruto: "); scanf("%f", &salario_bruto); if (salario_bruto <= 1903.98) { ir = 0; } else if (salario_bruto <= 2826.65) { ir = (salario_bruto - inss) * 0.075 - 142.80; } else if (salario_bruto <= 3751.05) { ir = (salario_bruto - inss) * 0.15 - 354.80; } else if (salario_bruto <= 4664.68) { ir = (salario_bruto - inss) * 0.225 - 636.13; } else { ir = (salario_bruto - inss) * 0.275 - 869.36; } if (salario_bruto <= 1693.72) { inss = salario_bruto * 0.08; } else if (salario_bruto <= 2822.90) { inss = salario_bruto * 0.09; } else if (salario_bruto <= 5645.80) { inss = salario_bruto * 0.11; } else { inss = 621.04; } salario_liquido = salario_bruto - inss - ir; printf("\nDesconto INSS: R$ %.2f\n", inss); printf("Desconto IR: R$ %.2f\n", ir); printf("Salario liquido: R$ %.2f\n", salario_liquido); return 0; }
  19. Para retornar o valor inteiro do count(*), você deve obter o valor do ResultSet. Você pode fazer isso adicionando o seguinte código dentro do try-catch: resultado.next(); qtiaLinhas = resultado.getInt(1); E então retornar o valor de qtiaLinhas, ao invés de resultado. Assim: public static int getQtiaLinhas() { int qtiaLinhas = 0; ResultSet resultado = null; String sql = "select count (*) from autor_consulta"; try { Connection conexao = Conexao.getConnection(); Statement comando = conexao.createStatement(); resultado = comando.executeQuery(sql); resultado.next(); qtiaLinhas = resultado.getInt(1); } catch (Exception e) { System.out.println("não foi possível contar o num de linhas" + e.getMessage()); } return qtiaLinhas; } Lembre-se de fechar a conexão com o banco de dados ao terminar de usar.
  20. Se a sua dúvida é no desenvolvimento de um script sql você pode postar nessa seção https://www.clubedohardware.com.br/forums/forum/180-bancos-de-dados/
  21. Para verificar o progresso da descompactação de um arquivo zip usando o módulo zipfile do Python, você pode usar o método extractall() e passar um objeto de retorno de chamada (callback) como um argumento. Esse objeto de retorno de chamada deve ser uma função que será chamada a cada vez que um arquivo é extraído do arquivo zip. Você pode usar essa função para exibir o progresso da descompactação para o usuário. Aqui está um exemplo de como fazer isso: import zipfile def unzip_progress(zip_obj): print("Descompactando arquivo %s" % zip_obj.filename) zip_file = zipfile.ZipFile("arquivo.zip", "r") zip_file.extractall(callback=unzip_progress) zip_file.close() Para verificar o progresso da descompactação de um arquivo lzma usando o módulo lzma do Python, você pode usar o método open() para abrir o arquivo lzma e então usar o método read() para ler os dados. A cada vez que você chama o método read(), você pode atualizar uma barra de progresso ou exibir uma mensagem de progresso para o usuário. Aqui está um exemplo de como fazer isso: import lzma CHUNK_SIZE = 1024 # Tamanho do pedaço de dados a ser lido por iteração with lzma.open("arquivo.lzma", "rb") as lzma_file: # Obtenha o tamanho total do arquivo total_size = lzma_file.getbuffer().size() # Inicialize a variável de progresso progress = 0 while True: data = lzma_file.read(CHUNK_SIZE) if not data: # O arquivo foi lido completamente break # Atualize o progresso progress += len(data) percentage = int(progress / total_size * 100) print("Progresso da descompactação: %d%%" % percentage)
  22. Para exibir uma barra de progresso para uma função que não é um laço, voce pode adicionar uma variavel para armazenar o progresso atual da função e atualizar essa variavel enquanto a função estiver sendo executada. Depois, voce pode usar essa variavel para exibir a barra de progresso na tabela. voce pode adicionar um argumento na sua função zipar_lzma e zipar_rar para armazenar o progresso atual da compactação do arquivo. Por exemplo: def zipar_lzma(nome, progresso): # codigo para compactar o arquivo # atualiza o progresso progresso[nome] = 50 # exemplo, o progresso é 50% def zipar_rar(nome, progresso): # codigo para compactar o arquivo # atualiza o progresso progresso[nome] = 75 # exemplo, o progresso é 75% voce pode criar uma variavel compartilhada (como um dicionario) para armazenar o progresso atual de cada arquivo e passar essa variavel como argumento para as threads. Exemplo: import threading progresso = {} # dicionario para armazenar o progresso de cada arquivo # cria as threads threads = [] for nome in nomes_dos_arquivos: t = threading.Thread(target=zipar_lzma if usar_lzma else zipar_rar, args=(nome, progresso)) t.start() threads.append(t) # espera até que todas as threads terminem for t in threads: t.join() # todos os arquivos foram compactados # atualiza o resultado final da compactação na tabela voce pode usar o dicionario progresso para atualizar a barra de progresso na tabela enquanto as threads estão sendo executadas. Quando todas as threads terminarem, voce pode atualizar o resultado final da compactação na tabela. voce pode usar a biblioteca time para calcular o tempo estimado para a conclusão da função. voce pode medir o tempo que a função leva para executar e usar essa informação para estimar o tempo restante para a conclusão da função.
  23. Para implementar a funcionalidade de controlar a luminosidade da lâmpada utilizando o Dimmer, você pode usar o oscilador interno do microcontrolador para gerar um sinal de PWM (modulação por largura de pulso). A intensidade da lâmpada pode ser controlada variando a relação ciclo ativo/ciclo total do sinal PWM. A seguir está um exemplo de como implementar o sinal PWM no seu código: #define _XTAL_FREQ 4000000 // frequência do oscilador interno // configura o oscilador interno e o módulo CCP void setup_PWM() { // configura o oscilador interno para trabalhar a 4 MHz OSCCON = 0b01110010; // habilita o módulo CCP1 em modo PWM CCP1CON = 0b00001100; // configura o período do sinal PWM PR2 = 249; // período de 4 ms (250 * 16 us) // habilita o timer 2 T2CON = 0b00000101; } // define a duty cycle do sinal PWM (de 0 a 100) void set_duty_cycle(unsigned char duty_cycle) { // calcula o valor do ciclo ativo unsigned int t_on = (duty_cycle * PR2) / 100; // atualiza o registrador CCPR1L CCPR1L = t_on >> 2; // atualiza os bits de menor peso do registrador CCP1CON CCP1CON &= 0b11001111; CCP1CON |= (t_on & 0b00000011) << 4; } void main() { // configura o PWM setup_PWM(); // habilita a saída do sinal PWM no pino RC2 TRISC2 = 0; while (1) { // ajusta o duty cycle para 0% set_duty_cycle(0); delay_ms(500); // ajusta o duty cycle para 50% set_duty_cycle(50); delay_ms(500); // ajusta o duty cycle para 100% set_duty_cycle(100); delay_ms(500); } }
  24. Poste seu código especificando o que deseja alterar. talvez eu possa ajudar.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!