Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
name: Deploy Jekyll site to Pages
# Sample workflow for building and deploying a VitePress site to GitHub Pages
name: Deploy VitePress site to Pages

on:
# Runs on pushes targeting the default branch
Expand Down Expand Up @@ -30,28 +30,24 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node
with:
fetch-depth: 0 # For git-based features like lastUpdated
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install Node deps
cache: npm
- name: Install dependencies
run: npm ci
- name: Compile typescript
- name: Build with VitePress
run: npm run build
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0' # Not needed with a .ruby-version file
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
cache-version: 0 # Increment this number if you need to re-download cached gems
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" # defaults output to '/_site'
env:
JEKYLL_ENV: production
- name: Upload artifact
uses: actions/upload-pages-artifact@v3 # This will automatically upload an artifact from the '/_site' directory
uses: actions/upload-pages-artifact@v3
with:
path: .vitepress/dist
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@ _site/
.jekyll-metadata
Gemfile.lock
assets/js/zzzz-search-data.json

### VitePress ###
.vitepress/dist/
.vitepress/cache/
.vitepress/.temp/

### Node ###
node_modules/
assets/js/generated
135 changes: 135 additions & 0 deletions .vitepress/config.mts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot sistema il gitignore, mi hai committato i file di build

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sistemato! Ho aggiornato il .gitignore per escludere i file di build di VitePress (.vitepress/dist/, .vitepress/cache/, .vitepress/.temp/) e rimosso tutti i file di build dal repository. Commit: 77b2c90

Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { defineConfig } from 'vitepress'

