Browse Source

Start page, switched to brave and quark

main
Yiğit Çolakoğlu 4 years ago
parent
commit
2ab44613d7
64 changed files with 36143 additions and 41 deletions
  1. +14
    -0
      browser/startpage/.editorconfig
  2. +28
    -0
      browser/startpage/.env.example
  3. +66
    -0
      browser/startpage/.gitignore
  4. +21
    -0
      browser/startpage/LICENSE
  5. +1
    -0
      browser/startpage/assets/icons/favicon/pomme.svg
  6. +1
    -0
      browser/startpage/assets/icons/logo/logo.svg
  7. +31074
    -0
      browser/startpage/package-lock.json
  8. +75
    -0
      browser/startpage/package.json
  9. +115
    -0
      browser/startpage/src/binance/binance.css
  10. +122
    -0
      browser/startpage/src/binance/binance.js
  11. +25
    -0
      browser/startpage/src/binance/binance.pug
  12. +19
    -0
      browser/startpage/src/clock/clock.css
  13. +20
    -0
      browser/startpage/src/clock/clock.js
  14. +4
    -0
      browser/startpage/src/clock/clock.pug
  15. +169
    -0
      browser/startpage/src/index.css
  16. +33
    -0
      browser/startpage/src/index.js
  17. +56
    -0
      browser/startpage/src/index.pug
  18. +23
    -0
      browser/startpage/src/myrtille/myrtille.css
  19. +6
    -0
      browser/startpage/src/myrtille/myrtille.pug
  20. +81
    -0
      browser/startpage/src/openweather/openweather.css
  21. +51
    -0
      browser/startpage/src/openweather/openweather.js
  22. +148
    -0
      browser/startpage/src/openweather/openweather.pug
  23. +45
    -0
      browser/startpage/src/raisin/raisin.css
  24. +14
    -0
      browser/startpage/src/raisin/raisin.js
  25. +46
    -0
      browser/startpage/src/raisin/raisin.pug
  26. +58
    -0
      browser/startpage/src/search/search.css
  27. +27
    -0
      browser/startpage/src/search/search.js
  28. +28
    -0
      browser/startpage/src/search/search.pug
  29. +91
    -0
      browser/startpage/src/stormglass/stormglass.css
  30. +53
    -0
      browser/startpage/src/stormglass/stormglass.js
  31. +57
    -0
      browser/startpage/src/stormglass/stormglass.pug
  32. +49
    -0
      browser/startpage/src/unsplash/unsplash.css
  33. +41
    -0
      browser/startpage/src/unsplash/unsplash.js
  34. +15
    -0
      browser/startpage/src/unsplash/unsplash.pug
  35. +0
    -0
      browser/vimium.json
  36. +21
    -8
      install.sh
  37. +1
    -1
      misc/dunst/dunstrc
  38. +3
    -29
      misc/mimeapps.list
  39. +9
    -0
      root/quark.service
  40. +1
    -1
      scripts/status-bar/arch
  41. +1
    -0
      suckless/dwm/rules.h
  42. +27
    -0
      suckless/quark/LICENSE
  43. +46
    -0
      suckless/quark/Makefile
  44. +50
    -0
      suckless/quark/arg.h
  45. +40
    -0
      suckless/quark/config.h
  46. +16
    -0
      suckless/quark/config.mk
  47. +314
    -0
      suckless/quark/connection.c
  48. +32
    -0
      suckless/quark/connection.h
  49. +231
    -0
      suckless/quark/data.c
  50. +18
    -0
      suckless/quark/data.h
  51. +1044
    -0
      suckless/quark/http.c
  52. +97
    -0
      suckless/quark/http.h
  53. +364
    -0
      suckless/quark/main.c
  54. +137
    -0
      suckless/quark/quark.1
  55. +217
    -0
      suckless/quark/queue.c
  56. +33
    -0
      suckless/quark/queue.h
  57. +177
    -0
      suckless/quark/server.c
  58. +35
    -0
      suckless/quark/server.h
  59. +209
    -0
      suckless/quark/sock.c
  60. +18
    -0
      suckless/quark/sock.h
  61. +281
    -0
      suckless/quark/util.c
  62. +42
    -0
      suckless/quark/util.h
  63. +1
    -1
      xorg/xinitrc
  64. +2
    -1
      zsh/profile

+ 14
- 0
browser/startpage/.editorconfig View File

@ -0,0 +1,14 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[*.md]
max_line_length = off
trim_trailing_whitespace = false
indent_size = false

+ 28
- 0
browser/startpage/.env.example View File

@ -0,0 +1,28 @@
# ################################################# #
# OPEN WEATHER - https://openweathermap.org/current #
# ################################################# #
OPEN_WEATHER_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OPEN_WEATHER_CITY_QUERY_NAME=Leeds
OPEN_WEATHER_CITY_DISPLAY_NAME=Leeds
OPEN_WEATHER_UNITS=metric
# ################################################################ #
# UNSPLASH - https://unsplash.com/documentation#get-a-random-photo #
# ################################################################ #
UNSPLASH_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UNSPLASH_COLLECTION_ID=789734
# ########################################## #
# STORMGLASS - https://docs.stormglass.io/#/ #
# ########################################## #
STORMGLASS_API_KEY=xxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxxx
STORMGLASS_LATITUDE=46.365891
STORMGLASS_LONGITUDE=-1.478393
STORMGLASS_SPOT_NAME=bud-bud
# ###################################################################### #
# BINANCE - https://binance-docs.github.io/apidocs/spot/en/#general-info #
# ###################################################################### #
BINANCE_SYMBOLS="btc ada ltc dot bch"
BINANCE_PAIR=USDT
BINANCE_PAIR_SYMBOL=\$

+ 66
- 0
browser/startpage/.gitignore View File

@ -0,0 +1,66 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
.DS_Store
dist
.cache
development/

+ 21
- 0
browser/startpage/LICENSE View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 kikiklang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 1
- 0
browser/startpage/assets/icons/favicon/pomme.svg View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.001 512.001" fill="#9ab899"><path d="M435.827 17.45l-2.399-14.879L418.47.723C417.872.648 412.374 0 403.632 0c-28.593 0-83.096 6.534-126.859 50.298-.237.237-.462.477-.696.713V20.077h-40.155v64.508c6.908 3.385 13.626 7.21 20.077 11.507 28.38-18.898 61.71-29.168 95.368-29.168 21.67 0 43.372 4.042 64.503 12.014 5.539 2.088 10.898 4.467 16.103 7.069 8.751-36.467 4.188-66.481 3.854-68.557zM401.699 116.507c-16.587-6.256-33.518-9.428-50.331-9.428-36.411 0-70.032 14.608-95.368 40.806-25.336-26.198-58.958-40.806-95.37-40.806-16.811 0-33.745 3.172-50.33 9.428-52.531 19.818-82.66 67.606-82.66 131.113 0 112.118 60.196 203.499 119.877 244.362 18.782 13.097 41.974 20.02 67.073 20.02 13.859 0 28.031-2.21 41.41-6.426 13.378 4.215 27.55 6.426 41.41 6.426h.007c25.093 0 48.281-6.921 67.061-20.014 57.756-39.539 119.884-132.846 119.884-244.366-.002-63.509-30.13-111.297-82.663-131.115z"/></svg>

+ 1
- 0
browser/startpage/assets/icons/logo/logo.svg View File

@ -0,0 +1 @@
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path d="M80 419c166.008 10.245 293.533 7.721 318-29-30.423 61.764-76.731 87.911-136 85-95.161 19.886-148.537-6.929-182-56z" fill="#ff837a"/><path d="M398 390l-22-13c-12.307 59.889-165.176 45.087-296 42 138.782 4.742 285.167 12.825 318-29z" fill="#222835"/><path d="M383 357c-1.481 46.681-61.03 63.59-140.147 66.086C181.364 425.026 108.055 418.261 41 410c-24.997-21.429-32.603-40.78-38-73 26.168 33.097 191.17 25.869 380 20z" fill="#e89d4a"/><path d="M383 357c-100.436 4.732-200.099 5.21-294-26-7.544-5.866-11.348-17.538-14-31-23.894.885-46.171 6.035-67 15-5.866 6.213-7.419 14.261-5 24 11.542 6.744 26.853 11.778 45.12 15.47 78.511 15.869 211.634 6.959 334.88 2.53z" fill="#222835"/><path d="M74 289c1.36 17.141 5.568 32.022 15 42.761 130.838 36.218 262.796 39.202 396 5.239l19-68c-41.448 58.916-228.863 42.976-430 20z" fill="#9193b1"/><path d="M504 269c.591-10.699-24.351-20.075-58-29l-12.984 4C417.842 317.792 229.919 294.082 75 289c179.632 15.36 374.816 41.662 429-20z" fill="#222835"/><path d="M5 185C.287 212.376.854 237.615 6 261c31.581 14.826 56.116 26.72 91.343 28.759C256.991 299.002 434.939 306.96 433 243c-201.827 7.469-406.773 16.35-428-58z" fill="#9ab899"/><path d="M5 185c9.537-16.535 45.148-24.743 90-30l5 3c-9.311 13.234-13.565 25.802-15 38 164.029 77.285 396.636 51.352 425 8-96.21 74.454-348.348 56.302-455.587 17.704C23.535 210.59 4.67 197.781 5 185z" fill="#222835"/><path d="M100 158c-8.486 13.092-13.097 25.711-15 38 171.032 64.805 319.893 84.013 423 9.123L489 130c-31.894 72.626-217.505 45.744-389 28z" fill="#ff837a"/><path d="M489 130c-12.29-17.066-41.544-22.476-75-25 9.362 8.33 16.317 16.228 17 23 5.709 35.983-77.456 40.014-141.484 46 90.327 4.851 175.64 5.596 199.484-44z" fill="#222835"/><path d="M414 105c-15.95-28.885-52.291-46.565-100-58-33 2.599-66-3.171-99-15-97.48 3.085-144.513 43.341-172 98 41.567 28.826 111.32 33.949 171.398 38.398C334.527 177.293 456.862 163.129 414 105z" fill="#e89d4a"/><path d="M269.516 3c-12.112 22.185-21.194 45.38-26 70l15-4c7.172-20.947 11.881-43.929 31-55V9c-5.504-1.745-9.741-4.849-13-9l-7 3z" fill="#222835"/></svg>

+ 31074
- 0
browser/startpage/package-lock.json
File diff suppressed because it is too large
View File


+ 75
- 0
browser/startpage/package.json View File

@ -0,0 +1,75 @@
{
"name": "pomme-page",
"version": "0.2.0",
"description": "Big buttons with easy click startpage for a browser",
"main": "src/index.pug",
"author": "kikiklang",
"license": "MIT",
"scripts": {
"dev": "npm run clean && npx parcel src/index.pug --out-dir development -p 3000",
"build": "npm run clean && npx parcel build src/index.pug --no-cache",
"serve": "npx serve dist",
"clean": "rimraf ./development && rimraf -rf ./.cache && rimraf -rf ./dist",
"prettier": "prettier --write 'src/**/*.pug'",
"stylelint": "stylelint --fix './**/*.css'",
"xo": "xo --env=browser --fix",
"format": "npm run clean && npm run prettier && npm run stylelint && npm run xo"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/preset-env": "^7.12.7",
"@prettier/plugin-pug": "^1.13.3",
"autoprefixer": "^9.8.6",
"husky": "^4.3.0",
"parcel-bundler": "^1.12.4",
"prettier": "^2.2.1",
"pug": "^3.0.0",
"rimraf": "^3.0.2",
"stylelint": "^13.7.2",
"stylelint-color-format": "^1.1.0",
"stylelint-config-rational-order": "^0.0.4",
"stylelint-config-standard": "^20.0.0",
"stylelint-group-selectors": "^1.0.8",
"xo": "^0.37.1"
},
"browserslist": [
"since 2017-06"
],
"prettier": {
"printWidth": 130,
"singleQuote": true
},
"postcss": {
"plugins": {
"autoprefixer": {
"grid": true
}
}
},
"stylelint": {
"plugins": [
"stylelint-color-format",
"stylelint-group-selectors"
],
"extends": [
"stylelint-config-standard",
"stylelint-config-rational-order"
],
"rules": {
"selector-type-no-unknown": null,
"plugin/stylelint-group-selectors": true,
"color-format/format": {
"format": "hsl"
}
}
},
"xo": {
"semicolon": false,
"space": true
},
"husky": {
"hooks": {
"pre-commit": "npm run format"
}
}
}

+ 115
- 0
browser/startpage/src/binance/binance.css View File

