<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Decenhash - File Sharing Project</title>
<style>
:root {
--bg-color: #ffffff;
--text-color: #374151;
--primary-color: #4b5563;
--secondary-color: #f3f4f6;
--accent-color: #6b7280;
--link-color: #3b82f6;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: var(--bg-color);
margin: 0;
padding: 0;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid #e5e7eb;
}
h1 {
color: var(--text-color);
margin: 0;
font-size: 1.75rem;
font-weight: 600;
}
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
cursor: pointer;
font-size: 0.875rem;
transition: all 0.2s ease;
font-weight: 500;
}
button:hover {
background-color: var(--accent-color);
transform: translateY(-1px);
}
section {
margin-bottom: 2rem;
}
h2 {
color: var(--text-color);
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
}
ul {
padding-left: 1.25rem;
margin: 1rem 0;
}
li {
margin-bottom: 0.5rem;
position: relative;
}
li::before {
content: "•";
color: var(--accent-color);
position: absolute;
left: -1rem;
}
footer {
margin-top: 3rem;
padding-top: 1.5rem;
border-top: 1px solid #e5e7eb;
font-size: 0.875rem;
color: var(--accent-color);
}
a {
color: var(--link-color);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: #2563eb;
text-decoration: underline;
}
.static-links {
display: flex;
gap: 1.5rem;
margin-top: 1rem;
}
.feature-item {
margin-bottom: 1.5rem;
}
.feature-title {
font-weight: 500;
color: var(--text-color);
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
</head>
<body>
<header>
<h1 id="title">DECENHASH</h1>
<form id="search-form" class="search-form" onsubmit="performSearch(event)">
<input type="text" id="search-input" class="search-input" placeholder="Enter file hash or category" required>
<button type="submit" class="search-button">Search</button>
</form>
<button id="language-toggle">English</button>
</header>
<main>
<section>
<p id="main-description">Nosso projeto oferecer padrões e convenções que tornam fácil identificar quais servidores hospedam o mesmo arquivo e o compartilhamento. Além da pesquisa por hash também é possível explorar e descobrir categorias de arquivos nos servidores.</p>
<ul id="features-list">
<li>Todos os arquivos são salvos usando como nome o hash sha256 do arquivo e a extensão</li>
<li>Todos os arquivos são salvos dentro do diretório "data" (em subdiretório com o nome do hash do arquivo, por exemplo, data/123/123.jpg)</li>
<li>Alguns arquivos e diretórios podem ser categorias que apenas apotam para outros arquivos ou diretórios.</li>
</ul>
</section>
<section>
<h2 id="how-it-works">Como funciona?</h2>
<div class="feature-item">
<p><strong class="feature-title" id="index-title">Index / FileUploadServer</strong> - <span id="index-desc">O arquivo que você enviar será renomeado usando o hash sha256 e você pode inserir uma categoria. Você ou qualquer usuário pode acessar o arquivo do servidor se souber o hash do arquivo ou se inserir uma categoria que coincida com a que você inseriu.</span></p>
</div>
<div class="feature-item">
<p><strong class="feature-title" id="builder-title">Data builder</strong> - <span id="builder-desc">Todos os arquivos nos subdiretórios da pasta "categories" serão copiados para a pasta "data" e renomeados usando o hash do arquivo (Por exemplo, dentro da pasta "categories" você criar outras pastas como música, imagens, videos e nelas colocar os arquivos desejados).</span></p>
</div>
<div class="feature-item">
<p><strong class="feature-title" id="servers-title">Servers</strong> - <span id="servers-desc">Verifica se cada servidor do arquivo 'servers.txt' possui os arquivos de "files.txt". Caso o arquivo seja válido então será criado um arquivo de texto na pasta "servers" com o nome do arquivo (hash) e o endereço de todos os servidores que hospedam esse arquivo.</span></p>
</div>
<div class="feature-item">
<p><strong class="feature-title" id="download-title">Download</strong> - <span id="download-desc">Faz a mesma coisa que "servers" mas irá salvar os arquivos caso eles não existam.</span></p>
</div>
<div class="feature-item">
<p><strong class="feature-title" id="block-title">Downloader</strong> - <span id="block-desc">O usuário pode salvar em um arquivo um conteúdo (não implementa a estrutura de blocos de verdade)</span></p>
</div>
<div class="feature-item">
<p><strong class="feature-title" id="blockchain-title">Blockchain</strong> - <span id="blockchain-desc">Implementa a estrutura de blocos, mas sem consenso (apenas envia para os servidores o conteúdo que o usuário inseriu)</span></p>
</div>
</section>
<section>
<h2 id="contact-title">Pages</h2>
<div class="static-links">
<a href="index.php">Upload</a>
<a href="add_server.php">Add server</a>
<a href="downloader.php">Downloader</a>
<a href="blockchain.php">Blockchain</a>
</div>
</section>
</main>
<footer>
<a href="https://chat.whatsapp.com/GbT2LBn2AGG1mw3vTreIWr" target="_blank">WhatsApp</a>/
<a href="https://t.me/decenhash" target="_blank">Telegram</a>/
<a href="https://sourceforge.net/projects/decenhash" target="_blank">Sourceforge</a>/
<a href="https://github.com/decenhash" target="_blank">GitHub</a>/
<a href="https://3gp.neocities.org/" target="_blank">Website</a>/
<a href="mailto:[email protected]" target="_blank">Mail</a>/
<p id="footer-text">© 2023 File Sharing Project. Todos os direitos reservados.</p>
</footer>
<script>
// Add SHA-256 hashing function
async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
// Function to handle search form submission
async function performSearch(event) {
event.preventDefault();
const searchInput = document.getElementById('search-input').value.trim();
if (!searchInput) return;
try {
// Check if input is already a valid SHA-256 hash (64 hex characters)
const isValidHash = /^[a-fA-F0-9]{64}$/.test(searchInput);
let hash;
if (isValidHash) {
// If input is already a valid hash, use it directly
hash = searchInput;
} else {
// Otherwise generate SHA-256 hash of the input
hash = await sha256(searchInput);
}
// Redirect to the directory with the hash
window.location.href = `data/${hash}/index.html`;
} catch (error) {
console.error('Error processing request:', error);
alert('An error occurred while processing your request. Please try again.');
}
}
const translations = {
'pt-BR': {
'title': 'DECENHASH',
'main-description': 'Nosso projeto oferecer padrões e convenções que tornam fácil identificar quais servidores hospedam o mesmo arquivo e o compartilhamento. Além da pesquisa por hash também é possível explorar e descobrir categorias de arquivos nos servidores.',
'features-list': [
'Todos os arquivos são salvos usando como nome o hash sha256 do arquivo e a extensão.',
'Todos os arquivos são salvos dentro do diretório "data" (em subdiretório com o nome do hash do arquivo, por exemplo, data/123/123.jpg).',
'É possivel pesquisar quais servidores hospedam o mesmo arquivo através do hash. Ou baixar todos os arquivos de uma categoria facilmente.'
],
'how-it-works': 'Como funciona?',
'index-title': 'Index / FileUploadServer',
'index-desc': 'O arquivo que você enviar será renomeado usando o hash SHA-256 e você pode inserir uma categoria. Você ou qualquer usuário pode acessar o arquivo do servidor se souber o hash do arquivo ou se inserir uma categoria que coincida com a que você inseriu.',
'builder-title': 'Data builder',
'builder-desc': 'Todos os arquivos nos subdiretórios da pasta "categories" serão copiados para a pasta "data" e renomeados usando o hash do arquivo (Por exemplo, dentro da pasta "categories" você pode criar outras pastas como música, imagens, videos e nelas coloca os arquivos desejados).',
'servers-title': 'Servers',
'servers-desc': 'Verifica se cada servidor do arquivo "servers.txt" possui os arquivos de "files.txt". Caso o arquivo seja válido então será criado um arquivo de texto na pasta "servers" com o nome do arquivo (hash) e o endereço de todos os servidores que hospedam esse arquivo.',
'download-title': 'Download',
'download-desc': 'Faz a mesma coisa que "servers" mas irá salvar os arquivos caso eles não existam.',
'block-title': 'Downloader',
'block-desc': 'Pesquisa nos servidores e baixa todos os arquivos de uma categoria específica ou pelo hash.',
'blockchain-title': 'Blockchain',
'blockchain-desc': 'Implementa a estrutura de blocos, mas sem consenso (apenas envia para os servidores o conteúdo que o usuário inseriu).',
'contact-title': 'Páginas',
'contact-info': 'WhatsApp / Telegram / Mail',
'footer-text': '© 2025 Decenhash. Todos os direitos reservados.',
'toggle-button': 'English'
},
'en': {
'title': 'DECENHASH',
'main-description': 'Our project provides standards and conventions that make it easy to identify which servers host the same file and enable sharing. In addition to searching by hash, it is also possible to explore and discover file categories on the servers.',
'features-list': [
'All files are saved using the sha256 hash of the file as the name plus the extension.',
'All files are saved inside the "data" directory (in a subdirectory named after the file hash, e.g., data/123/123.jpg).',
'It is possible to search which servers host the same file through its hash, or easily download all files from a category.'
],
'how-it-works': 'How it works?',
'index-title': 'Index / FileUploadServer',
'index-desc': 'The file you upload will be renamed using the SHA-256 hash, and you can assign it a category. You or any user can access the file on the server if they know the file\'s hash or provide a category that matches the one you entered. Both are saved in a subdirectory of the "data" folder, named after the generated hash.',
'builder-title': 'Data builder',
'builder-desc': 'All files in the subdirectories of the "categories" folder will be copied to the "data" folder and renamed using the file hash (For example, inside the "categories" folder you can create other folders like music, images, videos and place the desired files in them).',
'servers-title': 'Servers',
'servers-desc': 'Checks if each server in the "servers.txt" file has the files listed in "files.txt". If the file is valid, a text file will be created in the "servers" folder with the file name (hash) and the address of all servers that host this file.',
'download-title': 'Download',
'download-desc': 'Does the same thing as "servers" but will save the files if they don\'t exist.',
'block-title': 'Downloader',
'block-desc': 'Searches the servers and downloads all files from a specific category or by hash.',
'blockchain-title': 'Blockchain',
'blockchain-desc': 'Implements the block structure, but without consensus (only sends to the servers the content that the user entered)',
'contact-title': 'Pages',
'contact-info': 'WhatsApp / Telegram / Mail',
'footer-text': '© 2025 Decenhash. All rights reserved.',
'toggle-button': 'Português'
}
};
const toggleButton = document.getElementById('language-toggle');
let currentLanguage = 'pt-BR';
function updateContent(language) {
document.documentElement.lang = language;
const elements = document.querySelectorAll('[id]');
elements.forEach(element => {
const id = element.id;
if (translations[language][id]) {
if (Array.isArray(translations[language][id])) {
// Handle lists
const listItems = element.querySelectorAll('li');
listItems.forEach((li, index) => {
li.textContent = translations[language][id][index];
});
} else {
element.textContent = translations[language][id];
}
}
});
toggleButton.textContent = translations[language]['toggle-button'];
}
toggleButton.addEventListener('click', () => {
currentLanguage = currentLanguage === 'pt-BR' ? 'en' : 'pt-BR';
updateContent(currentLanguage);
});
// Initialize with Portuguese
updateContent('pt-BR');
</script>
</body>
</html>