Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d57c87e69d | |||
| c3eef703ab | |||
| 538302d69c | |||
| 9c87bd3f71 | |||
| 3d7fe8e045 | |||
| f2fbd4227a | |||
| 86ee3389bb | |||
| 29f22e4c7d | |||
| 6f15dda97a | |||
| f7c3e26500 | |||
| 61794a63e3 |
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15400"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@@ -620,7 +620,7 @@
|
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleSourceList:" target="Ady-hI-5gd" id="iwa-gc-5KM"/>
|
||||
<action selector="toggleSidebar:" target="Ady-hI-5gd" id="iwa-gc-5KM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
@@ -707,21 +707,21 @@
|
||||
<objects>
|
||||
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModule="AppReceiptValidator_Demo_macOS" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="631" height="270"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="698" height="270"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ynK-dw-fFc">
|
||||
<rect key="frame" x="0.0" y="22" width="316" height="248"/>
|
||||
<rect key="frame" x="0.0" y="71" width="349" height="199"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="yEL-yO-YvB">
|
||||
<rect key="frame" x="1" y="1" width="314" height="246"/>
|
||||
<rect key="frame" x="1" y="1" width="347" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView toolTip="Paste Base64 here" importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" textCompletion="NO" id="0xW-mT-lME" customClass="DropAcceptingTextView" customModule="AppReceiptValidator_Demo_macOS" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="314" height="246"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="347" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="314" height="246"/>
|
||||
<size key="minSize" width="347" height="197"/>
|
||||
<size key="maxSize" width="629" height="10000000"/>
|
||||
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
@@ -732,22 +732,22 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="hkR-e4-WtN">
|
||||
<rect key="frame" x="299" y="1" width="16" height="246"/>
|
||||
<rect key="frame" x="332" y="1" width="16" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<scrollView toolTip="Parsed Receipt will be shown here" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6mt-ay-mAL">
|
||||
<rect key="frame" x="316" y="0.0" width="315" height="270"/>
|
||||
<rect key="frame" x="349" y="0.0" width="349" height="270"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="YwZ-F9-Cvh">
|
||||
<rect key="frame" x="1" y="1" width="313" height="268"/>
|
||||
<rect key="frame" x="1" y="1" width="347" height="268"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" textCompletion="NO" id="GHT-gS-G1g" customClass="TextView" customModule="AppReceiptValidator_Demo_macOS" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="313" height="268"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="347" height="268"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="313" height="268"/>
|
||||
<size key="minSize" width="347" height="268"/>
|
||||
<size key="maxSize" width="463" height="10000000"/>
|
||||
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
@@ -758,46 +758,112 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="uk9-Sg-RUp">
|
||||
<rect key="frame" x="298" y="1" width="16" height="268"/>
|
||||
<rect key="frame" x="332" y="1" width="16" height="268"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yvX-By-nNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="316" height="22"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Optional DeviceIdentifier for Validation (MAC Address, UUID, Base64)" drawsBackground="YES" id="Z2r-sB-vIS">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<action selector="identifierDidChange:" target="XfG-lQ-9wD" id="ccM-mH-NPQ"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<stackView distribution="fill" orientation="vertical" alignment="leading" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X6E-h2-FTp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="349" height="71"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yvX-By-nNw">
|
||||
<rect key="frame" x="0.0" y="50" width="316" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Optional DeviceIdentifier for Validation (MAC Address, UUID, Base64)" drawsBackground="YES" id="Z2r-sB-vIS">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<action selector="identifierDidChange:" target="XfG-lQ-9wD" id="ccM-mH-NPQ"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<customView verticalHuggingPriority="251" verticalCompressionResistancePriority="749" translatesAutoresizingMaskIntoConstraints="NO" id="MIY-2Q-BBh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="276" height="50"/>
|
||||
<subviews>
|
||||
<stackView distribution="fill" orientation="horizontal" alignment="top" spacing="14" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Fk-0l-MkU">
|
||||
<rect key="frame" x="5" y="2" width="264" height="48"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="252" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3HO-XF-hNE">
|
||||
<rect key="frame" x="-2" y="32" width="122" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Local MAC Address" id="cII-wV-fEg">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MYU-Qf-vgG">
|
||||
<rect key="frame" x="130" y="32" width="37" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" title="Label" id="toH-92-xds">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7M8-eM-sps">
|
||||
<rect key="frame" x="173" y="20" width="97" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Reload" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="nhJ-Nu-6Mt">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="determineDeviceIdentifier:" target="XfG-lQ-9wD" id="0Iu-Ou-tt2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<visibilityPriorities>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
</visibilityPriorities>
|
||||
<customSpacing>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
</customSpacing>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="3Fk-0l-MkU" firstAttribute="top" secondItem="MIY-2Q-BBh" secondAttribute="top" id="G9h-eg-R7c"/>
|
||||
<constraint firstItem="3Fk-0l-MkU" firstAttribute="leading" secondItem="MIY-2Q-BBh" secondAttribute="leading" constant="5" id="XhE-X8-Yll"/>
|
||||
<constraint firstAttribute="bottom" secondItem="3Fk-0l-MkU" secondAttribute="bottom" constant="2" id="eS8-I6-F8I"/>
|
||||
<constraint firstAttribute="trailing" secondItem="3Fk-0l-MkU" secondAttribute="trailing" constant="7" id="u5d-kZ-Hiq"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<visibilityPriorities>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
</visibilityPriorities>
|
||||
<customSpacing>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
</customSpacing>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="6mt-ay-mAL" firstAttribute="leading" secondItem="yvX-By-nNw" secondAttribute="trailing" id="231-cE-39Q"/>
|
||||
<constraint firstItem="6mt-ay-mAL" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="CdY-lv-wee"/>
|
||||
<constraint firstItem="X6E-h2-FTp" firstAttribute="top" secondItem="ynK-dw-fFc" secondAttribute="bottom" id="0st-m4-dJZ"/>
|
||||
<constraint firstItem="ynK-dw-fFc" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="1Pf-3A-rBH"/>
|
||||
<constraint firstAttribute="bottom" secondItem="X6E-h2-FTp" secondAttribute="bottom" id="1kz-OO-S1i"/>
|
||||
<constraint firstItem="6mt-ay-mAL" firstAttribute="leading" secondItem="X6E-h2-FTp" secondAttribute="trailing" id="9Vb-5X-3ef"/>
|
||||
<constraint firstItem="ynK-dw-fFc" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="Cvz-FD-lzg"/>
|
||||
<constraint firstItem="yvX-By-nNw" firstAttribute="top" secondItem="ynK-dw-fFc" secondAttribute="bottom" id="KSy-yc-TCD"/>
|
||||
<constraint firstItem="ynK-dw-fFc" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="Rno-M6-Pjq"/>
|
||||
<constraint firstItem="6mt-ay-mAL" firstAttribute="width" secondItem="m2S-Jp-Qdl" secondAttribute="width" multiplier="1:2" id="SWu-Yn-pVc"/>
|
||||
<constraint firstAttribute="bottom" secondItem="yvX-By-nNw" secondAttribute="bottom" id="WOQ-2e-jWj"/>
|
||||
<constraint firstAttribute="trailing" secondItem="6mt-ay-mAL" secondAttribute="trailing" id="Yun-Rd-wsm"/>
|
||||
<constraint firstItem="6mt-ay-mAL" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="clC-xc-JDh"/>
|
||||
<constraint firstAttribute="bottom" secondItem="6mt-ay-mAL" secondAttribute="bottom" id="lKc-RV-ybx"/>
|
||||
<constraint firstItem="yvX-By-nNw" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="s2r-QB-ZQb"/>
|
||||
<constraint firstItem="ynK-dw-fFc" firstAttribute="width" secondItem="m2S-Jp-Qdl" secondAttribute="width" multiplier="1:2" id="wsI-iB-DvJ"/>
|
||||
<constraint firstItem="X6E-h2-FTp" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="ysr-U6-n9c"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="dropReceivingView" destination="0xW-mT-lME" id="cuR-H1-BKN"/>
|
||||
<outlet property="identifierTextField" destination="yvX-By-nNw" id="pW5-lJ-8Cy"/>
|
||||
<outlet property="inputTextView" destination="0xW-mT-lME" id="8Y7-yb-63r"/>
|
||||
<outlet property="localDeviceIdentifierLabel" destination="MYU-Qf-vgG" id="cqz-uf-16l"/>
|
||||
<outlet property="outputTextView" destination="GHT-gS-G1g" id="cVN-4m-knJ"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="75.5" y="726"/>
|
||||
<point key="canvasLocation" x="75" y="726"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
||||
@@ -18,6 +18,7 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextFieldDelegate
|
||||
@IBOutlet private var identifierTextField: NSTextField!
|
||||
@IBOutlet private var outputTextView: NSTextView!
|
||||
@IBOutlet private var dropReceivingView: DropAcceptingTextView!
|
||||
@IBOutlet private var localDeviceIdentifierLabel: NSTextField!
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
@@ -34,6 +35,7 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextFieldDelegate
|
||||
|
||||
self.identifierDidChange(self.identifierTextField)
|
||||
}
|
||||
self.renderLocalDeviceIdentifierText()
|
||||
}
|
||||
|
||||
// MARK: - NSTextViewDelegate
|
||||
@@ -55,6 +57,10 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextFieldDelegate
|
||||
func paste(_ sender: Any) {
|
||||
self.inputTextView.paste(sender)
|
||||
}
|
||||
|
||||
@IBAction func determineDeviceIdentifier(_ sender: Any) {
|
||||
self.renderLocalDeviceIdentifierText()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -113,9 +119,21 @@ private extension ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
func localDeviceIdentifierString() -> String {
|
||||
guard let device = AppReceiptValidator.Parameters.DeviceIdentifier.getPrimaryNetworkMACAddress() else { return "DeviceIdentifier could not be determined" }
|
||||
|
||||
return "\(device.addressString) (HEX), \(device.data.base64EncodedString()) (B64)"
|
||||
}
|
||||
|
||||
func render(string: String) {
|
||||
self.outputTextView.string = string
|
||||
}
|
||||
|
||||
func renderLocalDeviceIdentifierText() {
|
||||
NSLog("Local MAC Address: " + localDeviceIdentifierString())
|
||||
self.localDeviceIdentifierLabel.attributedStringValue =
|
||||
NSAttributedString(string: localDeviceIdentifierString())
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - TextView
|
||||
|
||||
@@ -62,11 +62,14 @@ extension AppReceiptValidator.Parameters {
|
||||
|
||||
case installedInMainBundle
|
||||
case data(Data)
|
||||
case dynamic(() -> Data?)
|
||||
|
||||
public func loadData() -> Data? {
|
||||
switch self {
|
||||
case .data(let data):
|
||||
return data
|
||||
case .dynamic(let maker):
|
||||
return maker()
|
||||
case .installedInMainBundle:
|
||||
guard let receiptUrl = Bundle.main.appStoreReceiptURL else { return nil }
|
||||
guard (try? receiptUrl.checkResourceIsReachable()) ?? false else { return nil }
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
import AppReceiptValidator.OpenSSL
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable file_length
|
||||
|
||||
/// Apple guide: https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Introduction.html
|
||||
///
|
||||
/// Original inspiration for the Code: https://github.com/andrewcbancroft/SwiftyLocalReceiptValidator/blob/master/ReceiptValidator.swift
|
||||
@@ -119,9 +117,6 @@ private extension AppReceiptValidator {
|
||||
var sha1Context = SHA_CTX()
|
||||
|
||||
SHA1_Init(&sha1Context)
|
||||
deviceIdentifierData.withUnsafeBytes { poi -> Void in
|
||||
print(poi)
|
||||
}
|
||||
_ = deviceIdentifierData.withUnsafeBytes { pointer -> Void in
|
||||
SHA1_Update(&sha1Context, pointer.baseAddress, deviceIdentifierData.count)
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ extension AppReceiptValidator.Parameters.DeviceIdentifier {
|
||||
/// Original implementation https://gist.github.com/mminer/82975d3781e2f42fc644d7fbfbf4f905
|
||||
///
|
||||
/// - Returns: The MAC Address as Data and String representation
|
||||
static func getPrimaryNetworkMACAddress() -> (data: Data, addressString: String)? {
|
||||
public static func getPrimaryNetworkMACAddress() -> (data: Data, addressString: String)? {
|
||||
let matching = IOServiceMatching("IOEthernetInterface") as NSMutableDictionary
|
||||
matching[kIOPropertyMatchKey] = ["IOPrimaryInterface": true]
|
||||
var servicesIterator: io_iterator_t = 0
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://github.com/Carthage/Carthage)
|
||||

|
||||

|
||||

|
||||
[](LICENSE)
|
||||
[](https://travis-ci.org/IdeasOnCanvas/AppReceiptValidator)
|
||||
[](https://twitter.com/hannesoid)
|
||||
|
||||
Reference in New Issue
Block a user