@ -0,0 +1,115 @@
/************** CRYPTO **************/
pp-binance {
display: none;
flex-direction: column;
grid-column: span 2;
grid-row: span 6;
padding: 0 var(--spacing-2);
background-color: var(--module-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
pp-binance-selector {
display: flex;
justify-content: space-between;
align-items: center;
height: var(--spacing-4);
}
.binance-selector-button {
padding: 0;
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
background: none;
border: none;
outline: inherit;
cursor: pointer;
}
.binance-selector-button[data-state='active'] {
color: var(--main);
}
.binance-selector-button[data-state='inactive'] {
color: var(--main-light);
}
pp-binance-chart {
display: flex;
flex: 1;
align-items: center;
transform: scaleY(-1);
}
pp-binance-chart-label {
color: var(--main-light);
font-weight: var(--font-weight-bold);
font-size: var(--scale-0);
text-align: right;
}
pp-binance-footer {
display: flex;
justify-content: space-between;
align-items: center;
height: var(--spacing-5);
}
pp-binance-current {
text-align: right;
}
.binance-difference-label,
.binance-current-label {
padding-top: var(--spacing-1);
color: var(--main-light);
font-weight: var(--font-weight-bold);
font-size: var(--scale-0);
}
.binance-difference-value,
.binance-current-value {
color: var(--main);
font-weight: var(--font-weight-bold);
font-size: var(--scale-3);
}
.binance-money-unit {
position: relative;
top: -1px;
color: var(--main-light);
font-size: var(--scale-0);
}
pp-binance-loader-container {
display: flex;
grid-column: span 2;
grid-row: span 6;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--pomme-background);
border-radius: 10px;
}
pp-binance-error-container {
display: none;
flex-direction: column;
grid-column: span 2;
grid-row: span 6;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--search-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
p.binance-error-code {
margin-top: var(--spacing-0);
color: var(--search-background);
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
}

+ 122
- 0
browser/startpage/src/binance/binance.js View File

@ -0,0 +1,122 @@
// //////// CRYPTO //////// //
let cryptoPicked = process.env.BINANCE_SYMBOLS.split(' ')[0].toUpperCase()
const cryptoButtonsContainer = document.querySelector('pp-binance-selector')
const binanceLoaderContainer = document.querySelector('pp-binance-loader-container')
function handleBinanceApiError(historicalDataResponse, currentDataResponse) {
const binanceErrorContainer = document.querySelector('pp-binance-error-container')
const binanceErrorCode = document.querySelector('.binance-error-code')
if (!historicalDataResponse.status <= 200 || historicalDataResponse.status >= 300) {
binanceErrorCode.innerHTML = historicalDataResponse.status
}
if (!currentDataResponse.status <= 200 || currentDataResponse.status >= 300) {
binanceErrorCode.innerHTML = currentDataResponse.status
}
binanceErrorCode.innerHTML = historicalDataResponse.status
binanceLoaderContainer.style.display = 'none'
binanceErrorContainer.style.display = 'flex'
}
function generateButtons() {
const symbolsList = process.env.BINANCE_SYMBOLS.split(' ')
symbolsList.forEach(symbol => {
const newButton = document.createElement('button')
cryptoButtonsContainer.append(newButton)
newButton.className = 'binance-selector-button'
newButton.dataset.state = 'inactive'
newButton.innerHTML = symbol
})
cryptoButtonsContainer.firstChild.dataset.state = 'active'
}
function generateChartLine(data) {
const svg = document.querySelector('.binance-chart-svg')
const svgContainerWidth = document.querySelector('pp-binance-chart').offsetWidth
const svgContainerHeight = 130
const maxCryptoValue = Math.max(...data)
const minCryptoValue = Math.min(...data)
const xAxisPixelvalues = index => (svgContainerWidth / (data.length - 1)) * index
const yAxisPixelValues = value => Math.round(((value - minCryptoValue) * svgContainerHeight) / (maxCryptoValue - minCryptoValue))
const pixelCoordinatesArray = data.map((value, index) => [xAxisPixelvalues(index), yAxisPixelValues(value)])
const svgPath = pixelCoordinatesArray.map(pixel => pixel[0] === 0 ? `M ${pixel[0]},${pixel[1]}` : `L ${pixel[0]} ${pixel[1]}`).join(' ')
const svgCode = `
<defs>
<linearGradient id="gradient" x1="0%" x2="100%">
<stop offset="0%" stop-color="var(--module-background)" />
<stop offset="20%" stop-color="var(--main)" />
<stop offset="80%" stop-color="var(--main)" />
<stop offset="100%" stop-color="var(--module-background)" />
</linearGradient>
</defs>
<path d="${svgPath}" transform="translate(0, 10)" stroke="url(#gradient)" fill="none" stroke-width="7" stroke-linejoin="round" />
`
svg.innerHTML = svgCode
}
function completeFooterValues(data) {
const differenceValue = document.querySelector('.binance-difference-value')
const currentValue = document.querySelector('.binance-current-value')
const pairSymbol = process.env.BINANCE_PAIR_SYMBOL
differenceValue.innerHTML =
data.priceChange > 0 ?
`${Math.round(data.priceChange)}<span class="binance-money-unit">${pairSymbol}</span>` :
`${Math.round(data.priceChange)}<span class="binance-money-unit">${pairSymbol}</span>`
currentValue.innerHTML = `${Math.round(data.lastPrice)}<span class="binance-money-unit">${pairSymbol}</span>`
}
function displayBinanceData(historicalData, currentData) {
const filteredHistoricalData = historicalData.map(value => Number(value[1]))
const binanceLoader = document.querySelector('pp-binance-loader-container')
const binanceContainer = document.querySelector('pp-binance')
binanceLoader.style.display = 'none'
binanceContainer.style.display = 'flex'
generateChartLine(filteredHistoricalData)
completeFooterValues(currentData)
}
async function getBinancedata() {
const url = 'https://api.binance.com'
const pair = process.env.BINANCE_PAIR
const klinesPath = '/api/v3/klines'
const klinesParameters = `?symbol=${cryptoPicked}${pair}&interval=1d&limit=7`
const tickerPath = '/api/v3/ticker/24hr'
const tickerParameters = `?symbol=${cryptoPicked}${pair}`
const [historicalDataResponse, currentDataResponse] = await Promise.all([
fetch(`${url}${klinesPath}${klinesParameters}`),
fetch(`${url}${tickerPath}${tickerParameters}`)
])
if (historicalDataResponse.ok && currentDataResponse.ok) {
const [historicalDataJsonResponse, currentDataJsonResponse] = await Promise.all([
historicalDataResponse.json(),
currentDataResponse.json()
])
return displayBinanceData(historicalDataJsonResponse, currentDataJsonResponse)
}
return handleBinanceApiError(historicalDataResponse, currentDataResponse)
}
function toggleButtons(event) {
const buttonsList = document.querySelectorAll('.binance-selector-button')
buttonsList.forEach(button => {
button.dataset.state = 'inactive'
})
event.target.dataset.state = 'active'
cryptoPicked = event.target.innerHTML.toUpperCase()
getBinancedata()
}
export {generateButtons, cryptoButtonsContainer, getBinancedata, toggleButtons}

+ 25
- 0
browser/startpage/src/binance/binance.pug View File

@ -0,0 +1,25 @@
// //////// CRYPTO //////// //
pp-binance
pp-binance-selector
pp-binance-chart
svg.binance-chart-svg(version='1.1', xmlns='http://www.w3.org/2000/svg')
pp-binance-chart-label last week
pp-binance-footer
pp-binance-difference
p.binance-difference-label last 24h
p.binance-difference-value
pp-binance-current
p.binance-current-label curr. value
p.binance-current-value
pp-binance-loader-container
pp-loader
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-binance-error-container
p.error-notification API error
p.binance-error-code

+ 19
- 0
browser/startpage/src/clock/clock.css View File

@ -0,0 +1,19 @@
/************** CLOCK **************/
pp-clock {
display: flex;
grid-column: span 2;
grid-row: span 2;
justify-content: center;
align-items: center;
background-color: var(--module-background);
border-radius: 10px;
animation: fadein-page 250ms ease-out normal backwards;
animation-delay: 200ms;
}
.pp-time {
color: var(--main);
font-weight: var(--font-weight-bold);
font-size: var(--scale-3);
}

+ 20
- 0
browser/startpage/src/clock/clock.js View File

@ -0,0 +1,20 @@
// //////// CLOCK //////// //
function displayClock() {
const days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
const date = new Date()
const h = date.getHours()
const m = date.getMinutes()
const s = date.getSeconds()
const day = days[date.getDay()]
const hour = h < 10 ? `0${h}` : h
const minute = m < 10 ? `0${m}` : m
const second = s < 10 ? `0${s}` : s
document.querySelector('.pp-time').innerHTML = `${day} : ${hour} : ${minute} : ${second}`
setTimeout(displayClock, 1000)
}
export default displayClock

+ 4
- 0
browser/startpage/src/clock/clock.pug View File

@ -0,0 +1,4 @@
// //////// CLOCK //////// //
pp-clock
p.pp-time

+ 169
- 0
browser/startpage/src/index.css View File

@ -0,0 +1,169 @@
/******* RESET *******/
html,
body,
p,
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
}
button,
input,
select,
textarea {
margin: 0;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
/************** VARIABLES **************/
:root {
/* colors */
--main: hsl(220, 21%, 17%);
--main-light: hsl(30, 35%, 40%);
--module-background: hsl(31, 77%, 60%);
--search-background: hsl(4, 100%, 74%);
--pomme-background: hsl(118, 18%, 66%);
--myrtille-background: hsl(235, 17%, 63%);
/* font-family */
--font-family-sans: system-ui, -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, ubuntu, 'Helvetica Neue', sans-serif;
/* font Modular scale */
--scale-000: 0.75rem; /* 12px */
--scale-00: 0.875rem; /* 14px */
--scale-0: 1rem; /* 16px */
--scale-1: 1.125rem; /* 18px */
--scale-2: 1.25rem; /* 20px */
--scale-3: 1.5rem; /* 24px */
--scale-4: 1.875rem; /* 30px */
--scale-5: 2.25rem; /* 36px */
/* font weights */
--font-weight-regular: 400;
--font-weight-bold: 700;
/* sizing property -> margin, padding, height */
--spacing-0000: 4px;
--spacing-000: 8px;
--spacing-00: 12px;
--spacing-0: 16px;
--spacing-1: 20px;
--spacing-2: 32px;
--spacing-3: 48px;
--spacing-4: 64px;
--spacing-5: 96px;
/* Widths applied as max-width */
--width-00: 120px;
/* Grid gaps */
--gap-00: 12px;
--gap-0: 16px;
--gap-1: 24px;
}
/************** GLOBAL STYLES **************/
html {
background-color: var(--main);
}
body {
padding: var(--spacing-4);
font-family: var(--font-family-sans);
}
grid {
display: grid;
grid-auto-flow: dense;
grid-auto-rows: var(--spacing-2);
grid-gap: var(--gap-1);
grid-template-columns: repeat(auto-fit, minmax(var(--width-00), 1fr));
}
pomme {
grid-row: span 2;
background-color: var(--pomme-background);
border-radius: 10px;
animation: fadein-page 200ms ease-out normal backwards;
}
pp-loader {
display: grid;
grid-gap: var(--gap-00);
grid-template-areas:
'pp-loader-dot pp-loader-dot'
'pp-loader-dot pp-loader-dot';
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
pp-loader-dot {
width: var(--spacing-1);
height: var(--spacing-1);
background-color: var(--main);
border-radius: 50%;
animation: loader-animation 1s linear 1s infinite alternate;
}
pp-loader-dot:nth-child(1) {
animation-delay: 0s;
}
pp-loader-dot:nth-child(2) {
animation-delay: -0.2s;
}
pp-loader-dot:nth-child(3) {
animation-delay: -0.4s;
}
pp-loader-dot:nth-child(4) {
animation-delay: -0.6s;
}
.error-notification {
color: var(--search-background);
font-weight: var(--font-weight-regular);
font-size: var(--scale-2);
}
/******* ANIMATION *******/
@keyframes module-display {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes loader-animation {
100% { background-color: var(--module-background); }
}
@keyframes fadein-page {
0% { transform: scale(0); }
70% { transform: scale(1.05); }
100% { transform: scale(1); }
}
/******* IMPORTS *******/
@import './myrtille/myrtille.css';
@import './raisin/raisin.css';
@import './clock/clock.css';
@import './search/search.css';
@import './binance/binance.css';
@import './openweather/openweather.css';
@import './unsplash/unsplash.css';
@import './stormglass/stormglass.css';

+ 33
- 0
browser/startpage/src/index.js View File

@ -0,0 +1,33 @@
// //////// INDEX //////// //
import truncateLinkName from './raisin/raisin.js'
import displayClock from './clock/clock.js'
import {buttonsContainer, searchContainer, toggleEngineIcons, sendSearch} from './search/search.js'
import {generateButtons, cryptoButtonsContainer, getBinancedata, toggleButtons} from './binance/binance.js'
import getOpenWeatherData from './openweather/openweather.js'
import getUnsplashData from './unsplash/unsplash.js'
import getStormglassData from './stormglass/stormglass.js'
// Raisin
truncateLinkName()
// Clock
displayClock()
// Search
buttonsContainer.addEventListener('click', toggleEngineIcons)
searchContainer.addEventListener('keypress', sendSearch)
// Binance
generateButtons()
getBinancedata()
cryptoButtonsContainer.addEventListener('click', toggleButtons)
// Openweather
getOpenWeatherData()
// Unsplash
getUnsplashData()
// Stormglass
getStormglassData()

+ 56
- 0
browser/startpage/src/index.pug View File

@ -0,0 +1,56 @@
include myrtille/myrtille
include raisin/raisin
doctype html
head
meta(charset='UTF-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
meta(name='robots', content='noindex')
link(href='./index.css', rel='stylesheet', type='text/css')
link(rel='shortcut icon', href='../assets/icons/logo/logo.svg')
script(type='module', src='./index.js')
title Pomme Page
grid
include clock/clock
pomme
include search/search
pomme
+myrtille('reddit.com/', '0 0 24 24', 'M14.238 15.348a.215.215 0 010 .306c-.465.462-1.194.687-2.231.687l-.008-.002-.008.002c-1.036 0-1.766-.225-2.231-.688a.214.214 0 010-.305.219.219 0 01.307 0c.379.377 1.008.561 1.924.561l.008.002.008-.002c.915 0 1.544-.184 1.924-.561a.219.219 0 01.307 0zm-3.44-2.418a.922.922 0 00-1.845 0c0 .506.414.918.923.918a.92.92 0 00.922-.918zM24 12c0 6.627-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0s12 5.373 12 12zm-5-.129a1.548 1.548 0 00-2.624-1.108c-1.056-.695-2.485-1.137-4.066-1.194l.865-2.724 2.343.549-.003.034c0 .696.569 1.262 1.268 1.262.699 0 1.267-.566 1.267-1.262a1.266 1.266 0 00-2.446-.458l-2.525-.592a.216.216 0 00-.257.145l-.965 3.038c-1.656.02-3.155.466-4.258 1.181A1.546 1.546 0 005 11.871c0 .566.311 1.056.768 1.325-.03.164-.05.331-.05.5 0 2.281 2.805 4.137 6.253 4.137s6.253-1.856 6.253-4.137c0-.16-.017-.317-.044-.472.486-.261.82-.766.82-1.353zm-4.872.141a.921.921 0 00-.922.919.921.921 0 001.844 0 .921.921 0 00-.922-.919z')
+myrtille('github.com/', '0 0 64 64', "M22.8 62.664C9.63 58.7 0 46.4 0 32 0 14.3 14.3 0 32 0s32 14.3 32 32c0 14.3-9.4 26.4-22.3 30.5-.84-.483-1.408-1.2-1.6-2.5-.024-2.5-.179-13.6-1-13.996L39 46c8.666-2.2 15-8.535 15-16 0-3.9-1.1-8.047-3.9-10.966L50 19c1.01-3.3.496-6.2-1-9-3.4-.029-6.3 1.4-8.9 3.942L40 14c-2.4-1.553-13.4-1.4-15.9-.017L24 14c-1.1-2-7-4.6-9-4-2.1 2.4-2.6 5.3-1 8.958L14 19c-3.1 3.1-3.7 7.6-4 11-.4 7.4 8.4 16 15.9 16.001A.157.157 0 0126 46l-.086.001c-.498.1-.961 2.7-.914 3.9-4.8 2.7-9.2-1-11-4-.958-1.6-6-2.6-6-1 .039 1.2 3.1 2.7 4 5 1.4 3.8 9.3 8.8 13 5v5c-.3 1.3-1 2.2-2.1 2.664z")
+myrtille('youtube.com/', '0 0 1024 1024', "M512 0c282.58 0 512 229.42 512 512 0 282.58-229.42 512-512 512C229.42 1024 0 794.58 0 512 0 229.42 229.42 0 512 0zm270 422.988C782 370.563 739.437 328 687.012 328c0 0-116.66-4-175.012-4-58.671 0-177.012 4-177.012 4C282.563 328 240 370.563 240 422.988c-2.846 35.406-3.728 73.675-3.728 106.012 0 29.364 1.527 58.716 3.728 88.012C240 669.437 282.563 712 334.988 712c0 0 118.341 4 177.012 4 58.352 0 175.012-4 175.012-4C739.437 712 782 669.437 782 617.012c0 0 2-72.675 2-105.012 0-29.678-2-89.012-2-89.012zM461 444l147 86-146.012 84L461 444z")
+myrtille('media.yigitcolakoglu.com/', '0 0 512 512', "M256 201.6c-20.4 0-86.2 119.3-76.2 139.4s142.5 19.9 152.4 0-55.7-139.4-76.2-139.4z M256 23.3c-61.6 0-259.8 359.4-229.6 420.1s429.3 60 459.2 0S317.6 23.3 256 23.3zm150.5 367.5c-19.6 39.3-281.1 39.8-300.9 0S215.7 115.5 256 115.5s170.1 235.9 150.5 275.3z")
include binance/binance
include openweather/openweather
+raisin('dev', dev)
include unsplash/unsplash
+raisin('hack', hack)
+myrtille('vault.yigitcolakoglu.com/', '0 0 64 64', "M32 0c17.6 0 32 14.3 32 32S49.6 64 32 64 0 49.6 0 32 14.3 0 32 0zM14 17.539c0-.673.2-1.3.7-1.795A2.5 2.5 0 0116.539 15h30.868A2.59 2.5 0 0150 17.594V39c-2.8 9.1-9.1 14.5-17.4 17.7-.347.135-.73.1-1.078.008C23.4 53.7 17.3 48.2 14 39V17.539zM32 20h13v19c-1.3 5.022-6.3 9.1-13 13V20z")
+myrtille('twitter.com/', '0 0 64 64', "M6 9c-2.5 6.1-2.8 11.8 3 17-2.049.038-3.5-.409-5-1 .1 6.1 3.2 10.2 10 12-2.069.767-4.067.743-6 0 2.5 5.7 6.2 9.3 12 9-5.1 4.1-11.1 5.95-18 6 17.1 9.7 34.4 4.9 43-4 7.8-8.2 14.74-21.2 12-29 .9.246 6.305-5.8 6-6a57.81 57.81 0 01-7 2c2.5-1.9 4.1-4.3 5-7a30.6 30.6 0 01-8 3c-3.5-4-8.6-4.4-14-3-7.5 2-7.9 14.1-7 14 .0 2.8-27.9-6.3-26-13z")
pomme
+myrtille('drive.yigitcolakoglu.com/', '0 0 64 64', "m32.028095 17.446884c-6.630378 0-12.249342 4.49517-13.99122 10.563651-1.517121-3.258998-4.77612-5.506585-8.597016-5.506585-5.169446 0-9.439859 4.270413-9.439859 9.496049 0 5.225637 4.270413 9.49605 9.496049 9.49605 3.764706 0 7.079895-2.247586 8.597015-5.506585 1.685689 6.068481 7.304653 10.563652 13.935031 10.563652 6.574188 0 12.193152-4.438981 13.99122-10.451272 1.517121 3.146619 4.77612 5.338015 8.484636 5.338015 5.225637 0 9.496049-4.270412 9.496049-9.496049s-4.270412-9.43986-9.496049-9.43986c-3.708516 0-6.967515 2.191396-8.484636 5.338016-1.798068-5.956101-7.360843-10.395082-13.99122-10.395082zm0 5.562773c5.000878 0 8.990343 3.989465 8.990343 8.990342 0 5.000879-3.989465 8.990343-8.990343 8.990343s-8.990343-3.989464-8.990343-8.990343c0-5.000875 3.989465-8.99034 8.990343-8.990342zm-22.532046 5.057067c2.191397 0 3.933275 1.74188 3.933275 3.933275 0 2.191396-1.741878 3.933276-3.933275 3.933276-2.191396 0-3.933275-1.74188-3.933275-3.933276 0-2.191395 1.741879-3.933275 3.933275-3.933275zm45.007902 0c2.191396 0 3.933275 1.74188 3.933275 3.933275 0 2.191396-1.741879 3.933276-3.933275 3.933276s-3.933275-1.74188-3.933275-3.933276c.05619-2.191395 1.741879-3.933275 3.933275-3.933275z")
+myrtille('app.daily.dev/', '0 -10 48 48', "M39.8158775,12.9909755 L34.6975003,7.86188232 L37.2553552,2.73457106 L45.5717179,11.0683452 C46.6313388,12.1301846 46.6313388,13.8517664 45.5717179,14.9136059 L35.3358527,25.1709013 C34.2762317,26.2327407 32.5582467,26.2327407 31.4986258,25.1709013 C30.4390048,24.1090619 30.4390048,22.38748 31.4986258,21.3256406 L39.8158775,12.9909755 Z M31.500533,0.800996807 C32.560154,-0.260842615 34.2785836,-0.260397129 35.3382045,0.801442293 L37.2572625,2.72451813 L14.8678078,25.1608484 C13.8081869,26.2226878 12.0897573,26.2222423 11.0301363,25.1604029 L9.11107833,23.237327 L31.500533,0.800996807 Z M21.9047984,7.85272036 L18.0666824,11.698872 L12.9483052,6.56977883 L6.55055609,12.9809226 L11.6689332,18.1100158 L9.11107833,23.237327 L0.794715716,14.9035529 C-0.264905239,13.8417135 -0.264905239,12.1201317 0.794715716,11.0582922 L11.0301363,0.801442293 C12.0897573,-0.260397129 13.8081869,-0.260842615 14.8678078,0.800996807 L21.9047984,7.85272036 Z")
pomme
+myrtille('git.yigitcolakoglu.com/', '0 0 64 64', "m64 17.5c-.1-4.1-1.4-5-2.4-5.1-10.4.6-16.6.8-22 .9v.3.3 11.6l-1.6-.9v-10.7-.3-.3c-5.8 0-10.8-.3-19.9-.8l-1.8-.1c-.5 0-1.2-.1-1.9-.1-.9-.1-2-.1-3.1-.2-3.1 0-6.1 1.3-8.2 3.4-2.2 2.2-3.2 5.4-3.1 9 .2 6 2.8 10.3 7.5 12.8 2.8 1.5 6.4 2.3 10.6 2.5.8 2.8 6.5 11.4 10.9 11.9h19c2.3-.2 6.9-2.2 11.5-13.6 2.8-6.8 4.6-15.3 4.5-20.6zm-47.7 16.8c-5.3-.7-10.1-2.5-11-9.5-.3-2.1.2-4 1.4-5.3s3.1-2 5.6-2h.2c.6 6.9 1.7 11 3.8 16.8zm30.5-4.5c1.4.7 2 2.4 1.3 3.7l-5.3 10.9c-.7 1.4-2.4 2-3.7 1.3l-10.9-5.3c-1.4-.7-2-2.4-1.3-3.7l5.3-10.9c.7-1.4 2.4-2 3.7-1.3l2 1-1.4 2.9c-.2 0-.4 0-.6.1-.9.3-1.4 1.4-1.1 2.3.1.2.2.4.3.5l-2.4 5c-.2 0-.4 0-.6.1-.9.3-1.4 1.4-1.1 2.3s1.4 1.4 2.3 1.1 1.4-1.4 1.1-2.3c-.1-.3-.2-.5-.4-.7l2.4-4.9c.3 0 .5 0 .8-.1l.6-.3c.1 0 .2.1.3.1 1.8.9 2.9 1.4 3.1 2 .3.8-.5 2.4-2 5.4v.1c-.2 0-.4 0-.7.1-.9.3-1.4 1.4-1.1 2.3s1.4 1.4 2.3 1.1 1.4-1.4 1.1-2.3c-.1-.2-.2-.4-.4-.6 0 0 0 0 0-.1 1.8-3.6 2.5-5.2 2.1-6.5-.4-1.1-1.6-1.7-3.8-2.8-.1 0-.2-.1-.3-.1 0-.2 0-.5-.1-.7s-.2-.4-.4-.6l1.1-2.9z")
+myrtille('protonmail.com/', '0 0 64 64', "M8 64V41l21.1 13.2a5.4 5.4 0 005.7 0L56 41v23H8zm0-39C8.3 11.3 18.7 0 32 0c13.43 0 23.9 10.9 24 24.836V35L36.4 48.874A7.8 7.8 0 0127.5 49L8 36V25zm10.006-4C18.218 14.7 24.2 9.6 32 9.68c7.865 0 14 4.8 14 11.32v8H18v-8h.006z")

+ 23
- 0
browser/startpage/src/myrtille/myrtille.css View File

@ -0,0 +1,23 @@
/************** MYRTILLE **************/
.myrtille-link {
display: flex;
grid-row: span 2;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: var(--myrtille-background);
border-radius: 10px;
transition: 100ms ease-in-out;
animation: fadein-page 300ms ease-out normal backwards;
}
.myrtille-link:hover {
transform: rotate(5deg);
}
.myrtille-link svg {
width: 50%;
fill: var(--main);
}

+ 6
- 0
browser/startpage/src/myrtille/myrtille.pug View File

@ -0,0 +1,6 @@
// //////// MYRTILLE //////// //
mixin myrtille(domain, viewbox, svgPath)
a.myrtille-link(href="https://" + domain, target='_blank', rel='noopener noreferrer')
svg(xmlns='http://www.w3.org/2000/svg', fill-rule='evenodd', viewBox=viewbox)
path(d=svgPath)

+ 81
- 0
browser/startpage/src/openweather/openweather.css View File

@ -0,0 +1,81 @@
/************** openweather **************/
pp-openweather {
display: none;
flex-direction: column;
grid-column: span 1;
grid-row: span 4;
align-items: center;
padding: var(--spacing-0000) var(--spacing-0);
background-color: var(--module-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
pp-openweather-icons {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
}
pp-openweather-icons .pp-openweather-icon[data-state='hide'] {
display: none;
}
pp-openweather-city,
pp-openweather-temp,
pp-openweather-humid {
display: flex;
justify-content: space-between;
align-items: baseline;
width: 100%;
height: var(--spacing-2);
}
.city-label,
.temp-label,
.humid-label {
color: var(--main-light);
font-weight: var(--font-weight-bold);
font-size: var(--scale-0);
}
.city-value,
.temp-value,
.humid-value {
color: var(--main);
font-weight: var(--font-weight-bold);
font-size: var(--scale-1);
}
pp-openweather-loader-container {
display: flex;
grid-column: span 1;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--pomme-background);
border-radius: 10px;
}
pp-openweather-error-container {
display: none;
flex-direction: column;
grid-column: span 1;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--search-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
p.openweather-error-code {
margin-top: var(--spacing-0);
color: var(--search-background);
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
}

+ 51
- 0
browser/startpage/src/openweather/openweather.js View File

@ -0,0 +1,51 @@
// //////// WEATHER //////// //
const openWeatherLoaderContainer = document.querySelector('pp-openweather-loader-container')
function handleopenWeatherApiError(response) {
const openWeatherErrorContainer = document.querySelector('pp-openweather-error-container')
const openWeatherErrorCode = document.querySelector('.openweather-error-code')
openWeatherErrorCode.innerHTML = response.status
openWeatherLoaderContainer.style.display = 'none'
openWeatherErrorContainer.style.display = 'flex'
}
function displayOpenWeatherData(data) {
const openWeatherLoader = document.querySelector('pp-openweather-loader-container')
const openWeatherContainer = document.querySelector('pp-openweather')
const temporary = document.querySelector('.temp-value')
const humid = document.querySelector('.humid-value')
const icons = [...document.querySelectorAll('.pp-openweather-icon')]
const cityName = document.querySelector('.city-value')
icons.forEach(icon => {
if (icon.getAttribute('data-type').includes(data.weather[0].main.toLowerCase())) {
icon.dataset.state = 'show'
} else {
icon.dataset.state = 'hide'
}
})
cityName.innerHTML = process.env.OPEN_WEATHER_CITY_DISPLAY_NAME || process.env.OPEN_WEATHER_CITY_QUERY_NAME
temporary.innerHTML = data.main.temp > 0 && data.main.temp < 10 ? `0${Math.round(data.main.temp)}°` : `${Math.round(data.main.temp)}°`
humid.innerHTML = `${data.main.humidity}%`
openWeatherLoader.style.display = 'none'
openWeatherContainer.style.display = 'flex'
}
async function getOpenWeatherData() {
const apiKey = process.env.OPEN_WEATHER_API_KEY
const url = 'https://api.openweathermap.org/data/2.5/weather'
const city = process.env.OPEN_WEATHER_CITY_QUERY_NAME
const units = process.env.OPEN_WEATHER_UNITS
const response = await fetch(`${url}?q=${city}&units=${units}&APPID=${apiKey}`)
if (response.ok) {
const jsonResponse = await response.json()
return displayOpenWeatherData(jsonResponse)
}
return handleopenWeatherApiError(response)
}
export default getOpenWeatherData

+ 148
- 0
browser/startpage/src/openweather/openweather.pug View File

@ -0,0 +1,148 @@
// //////// openweather //////// //
pp-openweather
pp-openweather-icons
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='clear',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
circle(cx='12', cy='12', r='5')
path(d='M12 1v2')
path(d='M12 21v2')
path(d='M4.22 4.22l1.42 1.42')
path(d='M18.36 18.36l1.42 1.42')
path(d='M1 12h2')
path(d='M21 12h2')
path(d='M4.22 19.78l1.42-1.42')
path(d='M18.36 5.64l1.42-1.42')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='clouds',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M18 10h-1.26A8 8 0 109 20h9a5 5 0 000-10z')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='drizzle',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M8 19v2')
path(d='M8 13v2')
path(d='M16 19v2')
path(d='M16 13v2')
path(d='M12 21v2')
path(d='M12 15v2')
path(d='M20 16.58A5 5 0 0018 7h-1.26A8 8 0 104 15.25')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='rain',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M16 13v8')
path(d='M8 13v8')
path(d='M12 15v8')
path(d='M20 16.58A5 5 0 0018 7h-1.26A8 8 0 104 15.25')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='snow',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M20 17.58A5 5 0 0018 8h-1.26A8 8 0 104 16.25')
path(d='M8 16h.01')
path(d='M8 20h.01')
path(d='M12 18h.01')
path(d='M12 22h.01')
path(d='M16 16h.01')
path(d='M16 20h.01')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='thunderstorm',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M19 16.9A5 5 0 0018 7h-1.26a8 8 0 10-11.62 9')
path(d='M13 11l-4 6h6l-4 6')
svg.pp-openweather-icon(
xmlns='http://www.w3.org/2000/svg',
data-state='hide',
data-type='fog',
viewBox='0 0 24 24',
width='64',
fill='none',
stroke='var(--main)',
stroke-width='2',
stroke-linecap='round',
stroke-linejoin='round'
)
path(
d='M47.07 96.74c1.83 0 3.32 1.65 3.32 3.68 0 2.03-1.48 3.68-3.32 3.68h-9.35c-1.83 0-3.32-1.65-3.32-3.68 0-2.03 1.48-3.68 3.32-3.68h9.35zM14.3 67.94a3.678 3.678 0 01-4.72 5.64c-1.68-1.4-3.15-2.99-4.4-4.72C1.84 64.25.04 58.63 0 53.03c-.04-5.66 1.72-11.29 5.52-15.85 1.23-1.48 2.68-2.84 4.34-4.04 1.93-1.4 4.14-2.58 6.64-3.55 1.72-.67 3.56-1.23 5.5-1.68 2.2-8.74 6.89-15.47 12.92-20.14C40.56 3.4 47.35.85 54.34.18c6.96-.67 14.12.51 20.55 3.6C81.91 7.15 88.03 12.76 92 20.65c1.6-.25 3.2-.38 4.79-.36 6.72.05 13.2 2.45 18.3 7.95 1.07 1.15 2.08 2.45 3.02 3.9 3.2 4.92 4.84 11.49 4.77 17.92-.07 6.31-1.77 12.59-5.25 17.22a3.67 3.67 0 11-5.87-4.41c2.5-3.33 3.73-8.04 3.78-12.87.06-5.07-1.18-10.16-3.59-13.86-.69-1.07-1.45-2.03-2.25-2.89-3.61-3.89-8.19-5.59-12.95-5.62-3.46-.02-7.02.81-10.41 2.31-.75.37-1.5.77-2.25 1.21-2.25 1.32-4.47 2.93-6.74 4.78l-4.84-5.54c1.67-1.55 3.48-2.96 5.4-4.21 1.53-1 3.13-1.88 4.77-2.65.66-.33 1.33-.64 2-.93-3.19-5.65-7.78-9.7-12.98-12.2-5.2-2.49-11.02-3.45-16.69-2.9-5.63.54-11.1 2.59-15.62 6.1-5.23 4.06-9.2 10.11-10.73 18.14l-.48 2.51-2.5.44c-2.45.43-4.64 1.02-6.56 1.77-1.86.72-3.52 1.61-4.97 2.66-1.16.84-2.16 1.78-3.01 2.8-2.63 3.15-3.85 7.1-3.82 11.1a20.07 20.07 0 003.79 11.53 20.07 20.07 0 003.19 3.39zm17.97 4.09c-1.49 0-2.69-1.65-2.69-3.68 0-2.03 1.2-3.68 2.69-3.68h66.56c1.49 0 2.69 1.65 2.69 3.68 0 2.03-1.2 3.68-2.69 3.68H32.27zM20.38 87.54c-1.83 0-3.32-1.65-3.32-3.68s1.48-3.68 3.32-3.68H72.9c1.83 0 3.32 1.65 3.32 3.68s-1.48 3.68-3.32 3.68H20.38zm69.02 0c-1.83 0-3.32-1.65-3.32-3.68s1.48-3.68 3.32-3.68h11.82c1.83 0 3.32 1.65 3.32 3.68s-1.48 3.68-3.32 3.68H89.4zm19.87 9.49c1.82.01 3.3 1.66 3.29 3.68-.01 2.03-1.49 3.66-3.32 3.66l-46.97-.27c-1.82-.01-3.3-1.66-3.29-3.68.01-2.03 1.49-3.66 3.32-3.66l46.97.27z'
)
pp-openweather-city
p.city-label city
p.city-value LRSY
pp-openweather-temp
p.temp-label temp.
p.temp-value
pp-openweather-humid
p.humid-label humid.
p.humid-value
pp-openweather-loader-container
pp-loader
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-openweather-error-container
p.error-notification API error
p.openweather-error-code

+ 45
- 0
browser/startpage/src/raisin/raisin.css View File

@ -0,0 +1,45 @@
/************** RAISIN **************/
raisin {
display: flex;
flex-direction: column;
grid-row: span 4;
justify-content: space-between;
padding: var(--spacing-00) var(--spacing-0);
background-color: var(--main);
border: 2px solid var(--pomme-background);
border-radius: 10px;
animation: fadein-page 50ms ease-out normal backwards;
animation-delay: 50ms;
}
.raisin-title {
color: var(--myrtille-background);
font-weight: var(--font-weight-bold);
font-size: var(--scale-1);
}
raisin-links {
display: flex;
flex-direction: column;
}
.raisin-link {
padding: var(--spacing-0000) 0;
color: inherit;
color: var(--myrtille-background);
font-size: var(--scale-00);
text-decoration: none;
border-top: 1px dashed var(--myrtille-background);
outline: none;
}
.raisin-link:first-child {
border-top: none;
}
.raisin-link:hover::after {
position: absolute;
content: "❯";
color: var(--pomme-background);
}

+ 14
- 0
browser/startpage/src/raisin/raisin.js View File

@ -0,0 +1,14 @@
// //////// RAISIN //////// //
function truncateLinkName() {
const raisinLinks = [...document.querySelectorAll('.raisin-link')]
const maxLength = 12
raisinLinks.forEach(link => {
if (link.innerHTML.length > maxLength) {
link.innerHTML = `${link.innerHTML.replace(/\.[^/.]+$/, '').slice(0, Math.max(0, maxLength))}...`
}
})
}
export default truncateLinkName

+ 46
- 0
browser/startpage/src/raisin/raisin.pug View File

@ -0,0 +1,46 @@
// //////// RAISIN //////// //
-
var dev = {
'regex101': 'regex101.com',
'codewars': 'codewars.com',
'dev.to': 'dev.to',
'css tricks': 'css-tricks.com'
}
var hack = {
'hackerone': 'hackerone.com',
'bugcrowd': 'bugcrowd.com',
'hackthebox': 'hackthebox.eu',
'intigriti': 'intigriti.com'
}
var colors = {
'coolors': 'coolors.co',
'color space': 'mycolor.space/',
'color hunt': 'colorhunt.co',
'gradient magic': 'gradientmagic.com'
}
var css = {
'fancy borders': '9elements.github.io/fancy-border-radius',
'transform visualizer': 'css-transform.moro.es',
'css doodle': 'css-doodle.com',
'css stats': 'cssstats.com',
}
var fonts = {
'type scale': 'type-scale.com',
'fonts in use': 'fontsinuse.com',
'font joy': 'fontjoy.com',
'zenigata': 'typo.zenigata.fr',
}
mixin raisin(title, data)
raisin
raisin-header
p.raisin-title #{title}
raisin-links
each val, key in data
a.raisin-link(href="https://" + val, target='_blank', rel='noopener noreferrer') #{key}

+ 58
- 0
browser/startpage/src/search/search.css View File

@ -0,0 +1,58 @@
/************** SEARCH **************/
pp-search {
display: flex;
grid-column: span 3;
grid-row: span 2;
justify-content: space-between;
align-items: center;
padding: 0 var(--spacing-0);
background-color: var(--search-background);
border-radius: 10px;
animation: fadein-page 250ms ease-out normal backwards;
animation-delay: 150ms;
}
pp-engine-buttons {
display: flex;
justify-content: space-between;
align-items: center;
width: 80px;
}
.pp-search-icon {
width: var(--spacing-2);
height: var(--spacing-2);
padding: 0;
background: none;
border: none;
outline: inherit;
cursor: pointer;
}
.pp-search-icon[data-state='inactive'] {
opacity: 0.5;
}
.pp-search-icon > path {
pointer-events: none;
}
.pp-search-input {
flex: 1;
min-width: 0;
margin: 0 var(--spacing-000) 0 24px;
padding: var(--spacing-0000) 0;
color: var(--main);
font-size: var(--scale-2);
background-color: transparent;
background-image: none;
border: none;
border-bottom: 1px dashed var(--main);
box-shadow: none;
}
pp-search textarea:focus,
input:focus {
outline: none;
}

+ 27
- 0
browser/startpage/src/search/search.js View File

@ -0,0 +1,27 @@
// //////// SEARCH //////// //
const searchContainer = document.querySelector('pp-search')
const buttonsContainer = document.querySelector('pp-engine-buttons')
const iconList = document.querySelectorAll('.pp-search-icon')
function toggleEngineIcons(event) {
iconList.forEach(icon => {
icon.dataset.state = 'inactive'
})
event.target.dataset.state = 'active'
}
function sendSearch(event) {
const input = document.querySelector('.pp-search-input')
if (event.key === 'Enter') {
const activeEngine = [...iconList].find(b => [...b.attributes][3].value === 'active')
const activeEngineDomain = [...activeEngine.attributes][5].value
const url = `${activeEngineDomain}?q=${input.value}`
window.open(url)
input.value = ''
}
}
export {buttonsContainer, searchContainer, toggleEngineIcons, sendSearch}

+ 28
- 0
browser/startpage/src/search/search.pug View File

@ -0,0 +1,28 @@
// //////// SEARCH //////// //
pp-search
pp-engine-buttons
svg.pp-search-icon(
xmlns='http://www.w3.org/2000/svg',
viewBox='0 0 534 534',
data-state='inactive',
data-engine='duckduckgo',
data-address='https://www.duckduckgo.com/',
fill='var(--main)'
)
path(
d='M175.556 517.337C73.183 480.071 0 381.848 0 266.667 0 119.489 119.489 0 266.667 0c147.177 0 266.666 119.489 266.666 266.667 0 125.498-86.88 230.864-203.74 259.185L312.5 491.667c-19.063 4.786-32.54 4.404-41.667 0-15.311 11.875-31.988 20.181-50 25-11.041-16.974-12.847-49.127-8.333-91.667 5.902-5.051 28.026 2.93 62.5 20.833 1.372-4.124 5.432-6.952 12.5-8.333-10.974-31.038-14.996-63.002-12.5-95.833 31.823 19.933 69.278 29.735 112.5 29.166 29.953-2.016 53.515-11.799 70.833-29.166 2.241-5.611-.691-8.301-8.333-8.334-17.001-1.374-45.382 5.703-87.5 12.5-18.683-.116-34.105-4.111-45.833-12.5-14.395-9.696-13.463-15.31-4.167-25 5.345-5.359 29.53-4.833 54.167-4.166 28.74-2.514 102.777-34.723 116.666-45.834 10.682-8.545-15.23-22.754-33.333-20.833l-83.333 25C371.312 167.894 336.725 118.358 275 100c-33.955-40.195-83.302-50.067-141.667-41.667l25 8.334-29.166 25c25.938-2.216 53.635-.986 83.333 4.166-26.637 5.01-47.69 13.217-62.5 25-24.723 17.544-37.223 43.933-37.5 79.167 16.804 103.667 40.37 216.46 63.056 317.337zm16.111-313.17c11.498 0 20.833 9.335 20.833 20.833 0 11.498-9.335 20.833-20.833 20.833-11.499 0-20.834-9.335-20.834-20.833 0-11.498 9.335-20.833 20.834-20.833zm139.583-8.334c10.348 0 18.75 8.402 18.75 18.75 0 10.349-8.402 18.75-18.75 18.75s-18.75-8.401-18.75-18.75c0-10.348 8.402-18.75 18.75-18.75zm-133.333 20.834c3.449 0 6.25 2.8 6.25 6.25a6.254 6.254 0 01-6.25 6.25 6.253 6.253 0 01-6.25-6.25c0-3.45 2.8-6.25 6.25-6.25zm138.958-9.584a5.628 5.628 0 015.625 5.625 5.627 5.627 0 01-5.625 5.625 5.627 5.627 0 01-5.625-5.625 5.628 5.628 0 015.625-5.625zM154.167 187.5c5.383-19.103 19.214-26.131 41.666-20.833-6.781-5.178-22.222-11.806-29.166-8.334-6.945 3.473-15.388 17.721-12.5 29.167zm144.999-20.833c13.116-10.594 27.378-9.636 42.501 0-2.379-6.09-17.917-16.667-25-16.667-7.084 0-16.659 9.732-17.501 16.667z'
)
svg.pp-search-icon(
xmlns='http://www.w3.org/2000/svg',
viewBox='0 0 200 200',
data-state='active',
data-engine='google',
data-address='https://www.google.com/',
fill-rule='evenodd',
fill='var(--main)'
)
path(
d='M100 0c55.192 0 100 44.808 100 100s-44.808 100-100 100S0 155.192 0 100 44.808 0 100 0zm42.257 115.575h-40.174V87.5h70.834l3.205-.029s.961 8.266.961 12.529c0 43.693-34.54 79.167-77.083 79.167S22.917 143.693 22.917 100c0-43.693 34.54-79.167 77.083-79.167 20.791 0 39.671 8.473 53.542 22.236l-22.547 23.598c-8.06-7.908-18.979-12.768-30.995-12.768-24.774 0-44.888 20.657-44.888 46.101S75.226 146.101 100 146.101c19.453 0 36.033-12.737 42.257-30.526z'
)
input.pp-search-input(type='text', autofocus)

+ 91
- 0
browser/startpage/src/stormglass/stormglass.css View File

@ -0,0 +1,91 @@
/************** STORMGLASS **************/
pp-stormglass {
display: none;
flex-direction: column;
grid-column: span 2;
grid-row: span 4;
padding: 0 var(--spacing-2);
background-color: var(--module-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
pp-stormglass > * {
display: flex;
justify-content: space-between;
align-items: center;
height: var(--spacing-4);
}
pp-header > p,
.watertemp-value,
.winddir-value,
.windspeed-value,
.waveheight-value,
.waveperiod-value,
.wavedir-value {
color: var(--main);
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
}
pp-firstrow > *,
pp-secondrow > * {
display: flex;
flex-direction: column;
align-items: center;
}
.watertemp-label,
.winddir-label,
.windspeed-label,
.waveheight-label,
.waveperiod-label,
.wavedir-label {
color: var(--main-light);
font-weight: var(--font-weight-bold);
font-size: var(--scale-00);
}
.pp-stormglass-unit {
color: var(--main-light);
font-size: var(--scale-0);
}
pp-linebreak {
width: 100%;
height: 1px;
background: var(--main-light);
}
pp-stormglass-loader-container {
display: flex;
grid-column: span 2;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--pomme-background);
border-radius: 10px;
}
pp-stormglass-error-container {
display: none;
flex-direction: column;
grid-column: span 2;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--search-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
p.stormglass-error-code {
margin-top: var(--spacing-0);
color: var(--search-background);
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
}

+ 53
- 0
browser/startpage/src/stormglass/stormglass.js View File

@ -0,0 +1,53 @@
// //////// STORMGLASS //////// //
const stormglassLoaderContainer = document.querySelector('pp-stormglass-loader-container')
function handleStormGlassApiError(response) {
const stormglassErrorContainer = document.querySelector('pp-stormglass-error-container')
const stormglassErrorCode = document.querySelector('.stormglass-error-code')
stormglassErrorCode.innerHTML = response.status
stormglassLoaderContainer.style.display = 'none'
stormglassErrorContainer.style.display = 'flex'
}
async function displayStormglassData(data) {
const stormglassContainer = document.querySelector('pp-stormglass')
const spotName = document.querySelector('.header-spot')
const waterTemporary = document.querySelector('.watertemp-value')
const windDirection = document.querySelector('.winddir-icon')
const windSpeed = document.querySelector('.windspeed-value')
const waveHeight = document.querySelector('.waveheight-value')
const wavePeriod = document.querySelector('.waveperiod-value')
const wavedir = document.querySelector('.wavedir-icon')
spotName.innerHTML = process.env.STORMGLASS_SPOT_NAME
waterTemporary.innerHTML = `${Math.round(data.waterTemperature.meto || data.waterTemperature.noaa || data.waterTemperature.sg)}°`
windDirection.style.transform = `rotate(${data.windDirection.icon || data.windDirection.noaa || data.windDirection.sg}deg)`
windSpeed.innerHTML = `${data.windSpeed.icon || data.windSpeed.noaa || data.windSpeed.sg} <span class="pp-stormglass-unit">m/s</span>`
waveHeight.innerHTML = `${data.waveHeight.icon || data.waveHeight.dwd} <span class="pp-stormglass-unit">m</span>`
wavePeriod.innerHTML = `${Math.round(data.wavePeriod.icon || data.wavePeriod.noaa)} <span class="pp-stormglass-unit">s</span>`
wavedir.style.transform = `rotate(${data.waveDirection.icon || data.waveDirection.noaa || data.waveDirection.meteo}deg)`
stormglassLoaderContainer.style.display = 'none'
stormglassContainer.style.display = 'flex'
}
async function getStormglassData() {
const currentISODate = new Date().toISOString().slice(0, 13)
const apiKey = process.env.STORMGLASS_API_KEY
const lat = process.env.STORMGLASS_LATITUDE
const lng = process.env.STORMGLASS_LONGITUDE
const url = 'https://api.stormglass.io/v2/'
const path = 'weather/point'
const parameters = ['waterTemperature', 'waveDirection', 'waveHeight', 'wavePeriod', 'windDirection', 'windSpeed']
const response = await fetch(`${url}${path}?lat=${lat}&lng=${lng}&params=${parameters}`, {headers: {Authorization: apiKey}})
if (response.ok) {
const jsonResponse = await response.json()
const currentSurfData = await jsonResponse.hours.find(h => h.time.includes(currentISODate))
return displayStormglassData(currentSurfData)
}
return handleStormGlassApiError(response)
}
export default getStormglassData

+ 57
- 0
browser/startpage/src/stormglass/stormglass.pug View File

@ -0,0 +1,57 @@
// //////// STORMGLASS //////// //
pp-stormglass
pp-header
p.header-spot
pp-firstrow
pp-watertemp
p.watertemp-value
p.watertemp-label water t°
pp-winddir
svg.winddir-icon(
xmlns='http://www.w3.org/2000/svg',
width='24',
height='24',
fill='none',
stroke='var(--main)',
stroke-width='3',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M12 5v14M19 12l-7 7-7-7')
p.winddir-label wind dir.
pp-windspeed
p.windspeed-value
p.windspeed-label wind spd.
pp-linebreak
pp-secondrow
pp-waveheight
p.waveheight-value
p.waveheight-label wave hgt.
pp-waveperiod
p.waveperiod-value
p.waveperiod-label wave per.
pp-wavedir
svg.wavedir-icon(
xmlns='http://www.w3.org/2000/svg',
width='24',
height='24',
fill='none',
stroke='var(--main)',
stroke-width='3',
stroke-linecap='round',
stroke-linejoin='round'
)
path(d='M12 5v14M19 12l-7 7-7-7')
p.wavedir-label wave dir.
pp-stormglass-loader-container
pp-loader
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-stormglass-error-container
p.error-notification API error
p.stormglass-error-code

+ 49
- 0
browser/startpage/src/unsplash/unsplash.css View File

@ -0,0 +1,49 @@
/************** UNSPLASH **************/
pp-unsplash {
display: none;
grid-column: span 2;
grid-row: span 4;
background-color: var(--myrtille-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
pp-unsplash > img {
width: 100%;
padding: var(--spacing-0000);
border-radius: 12px;
opacity: 0.5;
filter: grayscale(80%);
}
pp-unsplash-loader-container {
display: flex;
grid-column: span 2;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--pomme-background);
border-radius: 10px;
}
pp-unsplash-error-container {
display: none;
flex-direction: column;
grid-column: span 2;
grid-row: span 4;
justify-content: center;
align-items: center;
background-color: var(--main);
border: 2px solid var(--search-background);
border-radius: 10px;
animation: module-display 500ms ease-in-out;
}
p.unsplash-error-code {
margin-top: var(--spacing-0);
color: var(--search-background);
font-weight: var(--font-weight-bold);
font-size: var(--scale-2);
}

+ 41
- 0
browser/startpage/src/unsplash/unsplash.js View File

@ -0,0 +1,41 @@
// //////// UNSPLASH //////// //
const unsplashLoaderContainer = document.querySelector('pp-unsplash-loader-container')
function handleUnsplashApiError(response) {
const unsplashErrorContainer = document.querySelector('pp-unsplash-error-container')
const unsplashErrorCode = document.querySelector('.unsplash-error-code')
unsplashErrorCode.innerHTML = response.status
unsplashLoaderContainer.style.display = 'none'
unsplashErrorContainer.style.display = 'flex'
}
function displayUnsplashImage(data) {
const image = document.querySelector('.unsplash-small')
const unsplashLoader = document.querySelector('pp-unsplash-loader-container')
const unsplashContainer = document.querySelector('pp-unsplash')
image.src = data.urls.small
unsplashLoader.style.display = 'none'
unsplashContainer.style.display = 'flex'
}
async function getUnsplashData() {
const apiKey = process.env.UNSPLASH_API_KEY
const orientation = 'landscape'
const collectionId = process.env.UNSPLASH_COLLECTION_ID
const url = 'https://api.unsplash.com/'
const path = 'photos/random/'
const parameters = `client_id=${apiKey}&orientation=${orientation}&collections=${collectionId}`
const response = await fetch(`${url}${path}?${parameters}`)
if (response.ok) {
const jsonResponse = await response.json()
return displayUnsplashImage(jsonResponse)
}
return handleUnsplashApiError(response)
}
export default getUnsplashData

+ 15
- 0
browser/startpage/src/unsplash/unsplash.pug View File

@ -0,0 +1,15 @@
// //////// UNSPLASH //////// //
pp-unsplash
img.unsplash-small(src='')
pp-unsplash-loader-container
pp-loader
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-loader-dot
pp-unsplash-error-container
p.error-notification API error
p.unsplash-error-code

firefox/vimium.json → browser/vimium.json View File


+ 21
- 8
install.sh View File

@ -1,6 +1,13 @@
#!/bin/bash
username=$(whoami)
# Configuring for your username
if [ ! "$username" = "yigit" ]; then
find /home/$username/.dotfiles -type f | xargs sed -i "s/\/home\/yigit/\/home\/$username/g"
fi
# Install packages
echo "Running update"
sudo pacman --noconfirm -Syu
@ -153,7 +160,7 @@ if [ ! -f "/var/spool/cron$username" ]; then
sudo chown yigit:yigit "/var/spool/cron/$username"
sudo chmod 755 "/var/spool/cron/$username"
fi
echo "COMMAND firefox-developer-edition" > ~/.urlview
echo "COMMAND brave" > ~/.urlview
echo "*/8 * * * * /home/$username/.scripts/mailsync" >> /var/spool/cron/yigit
echo "*/15 * * * * /home/$username/.scripts/nextcloud-sync" >> /var/spool/cron/yigit
echo "*/30 * * * * calcurse-caldav" >> /var/spool/cron/yigit
@ -162,16 +169,26 @@ echo "*/30 * * * * vdirsyncer sync" >> /var/spool/cron/yigit
# Root
sudo cp ~/.dotfiles/root/dwm.desktop /usr/share/xsessions
sudo cp ~/.dotfiles/root/nancyj.flf /usr/share/figlet/fonts
sudo cp ~/.dotfiles/quark.service /usr/lib/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable quark
# Config
cp ~/.dotfiles/config.env.def ~/.config.env
# Firefox
firefox-developer-edition -CreateProfile "yeet"
cp -r ~/.dotfiles/firefox/flyingfox/* ~/.mozilla/firefox/*.yeet
cp -r ~/.dotfiles/firefox/extensions ~/.mozilla/firefox/*.yeet
cp ~/.dotfiles/firefox/extensions.json ~/.mozilla/firefox/*.yeet
cp -r ~/.dotfiles/browser/flyingfox/* ~/.mozilla/firefox/*.yeet
cp -r ~/.dotfiles/browser/extensions ~/.mozilla/firefox/*.yeet
cp ~/.dotfiles/browser/extensions.json ~/.mozilla/firefox/*.yeet
# Start page
prev=$(pwd)
cd ~/.dotfiles/browser/startpage
npm install
npm run build
cd $prev
~/.dotfiles/arch-setup/fetch_keys.sh # Fetch keys (For personal use, this is not for you)
# Install vim and tmux plugins
@ -203,7 +220,3 @@ git clone https://github.com/theFr1nge/simcrop.git /tmp/simcrop
cd /tmp/simcrop
sudo make install
cd $prev
if [ ! "$username" = "yigit" ]; then
find /home/$username/.dotfiles -type f | xargs sed -i "s/\/home\/yigit/\/home\/$username/g"
fi

+ 1
- 1
misc/dunst/dunstrc View File

@ -158,7 +158,7 @@
dmenu = /usr/bin/dmenu -p dunst:
# Browser for opening urls in context menu.
browser = firefox-developer-edition
browser = brave
# Align icons left/right/off
icon_position = left


+ 3
- 29
misc/mimeapps.list View File

@ -1,8 +1,8 @@
[Default Applications]
x-scheme-handler/jetbrains=jetbrains-toolbox.desktop
x-scheme-handler/mailspring=mailspring.desktop
x-scheme-handler/http=firefox-developer-edition.desktop
x-scheme-handler/https=firefox-developer-edition.desktop
x-scheme-handler/http=brave.desktop
x-scheme-handler/https=brave.desktop
image/png=sxiv.desktop
image/jpeg=sxiv.desktop
text/plain=vim.desktop
@ -11,7 +11,7 @@ x-scheme-handler/gitkraken=GitKraken.desktop
x-scheme-handler/ssh=ktelnetservice5.desktop
video/mp4=mpv.desktop
video/x-matroska=mpv.desktop
text/html=firefox-developer-edition.desktop
text/html=brave.desktop
application/vnd.openxmlformats-officedocument.wordprocessingml.document=libreoffice-writer.desktop
application/x-shellscript=vim.desktop
inode/directory=ranger.desktop
@ -24,29 +24,3 @@ x-scheme-handler/mailto=neomutt.desktop
message/rfc822=userapp-neomutt.desktop
application/x-directory=ranger.desktop
[Added Associations]
image/png=deepin-image-viewer.desktop;feh.desktop;eom.desktop;
image/jpeg=deepin-image-viewer.desktop;eom.desktop;sxiv.desktop;
text/plain=gvim.desktop;vim.desktop;visual-studio-code.desktop;sublime_text.desktop;
application/octet-stream=sublime_text.desktop;org.gnome.GHex.desktop;vim.desktop;
video/x-ms-wmv=vlc.desktop;
audio/wav=sonic-visualiser.desktop;
text/x-python=vim.desktop;visual-studio-code.desktop;
text/x-tex=gvim.desktop;vim.desktop;
video/mp4=vlc.desktop;
video/x-matroska=vlc.desktop;
application/x-ole-storage=userapp-ghex-QDFPP0.desktop;
text/html=firefox-developer-edition.desktop;
video/quicktime=vlc.desktop;
application/pdf=org.pwmt.zathura-pdf-mupdf.desktop;atril.desktop;mupdf.desktop;userapp-zathura-N034Y0.desktop;
application/vnd.openxmlformats-officedocument.wordprocessingml.document=libreoffice-writer.desktop;
application/x-shellscript=sublime_text.desktop;
application/x-bittorrent=transmission-gtk.desktop;
application/zip=org.kde.ark.desktop;org.gnome.Nautilus.desktop;engrampa.desktop;
image/gif=eom.desktop;
video/webm=vlc.desktop;
x-scheme-handler/tg=userapp-Telegram Desktop-RUP9V0.desktop;
binary/octet-stream=sublime_text.desktop;
x-scheme-handler/mailto=userapp-Thunderbird-RAKCZ0.desktop;userapp-Thunderbird-38XBZ0.desktop;userapp-Thunderbird-A0ECZ0.desktop;
message/rfc822=userapp-Thunderbird-RAKCZ0.desktop;userapp-Thunderbird-38XBZ0.desktop;userapp-Thunderbird-A0ECZ0.desktop;
application/x-tex=vim.desktop;

+ 9
- 0
root/quark.service View File

@ -0,0 +1,9 @@
[Unit]
Description=Quark instance on 9999 for start page
[Service]
Type=simple
ExecStart=/usr/local/bin/quark -p 9999 -d /home/yigit/.dotfiles/browser/startpage/dist -h 127.0.0.1
[Install]
WantedBy=multi-user.target

+ 1
- 1
scripts/status-bar/arch View File

@ -7,7 +7,7 @@ if ! updates=$(checkupdates 2> /dev/null | wc -l ); then
fi
case $BLOCK_BUTTON in
1) "$TERMINAL" -e yay -Syu;;
1) setsid -f "$TERMINAL" -c center -n center -e yay -Syu;;
6) "$TERMINAL" -e "$EDITOR" "$0" ;;
esac


+ 1
- 0
suckless/dwm/rules.h View File

@ -7,6 +7,7 @@ static const Rule rules[] = {
*/
RULE(.class = "discord", .tags = 1 << 8)
RULE(.class = "firefoxdeveloperedition", .tags = 1 << 1)
RULE(.class = "Brave-browser", .tags = 1 << 1)
RULE(.class = "tabbed-surf", .tags = 1 << 1)
RULE(.class = "tabbed", .tags = 1 << 1)
RULE(.class = "bitwarden", .tags = 1 << 6)


+ 27
- 0
suckless/quark/LICENSE View File

@ -0,0 +1,27 @@
ISC-License
Copyright 2016-2021 Laslo Hunhold <dev@frign.de>
Copyright 2004 Ted Unangst <tedu@openbsd.org>
Copyright 2004 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright 2008 Otto Moerbeek <otto@drijf.net>
Copyright 2017-2018 Hiltjo Posthuma <hiltjo@codemadness.org>
Copyright 2017-2021 Quentin Rameau <quinq@fifth.space>
Copyright 2018 Josuah Demangeon <mail@josuah.net>
Copyright 2018 Dominik Schmidt <domischmidt@swissonline.ch>
Copyright 2018 Aaron Burrow <burrows@charstarstar.com>
Copyright 2020 Nihal Jere <nihal@nihaljere.xyz>
Copyright 2020 Rainer Holzner <rholzner@web.de>
Copyright 2020 Jeremy Bobbin <jer@jer.cx>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 46
- 0
suckless/quark/Makefile View File

@ -0,0 +1,46 @@
# See LICENSE file for copyright and license details
# quark - simple web server
.POSIX:
include config.mk
COMPONENTS = connection data http queue server sock util
all: quark
connection.o: connection.c config.h connection.h data.h http.h server.h sock.h util.h config.mk
data.o: data.c config.h data.h http.h server.h util.h config.mk
http.o: http.c config.h http.h server.h util.h config.mk
main.o: main.c arg.h config.h server.h sock.h util.h config.mk
server.o: server.c config.h connection.h http.h queue.h server.h util.h config.mk
sock.o: sock.c config.h sock.h util.h config.mk
util.o: util.c config.h util.h config.mk
quark: config.h $(COMPONENTS:=.o) $(COMPONENTS:=.h) main.o config.mk
$(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $(COMPONENTS:=.o) main.o $(LDFLAGS)
config.h:
cp config.def.h $@
clean:
rm -f quark main.o $(COMPONENTS:=.o)
dist:
rm -rf "quark-$(VERSION)"
mkdir -p "quark-$(VERSION)"
cp -R LICENSE Makefile arg.h config.def.h config.mk quark.1 \
$(COMPONENTS:=.c) $(COMPONENTS:=.h) main.c "quark-$(VERSION)"
tar -cf - "quark-$(VERSION)" | gzip -c > "quark-$(VERSION).tar.gz"
rm -rf "quark-$(VERSION)"
install: all
mkdir -p "$(DESTDIR)$(PREFIX)/bin"
cp -f quark "$(DESTDIR)$(PREFIX)/bin"
chmod 755 "$(DESTDIR)$(PREFIX)/bin/quark"
mkdir -p "$(DESTDIR)$(MANPREFIX)/man1"
cp quark.1 "$(DESTDIR)$(MANPREFIX)/man1/quark.1"
chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/quark.1"
uninstall:
rm -f "$(DESTDIR)$(PREFIX)/bin/quark"
rm -f "$(DESTDIR)$(MANPREFIX)/man1/quark.1"

+ 50
- 0
suckless/quark/arg.h View File

@ -0,0 +1,50 @@
/*
* ISC-License
*
* Copyright 2004-2017 Christoph Lohmann <20h@r-36.net>
* Copyright 2017-2018 Laslo Hunhold <dev@frign.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ARG_H
#define ARG_H
extern char *argv0;
/* int main(int argc, char *argv[]) */
#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \
*argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \
int i_, argused_; \
if ((*argv)[1] == '-' && !(*argv)[2]) { \
argc--, argv++; \
break; \
} \
for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \
switch((*argv)[i_])
#define ARGEND if (argused_) { \
if ((*argv)[i_ + 1]) { \
break; \
} else { \
argc--, argv++; \
break; \
} \
} \
} \
}
#define ARGC() ((*argv)[i_])
#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \
(*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x))
#define EARGF(x) ARGF_(((x), exit(1), (char *)0))
#define ARGF() ARGF_((char *)0)
#endif

+ 40
- 0
suckless/quark/config.h View File

@ -0,0 +1,40 @@
#ifndef CONFIG_H
#define CONFIG_H
#define BUFFER_SIZE 4096
#define FIELD_MAX 200
/* mime-types */
static const struct {
char *ext;
char *type;
} mimes[] = {
{ "xml", "application/xml; charset=utf-8" },
{ "xhtml", "application/xhtml+xml; charset=utf-8" },
{ "html", "text/html; charset=utf-8" },
{ "js", "text/javascript; charset=utf-8" },
{ "htm", "text/html; charset=utf-8" },
{ "css", "text/css; charset=utf-8" },
{ "txt", "text/plain; charset=utf-8" },
{ "md", "text/plain; charset=utf-8" },
{ "c", "text/plain; charset=utf-8" },
{ "h", "text/plain; charset=utf-8" },
{ "gz", "application/x-gtar" },
{ "tar", "application/tar" },
{ "pdf", "application/x-pdf" },
{ "png", "image/png" },
{ "gif", "image/gif" },
{ "jpeg", "image/jpg" },
{ "jpg", "image/jpg" },
{ "iso", "application/x-iso9660-image" },
{ "webp", "image/webp" },
{ "svg", "image/svg+xml; charset=utf-8" },
{ "flac", "audio/flac" },
{ "mp3", "audio/mpeg" },
{ "ogg", "audio/ogg" },
{ "mp4", "video/mp4" },
{ "ogv", "video/ogg" },
{ "webm", "video/webm" },
};
#endif /* CONFIG_H */

+ 16
- 0
suckless/quark/config.mk View File

@ -0,0 +1,16 @@
# quark version
VERSION = 0
# Customize below to fit your system
# paths
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
# flags
CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os
LDFLAGS = -lpthread -s
# compiler and linker
CC = cc

+ 314
- 0
suckless/quark/connection.c View File

@ -0,0 +1,314 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "connection.h"
#include "data.h"
#include "http.h"
#include "server.h"
#include "sock.h"
#include "util.h"
struct worker_data {
int insock;
size_t nslots;
const struct server *srv;
};
void
connection_log(const struct connection *c)
{
char inaddr_str[INET6_ADDRSTRLEN /* > INET_ADDRSTRLEN */];
char tstmp[21];
/* create timestamp */
if (!strftime(tstmp, sizeof(tstmp), "%Y-%m-%dT%H:%M:%SZ",
gmtime(&(time_t){time(NULL)}))) {
warn("strftime: Exceeded buffer capacity");
/* continue anyway (we accept the truncation) */
}
/* generate address-string */
if (sock_get_inaddr_str(&c->ia, inaddr_str, LEN(inaddr_str))) {
warn("sock_get_inaddr_str: Couldn't generate adress-string");
inaddr_str[0] = '\0';
}
printf("%s\t%s\t%s%.*d\t%s\t%s%s%s%s%s\n",
tstmp,
inaddr_str,
(c->res.status == 0) ? "dropped" : "",
(c->res.status == 0) ? 0 : 3,
c->res.status,
c->req.field[REQ_HOST][0] ? c->req.field[REQ_HOST] : "-",
c->req.path[0] ? c->req.path : "-",
c->req.query[0] ? "?" : "",
c->req.query,
c->req.fragment[0] ? "#" : "",
c->req.fragment);
}
void
connection_reset(struct connection *c)
{
if (c != NULL) {
shutdown(c->fd, SHUT_RDWR);
close(c->fd);
memset(c, 0, sizeof(*c));
}
}
void
connection_serve(struct connection *c, const struct server *srv)
{
enum status s;
int done;
switch (c->state) {
case C_VACANT:
/*
* we were passed a "fresh" connection which should now
* try to receive the header, reset buf beforehand
*/
memset(&c->buf, 0, sizeof(c->buf));
c->state = C_RECV_HEADER;
/* fallthrough */
case C_RECV_HEADER:
/* receive header */
done = 0;
if ((s = http_recv_header(c->fd, &c->buf, &done))) {
http_prepare_error_response(&c->req, &c->res, s);
goto response;
}
if (!done) {
/* not done yet */
return;
}
/* parse header */
if ((s = http_parse_header(c->buf.data, &c->req))) {
http_prepare_error_response(&c->req, &c->res, s);
goto response;
}
/* prepare response struct */
http_prepare_response(&c->req, &c->res, srv);
response:
/* generate response header */
if ((s = http_prepare_header_buf(&c->res, &c->buf))) {
http_prepare_error_response(&c->req, &c->res, s);
if ((s = http_prepare_header_buf(&c->res, &c->buf))) {
/* couldn't generate the header, we failed for good */
c->res.status = s;
goto err;
}
}
c->state = C_SEND_HEADER;
/* fallthrough */
case C_SEND_HEADER:
if ((s = http_send_buf(c->fd, &c->buf))) {
c->res.status = s;
goto err;
}
if (c->buf.len > 0) {
/* not done yet */
return;
}
c->state = C_SEND_BODY;
/* fallthrough */
case C_SEND_BODY:
if (c->req.method == M_GET) {
if (c->buf.len == 0) {
/* fill buffer with body data */
if ((s = data_fct[c->res.type](&c->res, &c->buf,
&c->progress))) {
/* too late to do any real error handling */
c->res.status = s;
goto err;
}
/* if the buffer remains empty, we are done */
if (c->buf.len == 0) {
break;
}
} else {
/* send buffer */
if ((s = http_send_buf(c->fd, &c->buf))) {
/* too late to do any real error handling */
c->res.status = s;
goto err;
}
}
return;
}
break;
default:
warn("serve: invalid connection state");
return;
}
err:
connection_log(c);
connection_reset(c);
}
static struct connection *
connection_get_drop_candidate(struct connection *connection, size_t nslots)
{
struct connection *c, *minc;
size_t i, j, maxcnt, cnt;
/*
* determine the most-unimportant connection 'minc' of the in-address
* with most connections; this algorithm has a complexity of O(n²)
* in time but is O(1) in space; there are algorithms with O(n) in
* time and space, but this would require memory allocation,
* which we avoid. Given the simplicity of the inner loop and
* relatively small number of slots per thread, this is fine.
*/
for (i = 0, minc = NULL, maxcnt = 0; i < nslots; i++) {
/*
* we determine how many connections have the same
* in-address as connection[i], but also minimize over
* that set with other criteria, yielding a general
* minimizer c. We first set it to connection[i] and
* update it, if a better candidate shows up, in the inner
* loop
*/
c = &connection[i];
for (j = 0, cnt = 0; j < nslots; j++) {
if (!sock_same_addr(&connection[i].ia,
&connection[j].ia)) {
continue;
}
cnt++;
/* minimize over state */
if (connection[j].state < c->state) {
c = &connection[j];
} else if (connection[j].state == c->state) {
/* minimize over progress */
if (c->state == C_SEND_BODY &&
connection[i].res.type != c->res.type) {
/*
* mixed response types; progress
* is not comparable
*
* the res-type-enum is ordered as
* DIRLISTING, ERROR, FILE, i.e.
* in rising priority, because a
* file transfer is most important,
* followed by error-messages.
* Dirlistings as an "interactive"
* feature (that take up lots of
* resources) have the lowest
* priority
*/
if (connection[i].res.type <
c->res.type) {
c = &connection[j];
}
} else if (connection[j].progress <
c->progress) {
/*
* for C_SEND_BODY with same response
* type, C_RECV_HEADER and C_SEND_BODY
* it is sufficient to compare the
* raw progress
*/
c = &connection[j];
}
}
}
if (cnt > maxcnt) {
/* this run yielded an even greedier in-address */
minc = c;
maxcnt = cnt;
}
}
return minc;
}
struct connection *
connection_accept(int insock, struct connection *connection, size_t nslots)
{
struct connection *c = NULL;
size_t i;
/* find vacant connection (i.e. one with no fd assigned to it) */
for (i = 0; i < nslots; i++) {
if (connection[i].fd == 0) {
c = &connection[i];
break;
}
}
if (i == nslots) {
/*
* all our connection-slots are occupied and the only
* way out is to drop another connection, because not
* accepting this connection just kicks this can further
* down the road (to the next queue_wait()) without
* solving anything.
*
* This may sound bad, but this case can only be hit
* either when there's a (D)DoS-attack or a massive
* influx of requests. The latter is impossible to solve
* at this moment without expanding resources, but the
* former has certain characteristics allowing us to
* handle this gracefully.
*
* During an attack (e.g. Slowloris, R-U-Dead-Yet, Slow
* Read or just plain flooding) we can not see who is
* waiting to be accept()ed.
* However, an attacker usually already has many
* connections open (while well-behaved clients could
* do everything with just one connection using
* keep-alive). Inferring a likely attacker-connection
* is an educated guess based on which in-address is
* occupying the most connection slots. Among those,
* connections in early stages (receiving or sending
* headers) are preferred over connections in late
* stages (sending body).
*
* This quantitative approach effectively drops malicious
* connections while preserving even long-running
* benevolent connections like downloads.
*/
c = connection_get_drop_candidate(connection, nslots);
c->res.status = 0;
connection_log(c);
connection_reset(c);
}
/* accept connection */
if ((c->fd = accept(insock, (struct sockaddr *)&c->ia,
&(socklen_t){sizeof(c->ia)})) < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
/*
* this should not happen, as we received the
* event that there are pending connections here
*/
warn("accept:");
}
return NULL;
}
/* set socket to non-blocking mode */
if (sock_set_nonblocking(c->fd)) {
/* we can't allow blocking sockets */
return NULL;
}
return c;
}

+ 32
- 0
suckless/quark/connection.h View File

@ -0,0 +1,32 @@
/* See LICENSE file for copyright and license details. */
#ifndef CONNECTION_H
#define CONNECTION_H
#include "http.h"
#include "server.h"
#include "util.h"
enum connection_state {
C_VACANT,
C_RECV_HEADER,
C_SEND_HEADER,
C_SEND_BODY,
NUM_CONN_STATES,
};
struct connection {
enum connection_state state;
int fd;
struct sockaddr_storage ia;
struct request req;
struct response res;
struct buffer buf;
size_t progress;
};
struct connection *connection_accept(int, struct connection *, size_t);
void connection_log(const struct connection *);
void connection_reset(struct connection *);
void connection_serve(struct connection *, const struct server *);
#endif /* CONNECTION_H */

+ 231
- 0
suckless/quark/data.c View File

@ -0,0 +1,231 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "data.h"
#include "http.h"
#include "util.h"
enum status (* const data_fct[])(const struct response *,
struct buffer *, size_t *) = {
[RESTYPE_DIRLISTING] = data_prepare_dirlisting_buf,
[RESTYPE_ERROR] = data_prepare_error_buf,
[RESTYPE_FILE] = data_prepare_file_buf,
};
static int
compareent(const struct dirent **d1, const struct dirent **d2)
{
int v;
v = ((*d2)->d_type == DT_DIR ? 1 : -1) -
((*d1)->d_type == DT_DIR ? 1 : -1);
if (v) {
return v;
}
return strcmp((*d1)->d_name, (*d2)->d_name);
}
static char *
suffix(int t)
{
switch (t) {
case DT_FIFO: return "|";
case DT_DIR: return "/";
case DT_LNK: return "@";
case DT_SOCK: return "=";
}
return "";
}
static void
html_escape(const char *src, char *dst, size_t dst_siz)
{
const struct {
char c;
char *s;
} escape[] = {
{ '&', "&amp;" },
{ '<', "&lt;" },
{ '>', "&gt;" },
{ '"', "&quot;" },
{ '\'', "&#x27;" },
};
size_t i, j, k, esclen;
for (i = 0, j = 0; src[i] != '\0'; i++) {
for (k = 0; k < LEN(escape); k++) {
if (src[i] == escape[k].c) {
break;
}
}
if (k == LEN(escape)) {
/* no escape char at src[i] */
if (j == dst_siz - 1) {
/* silent truncation */
break;
} else {
dst[j++] = src[i];
}
} else {
/* escape char at src[i] */
esclen = strlen(escape[k].s);
if (j >= dst_siz - esclen) {
/* silent truncation */
break;
} else {
memcpy(&dst[j], escape[k].s, esclen);
j += esclen;
}
}
}
dst[j] = '\0';
}
enum status
data_prepare_dirlisting_buf(const struct response *res,
struct buffer *buf, size_t *progress)
{
enum status s = 0;
struct dirent **e;
size_t i;
int dirlen;
char esc[PATH_MAX /* > NAME_MAX */ * 6]; /* strlen("&...;") <= 6 */
/* reset buffer */
memset(buf, 0, sizeof(*buf));
/* read directory */
if ((dirlen = scandir(res->internal_path, &e, NULL, compareent)) < 0) {
return S_FORBIDDEN;
}
if (*progress == 0) {
/* write listing header (sizeof(esc) >= PATH_MAX) */
html_escape(res->path, esc, MIN(PATH_MAX, sizeof(esc)));
if (buffer_appendf(buf,
"<!DOCTYPE html>\n<html>\n\t<head>"
"<title>Index of %s</title></head>\n"
"\t<body>\n\t\t<a href=\"..\">..</a>",
esc) < 0) {
s = S_REQUEST_TIMEOUT;
goto cleanup;
}
}
/* listing entries */
for (i = *progress; i < (size_t)dirlen; i++) {
/* skip hidden files, "." and ".." */
if (e[i]->d_name[0] == '.') {
continue;
}
/* entry line */
html_escape(e[i]->d_name, esc, sizeof(esc));
if (buffer_appendf(buf,
"<br />\n\t\t<a href=\"%s%s\">%s%s</a>",
esc,
(e[i]->d_type == DT_DIR) ? "/" : "",
esc,
suffix(e[i]->d_type))) {
/* buffer full */
break;
}
}
*progress = i;
if (*progress == (size_t)dirlen) {
/* listing footer */
if (buffer_appendf(buf, "\n\t</body>\n</html>\n") < 0) {
s = S_REQUEST_TIMEOUT;
goto cleanup;
}
(*progress)++;
}
cleanup:
while (dirlen--) {
free(e[dirlen]);
}
free(e);
return s;
}
enum status
data_prepare_error_buf(const struct response *res, struct buffer *buf,
size_t *progress)
{
/* reset buffer */
memset(buf, 0, sizeof(*buf));
if (*progress == 0) {
/* write error body */
if (buffer_appendf(buf,
"<!DOCTYPE html>\n<html>\n\t<head>\n"
"\t\t<title>%d %s</title>\n\t</head>\n"
"\t<body>\n\t\t<h1>%d %s</h1>\n"
"\t</body>\n</html>\n",
res->status, status_str[res->status],
res->status, status_str[res->status])) {
return S_INTERNAL_SERVER_ERROR;
}
(*progress)++;
}
return 0;
}
enum status
data_prepare_file_buf(const struct response *res, struct buffer *buf,
size_t *progress)
{
FILE *fp;
enum status s = 0;
ssize_t r;
size_t remaining;
/* reset buffer */
memset(buf, 0, sizeof(*buf));
/* open file */
if (!(fp = fopen(res->internal_path, "r"))) {
s = S_FORBIDDEN;
goto cleanup;
}
/* seek to lower bound + progress */
if (fseek(fp, res->file.lower + *progress, SEEK_SET)) {
s = S_INTERNAL_SERVER_ERROR;
goto cleanup;
}
/* read data into buf */
remaining = res->file.upper - res->file.lower + 1 - *progress;
while ((r = fread(buf->data + buf->len, 1,
MIN(sizeof(buf->data) - buf->len,
remaining), fp))) {
if (r < 0) {
s = S_INTERNAL_SERVER_ERROR;
goto cleanup;
}
buf->len += r;
*progress += r;
remaining -= r;
}
cleanup:
if (fp) {
fclose(fp);
}
return s;
}

+ 18
- 0
suckless/quark/data.h View File

@ -0,0 +1,18 @@
/* See LICENSE file for copyright and license details. */
#ifndef DATA_H
#define DATA_H
#include "http.h"
#include "util.h"
extern enum status (* const data_fct[])(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_dirlisting_buf(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_error_buf(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_file_buf(const struct response *,
struct buffer *, size_t *);
#endif /* DATA_H */

+ 1044
- 0
suckless/quark/http.c
File diff suppressed because it is too large
View File


+ 97
- 0
suckless/quark/http.h View File

@ -0,0 +1,97 @@
/* See LICENSE file for copyright and license details. */
#ifndef HTTP_H
#define HTTP_H
#include <limits.h>
#include <sys/socket.h>
#include "config.h"
#include "server.h"
#include "util.h"
enum req_field {
REQ_HOST,
REQ_RANGE,
REQ_IF_MODIFIED_SINCE,
NUM_REQ_FIELDS,
};
extern const char *req_field_str[];
enum req_method {
M_GET,
M_HEAD,
NUM_REQ_METHODS,
};
extern const char *req_method_str[];
struct request {
enum req_method method;
char path[PATH_MAX];
char query[FIELD_MAX];
char fragment[FIELD_MAX];
char field[NUM_REQ_FIELDS][FIELD_MAX];
};
enum status {
S_OK = 200,
S_PARTIAL_CONTENT = 206,
S_MOVED_PERMANENTLY = 301,
S_NOT_MODIFIED = 304,
S_BAD_REQUEST = 400,
S_FORBIDDEN = 403,
S_NOT_FOUND = 404,
S_METHOD_NOT_ALLOWED = 405,
S_REQUEST_TIMEOUT = 408,
S_RANGE_NOT_SATISFIABLE = 416,
S_REQUEST_TOO_LARGE = 431,
S_INTERNAL_SERVER_ERROR = 500,
S_VERSION_NOT_SUPPORTED = 505,
};
extern const char *status_str[];
enum res_field {
RES_ACCEPT_RANGES,
RES_ALLOW,
RES_LOCATION,
RES_LAST_MODIFIED,
RES_CONTENT_LENGTH,
RES_CONTENT_RANGE,
RES_CONTENT_TYPE,
NUM_RES_FIELDS,
};
extern const char *res_field_str[];
enum res_type {
RESTYPE_DIRLISTING,
RESTYPE_ERROR,
RESTYPE_FILE,
NUM_RES_TYPES,
};
struct response {
enum res_type type;
enum status status;
char field[NUM_RES_FIELDS][FIELD_MAX];
char path[PATH_MAX];
char internal_path[PATH_MAX];
struct vhost *vhost;
struct {
size_t lower;
size_t upper;
} file;
};
enum status http_prepare_header_buf(const struct response *, struct buffer *);
enum status http_send_buf(int, struct buffer *);
enum status http_recv_header(int, struct buffer *, int *);
enum status http_parse_header(const char *, struct request *);
void http_prepare_response(const struct request *, struct response *,
const struct server *);
void http_prepare_error_response(const struct request *,
struct response *, enum status);
#endif /* HTTP_H */

+ 364
- 0
suckless/quark/main.c View File

@ -0,0 +1,364 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <regex.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "arg.h"
#include "server.h"
#include "sock.h"
#include "util.h"
static char *udsname;
static void
cleanup(void)
{
if (udsname) {
sock_rem_uds(udsname);
}
}
static void
sigcleanup(int sig)
{
cleanup();
kill(0, sig);
_exit(1);
}
static void
handlesignals(void(*hdl)(int))
{
struct sigaction sa = {
.sa_handler = hdl,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
}
static void
usage(void)
{
const char *opts = "[-u user] [-g group] [-n num] [-d dir] [-l] "
"[-i file] [-v vhost] ... [-m map] ...";
die("usage: %s -p port [-h host] %s\n"
" %s -U file [-p port] %s", argv0,
opts, argv0, opts);
}
int
main(int argc, char *argv[])
{
struct group *grp = NULL;
struct passwd *pwd = NULL;
struct rlimit rlim;
struct server srv = {
.docindex = "index.html",
};
size_t i;
int insock, status = 0;
const char *err;
char *tok[4];
/* defaults */
size_t nthreads = 4;
size_t nslots = 64;
char *servedir = ".";
char *user = "nobody";
char *group = "nogroup";
ARGBEGIN {
case 'd':
servedir = EARGF(usage());
break;
case 'g':
group = EARGF(usage());
break;
case 'h':
srv.host = EARGF(usage());
break;
case 'i':
srv.docindex = EARGF(usage());
if (strchr(srv.docindex, '/')) {
die("The document index must not contain '/'");
}
break;
case 'l':
srv.listdirs = 1;
break;
case 'm':
if (spacetok(EARGF(usage()), tok, 3) || !tok[0] || !tok[1]) {
usage();
}
if (!(srv.map = reallocarray(srv.map, ++srv.map_len,
sizeof(struct map)))) {
die("reallocarray:");
}
srv.map[srv.map_len - 1].from = tok[0];
srv.map[srv.map_len - 1].to = tok[1];
srv.map[srv.map_len - 1].chost = tok[2];
break;
case 's':
err = NULL;
nslots = strtonum(EARGF(usage()), 1, INT_MAX, &err);
if (err) {
die("strtonum '%s': %s", EARGF(usage()), err);
}
break;
case 't':
err = NULL;
nthreads = strtonum(EARGF(usage()), 1, INT_MAX, &err);
if (err) {
die("strtonum '%s': %s", EARGF(usage()), err);
}
break;
case 'p':
srv.port = EARGF(usage());
break;
case 'U':
udsname = EARGF(usage());
break;
case 'u':
user = EARGF(usage());
break;
case 'v':
if (spacetok(EARGF(usage()), tok, 4) || !tok[0] || !tok[1] ||
!tok[2]) {
usage();
}
if (!(srv.vhost = reallocarray(srv.vhost, ++srv.vhost_len,
sizeof(*srv.vhost)))) {
die("reallocarray:");
}
srv.vhost[srv.vhost_len - 1].chost = tok[0];
srv.vhost[srv.vhost_len - 1].regex = tok[1];
srv.vhost[srv.vhost_len - 1].dir = tok[2];
srv.vhost[srv.vhost_len - 1].prefix = tok[3];
break;
default:
usage();
} ARGEND
if (argc) {
usage();
}
/* can't have both host and UDS but must have one of port or UDS*/
if ((srv.host && udsname) || !(srv.port || udsname)) {
usage();
}
if (udsname && (!access(udsname, F_OK) || errno != ENOENT)) {
die("UNIX-domain socket '%s': %s", udsname, errno ?
strerror(errno) : "File exists");
}
/* compile and check the supplied vhost regexes */
for (i = 0; i < srv.vhost_len; i++) {
if (regcomp(&srv.vhost[i].re, srv.vhost[i].regex,
REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
die("regcomp '%s': invalid regex",
srv.vhost[i].regex);
}
}
/* validate user and group */
errno = 0;
if (!user || !(pwd = getpwnam(user))) {
die("getpwnam '%s': %s", user ? user : "null",
errno ? strerror(errno) : "Entry not found");
}
errno = 0;
if (!group || !(grp = getgrnam(group))) {
die("getgrnam '%s': %s", group ? group : "null",
errno ? strerror(errno) : "Entry not found");
}
/* open a new process group */
setpgid(0, 0);
handlesignals(sigcleanup);
/*
* set the maximum number of open file descriptors as needed
* - 3 initial fd's
* - nthreads fd's for the listening socket
* - (nthreads * nslots) fd's for the connection-fd
* - (5 * nthreads) fd's for general purpose thread-use
*/
rlim.rlim_cur = rlim.rlim_max = 3 + nthreads + nthreads * nslots +
5 * nthreads;
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SYS_RESOURCE set, or are asking for more "
"file descriptors than the system can offer");
} else {
die("setrlimit:");
}
}
/*
* create the (non-blocking) listening socket
*
* we could use SO_REUSEPORT and create a listening socket for
* each thread (for better load-balancing, given each thread
* would get his own kernel-queue), but this increases latency
* (as a thread might get stuck on a larger request, making all
* other request wait in line behind it).
*
* socket contention with a single listening socket is a
* non-issue and thread-load-balancing is better fixed in the
* kernel by changing epoll-sheduling from a FIFO- to a
* LIFO-model, especially as it doesn't affect performance
*/
insock = udsname ? sock_get_uds(udsname, pwd->pw_uid, grp->gr_gid) :
sock_get_ips(srv.host, srv.port);
if (sock_set_nonblocking(insock)) {
return 1;
}
/*
* before dropping privileges, we fork, as we need to remove
* the UNIX-domain socket when we shut down, which we need
* privileges for
*/
switch (fork()) {
case -1:
warn("fork:");
break;
case 0:
/* restore default handlers */
handlesignals(SIG_DFL);
/* reap children automatically */
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
die("signal: Failed to set SIG_IGN on SIGCHLD");
}
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
die("signal: Failed to set SIG_IGN on SIGPIPE");
}
/*
* try increasing the thread-limit by the number
* of threads we need (which is the only reliable
* workaround I know given the thread-limit is per user
* rather than per process), but ignore EPERM errors,
* because this most probably means the user has already
* set the value to the kernel's limit, and there's not
* much we can do in any other case.
* There's also no danger of overflow as the value
* returned by getrlimit() is way below the limits of the
* rlim_t datatype.
*/
if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
die("getrlimit:");
}
if (rlim.rlim_max == RLIM_INFINITY) {
if (rlim.rlim_cur != RLIM_INFINITY) {
/* try increasing current limit by nthreads */
rlim.rlim_cur += nthreads;
}
} else {
/* try increasing current and hard limit by nthreads */
rlim.rlim_cur = rlim.rlim_max += nthreads;
}
if (setrlimit(RLIMIT_NPROC, &rlim) < 0 && errno != EPERM) {
die("setrlimit()");
}
/* limit ourselves to reading the servedir and block further unveils */
eunveil(servedir, "r");
eunveil(NULL, NULL);
/* chroot */
if (chdir(servedir) < 0) {
die("chdir '%s':", servedir);
}
if (chroot(".") < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SYS_CHROOT set");
} else {
die("chroot:");
}
}
/* drop root */
if (pwd->pw_uid == 0 || grp->gr_gid == 0) {
die("Won't run under root %s for hopefully obvious reasons",
(pwd->pw_uid == 0) ? (grp->gr_gid == 0) ?
"user and group" : "user" : "group");
}
if (setgroups(1, &(grp->gr_gid)) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETGID set");
} else {
die("setgroups:");
}
}
if (setgid(grp->gr_gid) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETGID set");
} else {
die("setgid:");
}
}
if (setuid(pwd->pw_uid) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETUID set");
} else {
die("setuid:");
}
}
if (udsname) {
epledge("stdio rpath proc unix", NULL);
} else {
epledge("stdio rpath proc inet", NULL);
}
/* accept incoming connections */
server_init_thread_pool(insock, nthreads, nslots, &srv);
exit(0);
default:
/* limit ourselves even further while we are waiting */
if (udsname) {
eunveil(udsname, "c");
eunveil(NULL, NULL);
epledge("stdio cpath", NULL);
} else {
eunveil("/", "");
eunveil(NULL, NULL);
epledge("stdio", NULL);
}
while (wait(&status) > 0)
;
}
cleanup();
return status;
}

+ 137
- 0
suckless/quark/quark.1 View File

@ -0,0 +1,137 @@
.Dd 2020-09-27
.Dt QUARK 1
.Os suckless.org
.Sh NAME
.Nm quark
.Nd simple static web server
.Sh SYNOPSIS
.Nm
.Fl p Ar port
.Op Fl h Ar host
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl s Ar num
.Op Fl t Ar num
.Op Fl d Ar dir
.Op Fl l
.Op Fl i Ar file
.Oo Fl v Ar vhost Oc ...
.Oo Fl m Ar map Oc ...
.Nm
.Fl U Ar file
.Op Fl p Ar port
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl s Ar num
.Op Fl t Ar num
.Op Fl d Ar dir
.Op Fl l
.Op Fl i Ar file
.Oo Fl v Ar vhost Oc ...
.Oo Fl m Ar map Oc ...
.Sh DESCRIPTION
.Nm
is a simple HTTP GET/HEAD-only web server for static content.
It supports virtual hosts (see
.Fl v ) ,
explicit redirects (see
.Fl m ) ,
directory listings (see
.Fl l ) ,
conditional "If-Modified-Since"-requests (RFC 7232), range requests
(RFC 7233) and well-known URIs (RFC 8615), while refusing to serve
hidden files and directories.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl d Ar dir
Serve
.Ar dir
after chrooting into it.
The default is ".".
.It Fl g Ar group
Set group ID when dropping privileges, and in socket mode the group of the
socket file, to the ID of
.Ar group .
The default is "nogroup".
.It Fl h Ar host
Use
.Ar host
as the server hostname.
The default is the loopback interface (i.e. localhost).
.It Fl i Ar file
Set
.Ar file
as the directory index.
The default is "index.html".
.It Fl l
Enable directory listing.
.It Fl m Ar map
Add the URI prefix mapping rule specified by
.Ar map ,
which has the form
.Qq Pa from to [chost] ,
where each element is separated with spaces (0x20) that can be
escaped with '\\'.
.Pp
The prefix
.Pa from
of all matching URIs is replaced with
.Pa to ,
optionally limited to the canonical virtual host
.Pa chost .
If no virtual hosts are given,
.Pa chost
is ignored.
.It Fl p Ar port
In host mode, listen on port
.Ar port
for incoming connections.
In socket mode, use
.Ar port
for constructing proper virtual host
redirects on non-standard ports.
.It Fl U Ar file
Create the UNIX-domain socket
.Ar file ,
listen on it for incoming connections and remove it on exit.
.It Fl s Ar num
Set the number of connection slots per worker thread to
.Ar num .
The default is 64.
.It Fl t Ar num
Set the number of worker threads to
.Ar num .
The default is 4.
.It Fl u Ar user
Set user ID when dropping privileges,
and in socket mode the user of the socket file,
to the ID of
.Ar user .
The default is "nobody".
.It Fl v Ar vhost
Add the virtual host specified by
.Ar vhost ,
which has the form
.Qq Pa chost regex dir [prefix] ,
where each element is separated with spaces (0x20) that can be
escaped with '\\'.
.Pp
A request matching the virtual host regular expression
.Pa regex
(see
.Xr regex 3 )
is redirected to the canonical host
.Pa chost ,
if they differ, using the directory
.Pa dir
as the root directory, optionally prefixing the URI with
.Pa prefix .
If any virtual hosts are specified, all requests on non-matching
hosts are discarded.
.El
.Sh CUSTOMIZATION
.Nm
can be customized by creating a custom config.h from config.def.h and
(re)compiling the source code. This keeps it fast, secure and simple.
.Sh AUTHORS
.An Laslo Hunhold Aq Mt dev@frign.de

+ 217
- 0
suckless/quark/queue.c View File

@ -0,0 +1,217 @@
/* See LICENSE file for copyright and license details. */
#include <stddef.h>
#ifdef __linux__
#include <sys/epoll.h>
#else
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif
#include "queue.h"
#include "util.h"
int
queue_create(void)
{
int qfd;
#ifdef __linux__
if ((qfd = epoll_create1(0)) < 0) {
warn("epoll_create1:");
}
#else
if ((qfd = kqueue()) < 0) {
warn("kqueue:");
}
#endif
return qfd;
}
int
queue_add_fd(int qfd, int fd, enum queue_event_type t, int shared,
const void *data)
{
#ifdef __linux__
struct epoll_event e;
/* set event flag */
if (shared) {
/*
* if the fd is shared, "exclusive" is the only
* way to avoid spurious wakeups and "blocking"
* accept()'s.
*/
e.events = EPOLLEXCLUSIVE;
} else {
/*
* if we have the fd for ourselves (i.e. only
* within the thread), we want to be
* edge-triggered, as our logic makes sure
* that the buffers are drained when we return
* to epoll_wait()
*/
e.events = EPOLLET;
}
switch (t) {
case QUEUE_EVENT_IN:
e.events |= EPOLLIN;
break;
case QUEUE_EVENT_OUT:
e.events |= EPOLLOUT;
break;
}
/* set data pointer */
e.data.ptr = (void *)data;
/* register fd in the interest list */
if (epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
int events;
/* prepare event flag */
events = (shared) ? 0 : EV_CLEAR;
switch (t) {
case QUEUE_EVENT_IN:
events |= EVFILT_READ;
break;
case QUEUE_EVENT_OUT:
events |= EVFILT_WRITE;
break;
}
EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
int
queue_mod_fd(int qfd, int fd, enum queue_event_type t, const void *data)
{
#ifdef __linux__
struct epoll_event e;
/* set event flag (only for non-shared fd's) */
e.events = EPOLLET;
switch (t) {
case QUEUE_EVENT_IN:
e.events |= EPOLLIN;
break;
case QUEUE_EVENT_OUT:
e.events |= EPOLLOUT;
break;
}
/* set data pointer */
e.data.ptr = (void *)data;
/* register fd in the interest list */
if (epoll_ctl(qfd, EPOLL_CTL_MOD, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
int events;
events = EV_CLEAR;
switch (t) {
case QUEUE_EVENT_IN:
events |= EVFILT_READ;
break;
case QUEUE_EVENT_OUT:
events |= EVFILT_WRITE;
break;
}
EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
int
queue_rem_fd(int qfd, int fd)
{
#ifdef __linux__
struct epoll_event e;
if (epoll_ctl(qfd, EPOLL_CTL_DEL, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
EV_SET(&e, fd, 0, EV_DELETE, 0, 0, 0);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
ssize_t
queue_wait(int qfd, queue_event *e, size_t elen)
{
ssize_t nready;
#ifdef __linux__
if ((nready = epoll_wait(qfd, e, elen, -1)) < 0) {
warn("epoll_wait:");
return -1;
}
#else
if ((nready = kevent(qfd, NULL, 0, e, elen, NULL)) < 0) {
warn("kevent:");
return -1;
}
#endif
return nready;
}
void *
queue_event_get_data(const queue_event *e)
{
#ifdef __linux__
return e->data.ptr;
#else
return e->udata;
#endif
}
int
queue_event_is_error(const queue_event *e)
{
#ifdef __linux__
return (e->events & ~(EPOLLIN | EPOLLOUT)) ? 1 : 0;
#else
return (e->flags & EV_EOF) ? 1 : 0;
#endif
}

+ 33
- 0
suckless/quark/queue.h View File

@ -0,0 +1,33 @@
#ifndef QUEUE_H
#define QUEUE_H
#include <stddef.h>
#ifdef __linux__
#include <sys/epoll.h>
typedef struct epoll_event queue_event;
#else
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
typedef struct kevent queue_event;
#endif
enum queue_event_type {
QUEUE_EVENT_IN,
QUEUE_EVENT_OUT,
};
int queue_create(void);
int queue_add_fd(int, int, enum queue_event_type, int, const void *);
int queue_mod_fd(int, int, enum queue_event_type, const void *);
int queue_rem_fd(int, int);
ssize_t queue_wait(int, queue_event *, size_t);
void *queue_event_get_data(const queue_event *);
int queue_event_is_error(const queue_event *e);
#endif /* QUEUE_H */

+ 177
- 0
suckless/quark/server.c View File

@ -0,0 +1,177 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "connection.h"
#include "queue.h"
#include "server.h"
#include "util.h"
struct worker_data {
int insock;
size_t nslots;
const struct server *srv;
};
static void *
server_worker(void *data)
{
queue_event *event = NULL;
struct connection *connection, *c, *newc;
struct worker_data *d = (struct worker_data *)data;
int qfd;
ssize_t nready;
size_t i;
/* allocate connections */
if (!(connection = calloc(d->nslots, sizeof(*connection)))) {
die("calloc:");
}
/* create event queue */
if ((qfd = queue_create()) < 0) {
exit(1);
}
/* add insock to the interest list (with data=NULL) */
if (queue_add_fd(qfd, d->insock, QUEUE_EVENT_IN, 1, NULL) < 0) {
exit(1);
}
/* allocate event array */
if (!(event = reallocarray(event, d->nslots, sizeof(*event)))) {
die("reallocarray:");
}
for (;;) {
/* wait for new activity */
if ((nready = queue_wait(qfd, event, d->nslots)) < 0) {
exit(1);
}
/* handle events */
for (i = 0; i < (size_t)nready; i++) {
c = queue_event_get_data(&event[i]);
if (queue_event_is_error(&event[i])) {
if (c != NULL) {
queue_rem_fd(qfd, c->fd);
c->res.status = 0;
connection_log(c);
connection_reset(c);
}
continue;
}
if (c == NULL) {
/* add new connection to the interest list */
if (!(newc = connection_accept(d->insock,
connection,
d->nslots))) {
/*
* the socket is either blocking
* or something failed.
* In both cases, we just carry on
*/
continue;
}
/*
* add event to the interest list
* (we want IN, because we start
* with receiving the header)
*/
if (queue_add_fd(qfd, newc->fd,
QUEUE_EVENT_IN,
0, newc) < 0) {
/* not much we can do here */
continue;
}
} else {
/* serve existing connection */
connection_serve(c, d->srv);
if (c->fd == 0) {
/* we are done */
memset(c, 0, sizeof(struct connection));
continue;
}
/*
* rearm the event based on the state
* we are "stuck" at
*/
switch(c->state) {
case C_RECV_HEADER:
if (queue_mod_fd(qfd, c->fd,
QUEUE_EVENT_IN,
c) < 0) {
connection_reset(c);
break;
}
break;
case C_SEND_HEADER:
case C_SEND_BODY:
if (queue_mod_fd(qfd, c->fd,
QUEUE_EVENT_OUT,
c) < 0) {
connection_reset(c);
break;
}
break;
default:
break;
}
}
}
}
return NULL;
}
void
server_init_thread_pool(int insock, size_t nthreads, size_t nslots,
const struct server *srv)
{
pthread_t *thread = NULL;
struct worker_data *d = NULL;
size_t i;
/* allocate worker_data structs */
if (!(d = reallocarray(d, nthreads, sizeof(*d)))) {
die("reallocarray:");
}
for (i = 0; i < nthreads; i++) {
d[i].insock = insock;
d[i].nslots = nslots;
d[i].srv = srv;
}
/* allocate and initialize thread pool */
if (!(thread = reallocarray(thread, nthreads, sizeof(*thread)))) {
die("reallocarray:");
}
for (i = 0; i < nthreads; i++) {
if (pthread_create(&thread[i], NULL, server_worker, &d[i]) != 0) {
if (errno == EAGAIN) {
die("You need to run as root or have "
"CAP_SYS_RESOURCE set, or are trying "
"to create more threads than the "
"system can offer");
} else {
die("pthread_create:");
}
}
}
/* wait for threads */
for (i = 0; i < nthreads; i++) {
if ((errno = pthread_join(thread[i], NULL))) {
warn("pthread_join:");
}
}
}

+ 35
- 0
suckless/quark/server.h View File

@ -0,0 +1,35 @@
/* See LICENSE file for copyright and license details. */
#ifndef SERVER_H
#define SERVER_H
#include <regex.h>
#include <stddef.h>
struct vhost {
char *chost;
char *regex;
char *dir;
char *prefix;
regex_t re;
};
struct map {
char *chost;
char *from;
char *to;
};
struct server {
char *host;
char *port;
char *docindex;
int listdirs;
struct vhost *vhost;
size_t vhost_len;
struct map *map;
size_t map_len;
};
void server_init_thread_pool(int, size_t, size_t, const struct server *);
#endif /* SERVER_H */

+ 209
- 0
suckless/quark/sock.c View File

@ -0,0 +1,209 @@
/* See LICENSE file for copyright and license details. */
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <unistd.h>
#include "sock.h"
#include "util.h"
int
sock_get_ips(const char *host, const char* port)
{
struct addrinfo hints = {
.ai_flags = AI_NUMERICSERV,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *ai, *p;
int ret, insock = 0;
if ((ret = getaddrinfo(host, port, &hints, &ai))) {
die("getaddrinfo: %s", gai_strerror(ret));
}
for (p = ai; p; p = p->ai_next) {
if ((insock = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) < 0) {
continue;
}
if (setsockopt(insock, SOL_SOCKET, SO_REUSEADDR,
&(int){1}, sizeof(int)) < 0) {
die("setsockopt:");
}
if (bind(insock, p->ai_addr, p->ai_addrlen) < 0) {
/* bind failed, close the insock and retry */
if (close(insock) < 0) {
die("close:");
}
continue;
}
break;
}
freeaddrinfo(ai);
if (!p) {
/* we exhaustet the addrinfo-list and found no connection */
if (errno == EACCES) {
die("You need to run as root or have "
"CAP_NET_BIND_SERVICE set to bind to "
"privileged ports");
} else {
die("bind:");
}
}
if (listen(insock, SOMAXCONN) < 0) {
die("listen:");
}
return insock;
}
int
sock_get_uds(const char *udsname, uid_t uid, gid_t gid)
{
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
size_t udsnamelen;
int insock, sockmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
if ((insock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
die("socket:");
}
if ((udsnamelen = strlen(udsname)) > sizeof(addr.sun_path) - 1) {
die("UNIX-domain socket name truncated");
}
memcpy(addr.sun_path, udsname, udsnamelen + 1);
if (bind(insock, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
die("bind '%s':", udsname);
}
if (listen(insock, SOMAXCONN) < 0) {
sock_rem_uds(udsname);
die("listen:");
}
if (chmod(udsname, sockmode) < 0) {
sock_rem_uds(udsname);
die("chmod '%s':", udsname);
}
if (chown(udsname, uid, gid) < 0) {
sock_rem_uds(udsname);
die("chown '%s':", udsname);
}
return insock;
}
void
sock_rem_uds(const char *udsname)
{
if (unlink(udsname) < 0) {
die("unlink '%s':", udsname);
}
}
int
sock_set_timeout(int fd, int sec)
{
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
warn("setsockopt:");
return 1;
}
return 0;
}
int
sock_set_nonblocking(int fd)
{
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
warn("fcntl:");
return 1;
}
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) {
warn("fcntl:");
return 1;
}
return 0;
}
int
sock_get_inaddr_str(const struct sockaddr_storage *in_sa, char *str,
size_t len)
{
switch (in_sa->ss_family) {
case AF_INET:
if (!inet_ntop(AF_INET,
&(((struct sockaddr_in *)in_sa)->sin_addr),
str, len)) {
warn("inet_ntop:");
return 1;
}
break;
case AF_INET6:
if (!inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)in_sa)->sin6_addr),
str, len)) {
warn("inet_ntop:");
return 1;
}
break;
case AF_UNIX:
snprintf(str, len, "uds");
break;
default:
snprintf(str, len, "-");
}
return 0;
}
int
sock_same_addr(const struct sockaddr_storage *sa1, const struct sockaddr_storage *sa2)
{
/* return early if address-families don't match */
if (sa1->ss_family != sa2->ss_family) {
return 0;
}
switch (sa1->ss_family) {
case AF_INET6:
return memcmp(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr,
((struct sockaddr_in6 *)sa2)->sin6_addr.s6_addr,
sizeof(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr));
case AF_INET:
return ntohl(((struct sockaddr_in *)sa1)->sin_addr.s_addr) ==
ntohl(((struct sockaddr_in *)sa2)->sin_addr.s_addr);
default: /* AF_UNIX */
return strcmp(((struct sockaddr_un *)sa1)->sun_path,
((struct sockaddr_un *)sa2)->sun_path) == 0;
}
}

+ 18
- 0
suckless/quark/sock.h View File

@ -0,0 +1,18 @@
/* See LICENSE file for copyright and license details. */
#ifndef SOCK_H
#define SOCK_H
#include <stddef.h>
#include <sys/socket.h>
#include <sys/types.h>
int sock_get_ips(const char *, const char *);
int sock_get_uds(const char *, uid_t, gid_t);
void sock_rem_uds(const char *);
int sock_set_timeout(int, int);
int sock_set_nonblocking(int);
int sock_get_inaddr_str(const struct sockaddr_storage *, char *, size_t);
int sock_same_addr(const struct sockaddr_storage *,
const struct sockaddr_storage *);
#endif /* SOCK_H */

+ 281
- 0
suckless/quark/util.c View File

@ -0,0 +1,281 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#ifdef __OpenBSD__
#include <unistd.h>
#endif /* __OpenBSD__ */
#include "util.h"
char *argv0;
static void
verr(const char *fmt, va_list ap)
{
if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
fprintf(stderr, "%s: ", argv0);
}
vfprintf(stderr, fmt, ap);
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(fmt, ap);
va_end(ap);
}
void
die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(fmt, ap);
va_end(ap);
exit(1);
}
void
epledge(const char *promises, const char *execpromises)
{
(void)promises;
(void)execpromises;
#ifdef __OpenBSD__
if (pledge(promises, execpromises) == -1) {
die("pledge:");
}
#endif /* __OpenBSD__ */
}
void
eunveil(const char *path, const char *permissions)
{
(void)path;
(void)permissions;
#ifdef __OpenBSD__
if (unveil(path, permissions) == -1) {
die("unveil:");
}
#endif /* __OpenBSD__ */
}
int
timestamp(char *buf, size_t len, time_t t)
{
struct tm tm;
if (gmtime_r(&t, &tm) == NULL ||
strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
return 1;
}
return 0;
}
int
esnprintf(char *str, size_t size, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(str, size, fmt, ap);
va_end(ap);
return (ret < 0 || (size_t)ret >= size);
}
int
prepend(char *str, size_t size, const char *prefix)
{
size_t len = strlen(str), prefixlen = strlen(prefix);
if (len + prefixlen + 1 > size) {
return 1;
}
memmove(str + prefixlen, str, len + 1);
memcpy(str, prefix, prefixlen);
return 0;
}
int
spacetok(const char *s, char **t, size_t tlen)
{
const char *tok;
size_t i, j, toki, spaces;
/* fill token-array with NULL-pointers */
for (i = 0; i < tlen; i++) {
t[i] = NULL;
}
toki = 0;
/* don't allow NULL string or leading spaces */
if (!s || *s == ' ') {
return 1;
}
start:
/* skip spaces */
for (; *s == ' '; s++)
;
/* don't allow trailing spaces */
if (*s == '\0') {
goto err;
}
/* consume token */
for (tok = s, spaces = 0; ; s++) {
if (*s == '\\' && *(s + 1) == ' ') {
spaces++;
s++;
continue;
} else if (*s == ' ') {
/* end of token */
goto token;
} else if (*s == '\0') {
/* end of string */
goto token;
}
}
token:
if (toki >= tlen) {
goto err;
}
if (!(t[toki] = malloc(s - tok - spaces + 1))) {
die("malloc:");
}
for (i = 0, j = 0; j < s - tok - spaces + 1; i++, j++) {
if (tok[i] == '\\' && tok[i + 1] == ' ') {
i++;
}
t[toki][j] = tok[i];
}
t[toki][s - tok - spaces] = '\0';
toki++;
if (*s == ' ') {
s++;
goto start;
}
return 0;
err:
for (i = 0; i < tlen; i++) {
free(t[i]);
t[i] = NULL;
}
return 1;
}
#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3
long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
int error = 0;
char *ep;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval) {
error = INVALID;
} else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return ll;
}
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}
int
buffer_appendf(struct buffer *buf, const char *suffixfmt, ...)
{
va_list ap;
int ret;
va_start(ap, suffixfmt);
ret = vsnprintf(buf->data + buf->len,
sizeof(buf->data) - buf->len, suffixfmt, ap);
va_end(ap);
if (ret < 0 || (size_t)ret >= (sizeof(buf->data) - buf->len)) {
/* truncation occured, discard and error out */
memset(buf->data + buf->len, 0,
sizeof(buf->data) - buf->len);
return 1;
}
/* increase buffer length by number of bytes written */
buf->len += ret;
return 0;
}