export default defineConfig({
title: 'Hack GPON',
description: 'Worldwide wiki on how to access, change and edit ONTs',

// Keep URLs consistent with Jekyll
cleanUrls: true,

head: [
['link', { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' }],
['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' }],
['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }],
['link', { rel: 'manifest', href: '/site.webmanifest' }],
['link', { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' }],
['meta', { name: 'msapplication-TileColor', content: '#da532c' }],
['meta', { name: 'theme-color', content: '#ffffff' }],
],

themeConfig: {
logo: '/favicon-32x32.png',

nav: [
{ text: 'Home', link: '/' },
{ text: 'Quick Start', link: '/quick-start' },
{ text: 'FAQ', link: '/faq' },
],

sidebar: [
{
text: 'Getting Started',
items: [
{ text: 'Home', link: '/' },
{ text: 'Quick Start', link: '/quick-start' },
{ text: 'FAQ', link: '/faq' },
]
},
{
text: 'ONT GPON',
collapsed: false,
link: '/ont-zte',
items: []
},
{
text: 'ONT XGS-PON',
collapsed: false,
items: []
},
{
text: 'ONT EPON',
collapsed: false,
items: []
},
{
text: 'Router PON',
collapsed: false,
items: []
},
{
text: 'Tools',
collapsed: false,
items: []
},
{
text: 'SFP Resources & standard',
collapsed: false,
items: []
},
{
text: 'GPON Resources & standard',
collapsed: false,
items: []
},
{
text: 'SFP cage',
collapsed: false,
items: []
}
],

socialLinks: [
{ icon: 'github', link: 'https://github.com/hack-gpon/hack-gpon.github.io' }
],

editLink: {
pattern: 'https://github.com/hack-gpon/hack-gpon.github.io/tree/main/:path',
text: 'Edit this page on GitHub'
},

footer: {
message: 'Copyright &copy; 2022-2023. The documentation hereby found is distributed under the terms of the <a href="https://github.com/hack-gpon/hack-gpon.github.io/blob/main/LICENSE">MIT License</a>. Any external reference, link or software retains its original license and is not under the control of this website. <a href="/privacy-policy">Privacy Policy</a>.',
},

search: {
provider: 'local'
},

outline: {
level: [2, 3]
}
},

// Custom rewrites to maintain Jekyll URL structure
rewrites: {
// ONT GPON: /_ont/ont-xxx.md -> /ont-xxx (remove _ont prefix, keep filename)
'_ont/:file': ':file',

// ONT XGS-PON: /_ont_xgs/ont-xxx.md -> /xgs/ont-xxx
'_ont_xgs/:file': 'xgs/:file',

// ONT EPON: /_ont_epon/xxx.md -> /epon/xxx
'_ont_epon/:file': 'epon/:file',

// Router PON: /_router_pon/xxx.md -> /router/xxx
'_router_pon/:file': 'router/:file',

// Tools, SFP, GPON, SFP cage: keep at root level as Jekyll did
'_tools/:file': ':file',
'_sfp/:file': ':file',
'_gpon/:file': ':file',
'_sfp_cage/:file': ':file',
},

vite: {
build: {
chunkSizeWarningLimit: 1000
},
resolve: {
alias: {
'@components': '/components'
}
}
}
})
56 changes: 56 additions & 0 deletions .vitepress/theme/components/Alert.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<div :class="['alert-container', `alert-${color}`]">
<div class="alert-content">
<span v-if="icon" class="alert-icon">
<component :is="iconComponent" />
</span>
<div class="alert-body">
<strong v-if="alert">{{ alert }}: </strong>
<span v-html="content"></span>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue'

const props = defineProps<{
content: string
alert?: string
icon?: string
color?: 'red' | 'yellow' | 'green' | 'blue'
}>()

// Simple icon components
const WarningIcon = {
template: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>`
}

const InfoIcon = {
template: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>`
}

const iconComponent = computed(() => {
if (props.icon === 'svg-warning') return WarningIcon
if (props.icon === 'svg-info') return InfoIcon
return null
})
</script>

<style scoped>
.alert-content {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}

.alert-icon {
flex-shrink: 0;
margin-top: 0.125rem;
}

.alert-body {
flex: 1;
}
</style>
140 changes: 140 additions & 0 deletions .vitepress/theme/components/CigPassword.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<template>
<div>
<form id="cig-password" novalidate @submit.prevent="handleSubmit">
<div class="form-floating mb-3">
<label for="serial" class="form-label">GPON S/N in format GPONabc12345</label>
<input
v-model="serial"
type="text"
class="form-control"
placeholder="Serial Number"
name="serial"
id="serial"
required
pattern="[0-9A-Za-z]{4}[0-9A-Fa-f]{8}"
/>
<div class="invalid-feedback">Please provide a valid GPON S/N.</div>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Generate!</button>
<label for="submit" class="form-label"
>Warning: this script is hosted on a third-party server.</label
>
</div>
<div class="form-floating mb-3">
<label for="username" class="form-label">Username</label>
<input
readonly
type="text"
class="form-control"
placeholder="Username"
name="username"
id="username"
:value="username"
/>
</div>
<div class="form-floating mb-3">
<label for="result" class="form-label">Password</label>
<input
readonly
class="form-control"
type="text"
id="result"
placeholder="Result"
v-model="result"
/>
</div>
</form>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import CryptoJS from 'crypto-js'

const props = defineProps<{
username?: string
}>()

const serial = ref('')
const result = ref('')
const validated = ref(false)

function hexToBytes(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2)
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16)
}
return bytes
}

function cigpassword_gpon(
ont_serial: string,
ont_user: string,
length: number = 0,
xgspon: boolean = false
): string {
const hardcoded_key = '01030a1013051764c8061419b49d0500'
const hardcoded_seed =
'2345679abcdefghijkmnpqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ'

let ont_vendor = ont_serial.substring(0, 4).toUpperCase()
let ont_id = ont_serial.substring(4).toLowerCase()

if (xgspon) {
ont_id = ont_id.toUpperCase()
}

let formatted_serial = `${ont_vendor}${ont_id}`

let key_bytes = new Uint8Array(
hardcoded_key.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))
)
if (length > 0) {
key_bytes[15] = length
}

let formatted_serial_user = formatted_serial
if (ont_user) {
formatted_serial_user += `-${ont_user}`
}

let hmac = CryptoJS.HmacMD5(
formatted_serial_user,
CryptoJS.lib.WordArray.create(key_bytes as any)
)
let pw_md5_hmac = hexToBytes(hmac.toString(CryptoJS.enc.Hex))

let output = Array(pw_md5_hmac.length)

for (let i = 0; i < pw_md5_hmac.length; i++) {
output[i] = hardcoded_seed[pw_md5_hmac[i] % 0x36]
}

if (length > 0) {
return output.slice(0, length).join('')
} else {
return output.join('')
}
}

function handleSubmit(event: Event) {
const form = event.target as HTMLFormElement
validated.value = true

if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
} else {
result.value = cigpassword_gpon(serial.value, props.username || '')
}

form.classList.add('was-validated')
}
</script>

<style scoped>
.mb-3 {
margin-bottom: 1rem;
}
</style>
Loading