Skip to content

Instantly share code, notes, and snippets.

View color-helpers.ts
type RGB = [number, number, number];
export function parseRgb(color: RGB | string): RGB {
if (Array.isArray(color)) {
return color;
}
let c = color;
let m;
if (
@mrclay
mrclay / flush-iptables.sh
Created May 14, 2020
Flush IP tables and restart docker
View flush-iptables.sh
!/bin/bash
# Script is needed because my default firewall rules are messed up and after
# every restart, docker containers can't make connections to the host, notably
# preventing debuggers like xdebug from attaching.
set -euo pipefail
# Unless docker is stopped with no containers running, docker will leave zombie
# proxy processes that hold the ports open preventing the start of new containers.
@mrclay
mrclay / usePrevious.ts
Created May 5, 2020
usePrevious in TypeScript with init value
View usePrevious.ts
import { useEffect, useRef } from 'react';
export default function usePrevious<T, U>(value: T, init: U): T | U {
const ref = useRef<T | U>(init);
useEffect(() => {
ref.current = value;
});
return ref.current;
}
@mrclay
mrclay / exceljs-extras.js
Last active Nov 20, 2019
Convert Exceljs rich text values to HTML or plaintext strings
View exceljs-extras.js
function isRichValue(value) {
return Boolean(value && Array.isArray(value.richText));
}
function richToString(rich) {
return rich.richText.map(({ text }) => text).join('');
}
function richToHtml(rich) {
let str = rich.richText.map(({ font = {}, text }) => {
@mrclay
mrclay / dclogs.sh
Created Aug 21, 2019
docker-compose logs -f but auto restarting
View dclogs.sh
function dclogs {
while :
do
docker-compose logs -f --tail=3
[ $? -eq 0 ] || break
echo "Awaiting a container to restart"
sleep 5
# wait around for startup
@mrclay
mrclay / fewest-meetings.js
Last active Aug 13, 2019
Exercise: From given list of meetings of varying lengths, find the shortest number of meetings that can fit in the day
View fewest-meetings.js
// Recursively create all combinations of the remaining items--at least those
// that are valid and aren't longer than those we've tested so far.
function buildCombinations(remaining, combo, process) {
process.recordIteration();
for (let i = 0; i < remaining.length; i++) {
if (process.isDone()) {
// global short-circuit
return;
}
@mrclay
mrclay / ClassList.php
Created Dec 9, 2017
HTML class list based on DOMTokenList
View ClassList.php
<?php
namespace MrClay;
/**
* HTML class list based on DOMTokenList
*
* @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
*/
class ClassList
@mrclay
mrclay / AjaxForm.js
Created Nov 11, 2015
Sets up Drupal so that any form can be fetched and submitted over Ajax. Unlike Drupal's ajax module, there are no modifications required to the form at all. Even redirects are captured and sent back to the client.
View AjaxForm.js
/**
* Notes:
* - This is not the complete JS module
*/
/**
* An object to simplify fetching Drupal forms via Ajax
*
* @param {object} spec Object with keys:
*
@mrclay
mrclay / elgg-profile-queries.php
Last active Oct 21, 2015
Elgg: profile MySQL queries on Elgg 1.10 - 1.x
View elgg-profile-queries.php
<?php
/**
* Query profiler for Elgg 1.10-1.12
*
* Require this script inside settings.php and the JavaScript console will report all
* queries with their time in seconds, and the total time spent in mysql_query().
*
* This will not include queries performed after the "output", "page" hook.
*
* On production you could include this only if a particular query string is set:
View wp_xss_20150426.md

More details on the WordPress XSS vulnerability found by Klikki. Both real exploits include a style attribute to widen the mouseover area to the whole viewport; I've left it out here to keep it simple.

The exploit comment is valid HTML and won't be altered by an HTML santizer:

<a title='x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAAA...[64 kb]..AAA'></a>

But once truncated by MySQL, the comment will become malformed HTML (note the attribute is left open):

<a title='x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA
You can’t perform that action at this time.