+ 42
- 0
suckless/quark/util.h View File

@ -0,0 +1,42 @@
/* See LICENSE file for copyright and license details. */
#ifndef UTIL_H
#define UTIL_H
#include <regex.h>
#include <stddef.h>
#include <time.h>
#include "config.h"
/* general purpose buffer */
struct buffer {
char data[BUFFER_SIZE];
size_t len;
};
#undef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#undef LEN
#define LEN(x) (sizeof (x) / sizeof *(x))
extern char *argv0;
void warn(const char *, ...);
void die(const char *, ...);
void epledge(const char *, const char *);
void eunveil(const char *, const char *);
int timestamp(char *, size_t, time_t);
int esnprintf(char *, size_t, const char *, ...);
int prepend(char *, size_t, const char *);
int spacetok(const char *, char **, size_t);
void *reallocarray(void *, size_t, size_t);
long long strtonum(const char *, long long, long long, const char **);
int buffer_appendf(struct buffer *, const char *, ...);
#endif /* UTIL_H */

+ 1
- 1
xorg/xinitrc View File

@ -38,7 +38,7 @@ echo "on" > ~/.cache/dunst
echo "on" > ~/.cache/screensaver
dbus-update-activation-environment --systemd DISPLAY
picom --no-fading-openclose &
firefox-developer-edition app.daily.dev&
brave &
bitwarden-desktop &
curl 'http://yeetclock/setcolor?R=136&G=192&B=208' &
xbanish -t 2000 -s &


+ 2
- 1
zsh/profile View File

@ -1,3 +1,4 @@
# vim:ft=bash
# Environment variables
export GOPATH=$HOME/go
export _JAVA_AWT_WM_NONREPARENTING=1
@ -6,7 +7,7 @@ export ANDROID_HOME=~/Android/Sdk
export FLUTTER_HOME=~/flutter
export TMUX_PLUGIN_MANAGER_PATH=~/.tmux/plugins
export BORG_KEYS_DIR=~/.keys/borg
export BROWSER=firefox-developer-edition
export BROWSER=brave
export DEFAULT_RECIPIENT="yigitcolakoglu@hotmail.com"
export EDITOR=vim


Loading…
Cancel
Save