summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/cllogger15
-rw-r--r--scripts/export-html.pl90
-rw-r--r--scripts/export-ical.pl102
-rw-r--r--scripts/ical2org.awk391
-rw-r--r--scripts/keepassx2pass_csv.py186
-rw-r--r--scripts/nextcloud-data-persmissions.sh7
-rw-r--r--scripts/org-gcal-sync32
-rw-r--r--scripts/top_ten_directories.sh2
-rwxr-xr-xscripts/wireless_fix.sh7
9 files changed, 832 insertions, 0 deletions
diff --git a/scripts/cllogger b/scripts/cllogger
new file mode 100644
index 0000000..e13941f
--- /dev/null
+++ b/scripts/cllogger
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# We want to log stuff on a text file when there are interesting commands or snippets on the command line
+
+LOGFILE=/home/lemon/ownCloud/Textnotes/commandline_stuff.txt
+
+if [ $# -ne 1 ]; then
+ echo "You need to include a fucking string. Your message?"
+ exit 1
+fi
+
+echo $1
+echo $1 >> $LOGFILE
+
+echo "Ok, I've written that to the end of $LOGFILE."
diff --git a/scripts/export-html.pl b/scripts/export-html.pl
new file mode 100644
index 0000000..48aa96c
--- /dev/null
+++ b/scripts/export-html.pl
@@ -0,0 +1,90 @@
+#! /usr/bin/perl
+################################################################################
+##
+## Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez.
+##
+## 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.
+##
+## http://www.opensource.org/licenses/mit-license.php
+##
+################################################################################
+
+use strict;
+use warnings;
+
+# Give a nice error if the (non-standard) JSON module is not installed.
+eval "use JSON";
+if ($@)
+{
+ print "Error: You need to install the JSON Perl module.\n";
+ exit 1;
+}
+
+# Use the taskwarrior 2.0+ export command to filter and return JSON
+my $command = join (' ', ("env PATH='$ENV{PATH}' task rc.verbose=nothing rc.json.array=no export", @ARGV));
+if ($command =~ /No matches/)
+{
+ printf STDERR $command;
+ exit 1;
+}
+
+# Generate output.
+print "<html>\n",
+ " <body>\n",
+ " <table>\n",
+ " <thead>\n",
+ " <tr>\n",
+ " <td>ID</td>\n",
+ " <td>Pri</td>\n",
+ " <td>Description</td>\n",
+ " <td>Project</td>\n",
+ " <td>Due</td>\n",
+ " </tr>\n",
+ " </thead>\n",
+ " <tbody>\n";
+
+my $count = 0;
+for my $task (split "\n", qx{$command})
+{
+ ++$count;
+ my $data = from_json ($task);
+
+ print " <tr>\n",
+ " <td>", ($data->{'id'} || ''), "</td>\n",
+ " <td>", ($data->{'priority'} || ''), "</td>\n",
+ " <td>", ($data->{'description'} || ''), "</td>\n",
+ " <td>", ($data->{'project'} || ''), "</td>\n",
+ " <td>", ($data->{'due'} || ''), "</td>\n",
+ " </tr>\n";
+}
+
+print " </tbody>\n",
+ " <tfooter>\n",
+ " <tr>\n",
+ " <td>", $count, " matching tasks</td>\n",
+ " </tr>\n",
+ " </tfooter>\n",
+ " </table>\n",
+ " </body>\n",
+ "</html>\n";
+
+exit 0;
+
+################################################################################
+
diff --git a/scripts/export-ical.pl b/scripts/export-ical.pl
new file mode 100644
index 0000000..594feea
--- /dev/null
+++ b/scripts/export-ical.pl
@@ -0,0 +1,102 @@
+#! /usr/bin/perl
+################################################################################
+##
+## Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez.
+##
+## 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.
+##
+## http://www.opensource.org/licenses/mit-license.php
+##
+################################################################################
+
+use strict;
+use warnings;
+
+# Give a nice error if the (non-standard) JSON module is not installed.
+eval "use JSON";
+if ($@)
+{
+ print "Error: You need to install the JSON Perl module.\n";
+ exit 1;
+}
+
+# Use the taskwarrior 2.0+ export command to filter and return JSON
+my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV));
+if ($command =~ /No matches/)
+{
+ printf STDERR $command;
+ exit 1;
+}
+
+# Generate output.
+print "BEGIN:VCALENDAR\n",
+ "VERSION:2.0\n",
+ "PRODID:=//GBF/taskwarrior 1.9.4//EN\n";
+
+for my $task (split "\n", qx{$command})
+{
+ my $data = from_json ($task);
+
+ print "BEGIN:VTODO\n";
+ print "UID:$data->{'uuid'}\n";
+ print "DTSTAMP:$data->{'entry'}\n";
+ print "DTSTART:$data->{'start'}\n" if exists $data->{'start'};
+ print "DUE:$data->{'due'}\n" if exists $data->{'due'};
+ print "COMPLETED:$data->{'end'}\n" if exists $data->{'end'};
+ print "SUMMARY:$data->{'description'}\n";
+ print "CLASS:PRIVATE\n";
+ print "CATEGORIES:", join (',', @{$data->{'tags'}}), "\n" if exists $data->{'tags'};
+
+ # Priorities map to a 1-9 scale.
+ if (exists $data->{'priority'})
+ {
+ print "PRIORITY:", ($data->{'priority'} eq 'H' ? '1' :
+ $data->{'priority'} eq 'M' ? '5' :
+ '9'), "\n";
+ }
+
+ # Status maps differently.
+ my $status = $data->{'status'};
+ if ($status eq 'pending' || $status eq 'waiting')
+ {
+ print "STATUS:", (exists $data->{'start'} ? 'IN-PROCESS' : 'NEEDS-ACTION'), "\n";
+ }
+ elsif ($status eq 'completed')
+ {
+ print "STATUS:COMPLETED\n";
+ }
+ elsif ($status eq 'deleted')
+ {
+ print "STATUS:CANCELLED\n";
+ }
+
+ # Annotations become comments.
+ if (exists $data->{'annotations'})
+ {
+ print "COMMENT:$_->{'description'}\n" for @{$data->{'annotations'}};
+ }
+
+ print "END:VTODO\n";
+}
+
+print "END:VCALENDAR\n";
+exit 0;
+
+################################################################################
+
diff --git a/scripts/ical2org.awk b/scripts/ical2org.awk
new file mode 100644
index 0000000..6b1996f
--- /dev/null
+++ b/scripts/ical2org.awk
@@ -0,0 +1,391 @@
+#!/usr/bin/awk -f
+# awk script for converting an iCal formatted file to a sequence of org-mode headings.
+# this may not work in general but seems to work for day and timed events from Google's
+# calendar, which is really all I need right now...
+#
+# usage:
+# awk -f THISFILE < icalinputfile.ics > orgmodeentries.org
+#
+# Note: change org meta information generated below for author and
+# email entries!
+#
+# Caveats:
+#
+# - date entries with no time specified are assumed to be local time zone;
+# same remark for date entries that do have a time but do not end with Z
+# e.g.: 20130101T123456 is local and will be kept as 2013-01-01 12:34
+# where 20130223T123422Z is UTC and will be corrected appropriately
+#
+# - UTC times are changed into local times, using the time zone of the
+# computer that runs the script; it would be very hard in an awk script
+# to respect the time zone of a file belonging to another time zone:
+# the offsets will be different as well as the switchover time(s);
+# (consider a remote shell to a computer with the file's time zone)
+#
+# - the UTC conversion entirely relies on the built-in strftime method;
+# the author is not responsible for any erroneous conversions nor the
+# consequence of such conversions
+#
+# - does process RRULE recurring events, but ignores COUNT specifiers
+#
+# - does not process EXDATE to exclude date(s) from recurring events
+#
+# Eric S Fraga
+# 20100629 - initial version
+# 20100708 - added end times to timed events
+# - adjust times according to time zone information
+# - fixed incorrect transfer for entries with ":" embedded within the text
+# - added support for multi-line summary entries (which become headlines)
+# 20100709 - incorporated time zone identification
+# - fixed processing of continuation lines as Google seems to
+# have changed, in the last day, the number of spaces at
+# the start of the line for each continuation...
+# - remove backslashes used to protect commas in iCal text entries
+# no further revision log after this as the file was moved into a git
+# repository...
+#
+# Updated by: Guido Van Hoecke <guivhoATgmailDOTcom>
+# Last change: 2013.05.26 14:28:33
+#----------------------------------------------------------------------------------
+
+BEGIN {
+ ### config section
+
+ # maximum age in days for entries to be output: set this to -1 to
+ # get all entries or to N>0 to only get enties that start or end
+ # less than N days ago
+ max_age = 7;
+
+ # set to 1 or 0 to yes or not output a header block with TITLE,
+ # AUTHOR, EMAIL etc...
+ header = 1;
+
+ # set to 1 or 0 to yes or not output the original ical preamble as
+ # comment
+ preamble = 1;
+
+ # set to 1 to output time and summary as one line starting with
+ # the time (value 1) or to 0 to output the summary as first line
+ # and the date and time info as a second line
+ condense = 0;
+
+ # set to 1 or 0 to yes or not output the original ical entry as a
+ # comment (mostly useful for debugging purposes)
+ original = 1;
+
+ # google truncates long subjects with ... which is misleading in
+ # an org file: it gives the unfortunate impression that an
+ # expanded entry is still collapsed; value 1 will trim those
+ # ... and value 0 doesn't touch them
+ trimdots = 1;
+
+ # change this to your name
+ author = "Matthew Lemon"
+
+ # and to your email address
+ emailaddress = "matthew.lemon@gmail.com"
+
+ ### end config section
+
+ # use a colon to separate the type of data line from the actual contents
+ FS = ":";
+
+ # we only need to preserve the original entry lines if either the
+ # preamble or original options are true
+ preserve = preamble || original
+ first = 1; # true until an event has been found
+ max_age_seconds = max_age*24*60*60
+
+ if (header) {
+ print "#+TITLE: Main Google calendar entries"
+ print "#+AUTHOR: ", author
+ print "#+EMAIL: ", emailaddress
+ print "#+DESCRIPTION: converted using the ical2org awk script"
+ print "#+CATEGORY: google"
+ print "#+STARTUP: hidestars"
+ print "#+STARTUP: overview"
+ print ""
+ }
+}
+
+# continuation lines (at least from Google) start with a space
+# if the continuation is after a description or a summary, append the entry
+# to the respective variable
+
+/^[ ]/ {
+ if (indescription) {
+ entry = entry gensub("\r", "", "g", gensub("^[ ]", "", "", $0));
+ } else if (insummary) {
+ summary = summary gensub("\r", "", "g", gensub("^[ ]", "", "", $0))
+ }
+ if (preserve)
+ icalentry = icalentry "\n" $0
+}
+
+/^BEGIN:VEVENT/ {
+ # start of an event: initialize global velues used for each event
+ date = "";
+ entry = ""
+ headline = ""
+ icalentry = "" # the full entry for inspection
+ id = ""
+ indescription = 0;
+ insummary = 0
+ intfreq = "" # the interval and frequency for repeating org timestamps
+ lasttimestamp = -1;
+ location = ""
+ rrend = ""
+ status = ""
+ summary = ""
+
+ # if this is the first event, output the preamble from the iCal file
+ if (first) {
+ if(preamble) {
+ print "* COMMENT original iCal preamble"
+ print gensub("\r", "", "g", icalentry)
+ }
+ if (preserve)
+ icalentry = ""
+ first = false;
+ }
+}
+
+# any line that starts at the left with a non-space character is a new data field
+
+/^[A-Z]/ {
+ # we do not copy DTSTAMP lines as they change every time you download
+ # the iCal format file which leads to a change in the converted
+ # org file as I output the original input. This change, which is
+ # really content free, makes a revision control system update the
+ # repository and confuses.
+ if (preserve)
+ if (! index("DTSTAMP", $1))
+ icalentry = icalentry "\n" $0
+ # this line terminates the collection of description and summary entries
+ indescription = 0;
+ insummary = 0;
+}
+
+# this type of entry represents a day entry, not timed, with date stamp YYYYMMDD
+
+/^DTSTART;VALUE=DATE/ {
+ date = datestring($2);
+}
+
+/^DTEND;VALUE=DATE/ {
+ time2 = datestring($2, 1);
+ if ( issameday )
+ time2 = ""
+}
+
+# this represents a timed entry with date and time stamp YYYYMMDDTHHMMSS
+# we ignore the seconds
+
+/^DTSTART[:;][^V]/ {
+ date = datetimestring($2);
+ # print date;
+}
+
+# and the same for the end date;
+
+/^DTEND[:;][^V]/ {
+ time2 = datetimestring($2);
+ if (substr(date,1,10) == substr(time2,1,10)) {
+ # timespan within same date, use one date with a time range
+ date = date "-" substr(time2, length(time2)-4)
+ time2 = ""
+ }
+}
+
+# repetition rule
+
+/^RRULE:FREQ=(DAILY|WEEKLY|MONTHLY|YEARLY)/ {
+ # get the d, w, m or y value
+ freq = tolower(gensub(/.*FREQ=(.).*/, "\\1", $0))
+ # get the interval, and use 1 if none specified
+ interval = $2 ~ /INTERVAL=/ ? gensub(/.*INTERVAL=([0-9]+);.*/, "\\1", $2) : 1
+ # get the enddate of the rule and use "" if none specified
+ rrend = $2 ~ /UNTIL=/ ? datestring(gensub(/.*UNTIL=([0-9]{8}).*/, "\\1", $2)) : ""
+ # build the repetitor vale as understood by org
+ intfreq = " +" interval freq
+ # if the repetition is daily, and there is an end date, drop the repetitor
+ # as that is the default
+ if (intfreq == " +1d" && time2 =="" && rrend != "")
+ intfreq = ""
+}
+
+# The description will the contents of the entry in org-mode.
+# this line may be continued.
+
+/^DESCRIPTION/ {
+ $1 = "";
+ entry = entry gensub("\r", "", "g", $0);
+ indescription = 1;
+}
+
+# the summary will be the org heading
+
+/^SUMMARY/ {
+ $1 = "";
+ summary = gensub("\r", "", "g", $0);
+
+ # trim trailing dots if requested by config option
+ if(trimdots && summary ~ /\.\.\.$/)
+ sub(/\.\.\.$/, "", summary)
+ insummary = 1;
+}
+
+# the unique ID will be stored as a property of the entry
+
+/^UID/ {
+ id = gensub("\r", "", "g", $2);
+}
+
+/^LOCATION/ {
+ location = gensub("\r", "", "g", $2);
+}
+
+/^STATUS/ {
+ status = gensub("\r", "", "g", $2);
+}
+
+# when we reach the end of the event line, we output everything we
+# have collected so far, creating a top level org headline with the
+# date/time stamp, unique ID property and the contents, if any
+
+/^END:VEVENT/ {
+ #output event
+ if(max_age<0 || ( lasttimestamp>0 && systime()<lasttimestamp+max_age_seconds ) )
+ {
+ # build org timestamp
+ if (intfreq != "")
+ date = date intfreq
+ if (time2 != "")
+ date = date ">--<" time2
+ else if (rrend != "")
+ date = date ">--<" rrend
+
+ # translate \n sequences to actual newlines and unprotect commas (,)
+ if (condense)
+ print "* <" date "> " gensub("^[ ]+", "", "", gensub("\\\\,", ",", "g", gensub("\\\\n", " ", "g", summary)))
+ else
+ print "* " gensub("^[ ]+", "", "", gensub("\\\\,", ",", "g", gensub("\\\\n", " ", "g", summary))) "\n<" date ">"
+ print ":PROPERTIES:"
+ print ":ID: " id
+ if(length(location))
+ print ":LOCATION: " location
+ if(length(status))
+ print ":STATUS: " status
+ print ":END:"
+
+ print ""
+ # translate \n sequences to actual newlines and unprotect commas (,)
+ if(length(entry)>1)
+ print gensub("^[ ]+", "", "", gensub("\\\\,", ",", "g", gensub("\\\\n", "\n", "g", entry)));
+
+ # output original entry if requested by 'original' config option
+ if (original)
+ print "** COMMENT original iCal entry\n", gensub("\r", "", "g", icalentry)
+ }
+}
+
+
+
+# funtion to convert an iCal time string 'yyyymmddThhmmss[Z]' into a
+# date time string as used by org, preferably including the short day
+# of week: 'yyyy-mm-dd day hh:mm' or 'yyyy-mm-dd hh:mm' if we cannot
+# define the day of the week
+
+function datetimestring(input)
+{
+ # print "________"
+ # print "input : " input
+ # convert the iCal Date+Time entry to a format that mktime can understand
+ spec = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])T([0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1 \\2 \\3 \\4 \\5 \\6", "g", input);
+ # print "spec :" spec
+
+ stamp = mktime(spec);
+ lasttimestamp = stamp;
+
+ if (stamp <= 0) {
+ # this is a date before the start of the epoch, so we cannot
+ # use strftime and will deliver a 'yyyy-mm-dd hh:mm' string
+ # without day of week; this assumes local time, and does not
+ # attempt UTC offset correction
+ spec = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])T([0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1-\\2-\\3 \\4:\\5", "g", input);
+ # print "==> spec:" spec;
+ return spec;
+ }
+
+ if (input ~ /[0-9]{8}T[0-9]{6}Z/ ) {
+ # this is an utc time;
+ # we need to correct the timestamp by the utc offset for this time
+ offset = strftime("%z", stamp)
+ pm = substr(offset,1,1) 1 # define multiplier +1 or -1
+ hh = substr(offset,2,2) * 3600 * pm
+ mm = substr(offset,4,2) * 60 * pm
+
+ # adjust the timestamp
+ stamp = stamp + hh + mm
+ }
+
+ return strftime("%Y-%m-%d %a %H:%M", stamp);
+}
+
+# function to convert an iCal date into an org date;
+# the optional parameter indicates whether this is an end date;
+# for single or multiple whole day events, the end date given by
+# iCal is the date of the first day after the event;
+# if the optional 'isenddate' parameter is non zero, this function
+# tries to reduce the given date by one day
+
+function datestring(input, isenddate)
+{
+ #convert the iCal string to a an mktime input string
+ spec = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1 \\2 \\3 00 00 00", "g", input);
+
+ # compute the nr of seconds after or before the epoch
+ # dates before the epoch will have a negative timestamp
+ # days after the epoch will have a positive timestamp
+ stamp = mktime(spec);
+
+ if (isenddate) {
+ # subtract 1 day from the timestamp
+ # note that this also works for dates before the epoch
+ stamp = stamp - 86400;
+
+ # register whether the end date is same as the start date
+ issameday = lasttimestamp == stamp
+ }
+ # save timestamp to allow for check of max_age
+ lasttimestamp = stamp
+
+ if (stamp < 0) {
+ # this date is before the epoch;
+ # the returned datestring will not have the short day of week string
+ # as strftime does not handle negative times;
+ # we have to construct the datestring directly from the input
+ if (isenddate) {
+ # we really should return the date before the input date, but strftime
+ # does not work with negative timestamp values; so we can not use it
+ # to obtain the string representation of the corrected timestamp;
+ # we have to return the date specified in the iCal input and we
+ # add time 00:00 to clarify this
+ return spec = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1-\\2-\\3 00:00", "g", input);
+ } else {
+ # just generate the desired representation of the input date, without time;
+ return gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1-\\2-\\3", "g", input);
+ }
+ }
+
+ # return the date and day of week
+ return strftime("%Y-%m-%d %a", stamp);
+}
+
+# Local Variables:
+# time-stamp-line-limit: 1000
+# time-stamp-format: "%04y.%02m.%02d %02H:%02M:%02S"
+# time-stamp-active: t
+# time-stamp-start: "Last change:[ \t]+"
+# time-stamp-end: "$"
+# End:
diff --git a/scripts/keepassx2pass_csv.py b/scripts/keepassx2pass_csv.py
new file mode 100644
index 0000000..c3bd288
--- /dev/null
+++ b/scripts/keepassx2pass_csv.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+
+# Copyright 2015 David Francoeur <dfrancoeur04@gmail.com>
+# Copyright 2017 Nathan Sommer <nsommer@wooster.edu>
+#
+# This file is licensed under the GPLv2+. Please see COPYING for more
+# information.
+#
+# KeePassX 2+ on Mac allows export to CSV. The CSV contains the following
+# headers:
+# "Group","Title","Username","Password","URL","Notes"
+#
+# By default the pass entry will have the path Group/Title/Username and will
+# have the following structure:
+#
+# <Password>
+# user: <Username>
+# url: <URL>
+# notes: <Notes>
+#
+# Any missing fields will be omitted from the entry. If Username is not present
+# the path will be Group/Title.
+#
+# The username can be left out of the path by using the --name_is_original
+# switch. Group and Title can be converted to lowercase using the --to_lower
+# switch. Groups can be excluded using the --exclude_groups option.
+#
+# Default usage: ./keepass2csv2pass.py input.csv
+#
+# To see the full usage: ./keepass2csv2pass.py -h
+
+import sys
+import csv
+import argparse
+from subprocess import Popen, PIPE
+
+
+class KeepassCSVArgParser(argparse.ArgumentParser):
+ """
+ Custom ArgumentParser class which prints the full usage message if the
+ input file is not provided.
+ """
+ def error(self, message):
+ print(message, file=sys.stderr)
+ self.print_help()
+ sys.exit(2)
+
+
+def pass_import_entry(path, data):
+ """Import new password entry to password-store using pass insert command"""
+ proc = Popen(['pass', 'insert', '--multiline', path], stdin=PIPE,
+ stdout=PIPE)
+ proc.communicate(data.encode('utf8'))
+ proc.wait()
+
+
+def confirmation(prompt):
+ """
+ Ask the user for 'y' or 'n' confirmation and return a boolean indicating
+ the user's choice. Returns True if the user simply presses enter.
+ """
+
+ prompt = '{0} {1} '.format(prompt, '(Y/n)')
+
+ while True:
+ user_input = input(prompt)
+
+ if len(user_input) > 0:
+ first_char = user_input.lower()[0]
+ else:
+ first_char = 'y'
+
+ if first_char == 'y':
+ return True
+ elif first_char == 'n':
+ return False
+
+ print('Please enter y or n')
+
+
+def insert_file_contents(filename, preparation_args):
+ """ Read the file and insert each entry """
+
+ entries = []
+
+ with open(filename, 'rU') as csv_in:
+ next(csv_in)
+ csv_out = (line for line in csv.reader(csv_in, dialect='excel'))
+ for row in csv_out:
+ path, data = prepare_for_insertion(row, **preparation_args)
+ if path and data:
+ entries.append((path, data))
+
+ if len(entries) == 0:
+ return
+
+ print('Entries to import:')
+
+ for (path, data) in entries:
+ print(path)
+
+ if confirmation('Proceed?'):
+ for (path, data) in entries:
+ pass_import_entry(path, data)
+ print(path, 'imported!')
+
+
+def prepare_for_insertion(row, name_is_username=True, convert_to_lower=False,
+ exclude_groups=None):
+ """Prepare a CSV row as an insertable string"""
+
+ group = escape(row[0])
+ name = escape(row[1])
+
+ # Bail if we are to exclude this group
+ if exclude_groups is not None:
+ for exclude_group in exclude_groups:
+ if exclude_group.lower() in group.lower():
+ return None, None
+
+ # The first component of the group is 'Root', which we do not need
+ group_components = group.split('/')[1:]
+
+ path = '/'.join(group_components + [name])
+
+ if convert_to_lower:
+ path = path.lower()
+
+ username = row[2]
+ password = row[3]
+ url = row[4]
+ notes = row[5]
+
+ if username and name_is_username:
+ path += '/' + username
+
+ data = '{}\n'.format(password)
+
+ if username:
+ data += 'user: {}\n'.format(username)
+
+ if url:
+ data += 'url: {}\n'.format(url)
+
+ if notes:
+ data += 'notes: {}\n'.format(notes)
+
+ return path, data
+
+
+def escape(str_to_escape):
+ """ escape the list """
+ return str_to_escape.replace(" ", "-")\
+ .replace("&", "and")\
+ .replace("[", "")\
+ .replace("]", "")
+
+
+def main():
+ description = 'Import pass entries from an exported KeePassX CSV file.'
+ parser = KeepassCSVArgParser(description=description)
+
+ parser.add_argument('--exclude_groups', nargs='+',
+ help='Groups to exclude when importing')
+ parser.add_argument('--to_lower', action='store_true',
+ help='Convert group and name to lowercase')
+ parser.add_argument('--name_is_original', action='store_true',
+ help='Use the original entry name instead of the '
+ 'username for the pass entry')
+ parser.add_argument('input_file', help='The CSV file to read from')
+
+ args = parser.parse_args()
+
+ preparation_args = {
+ 'convert_to_lower': args.to_lower,
+ 'name_is_username': not args.name_is_original,
+ 'exclude_groups': args.exclude_groups
+ }
+
+ input_file = args.input_file
+ print("File to read:", input_file)
+ insert_file_contents(input_file, preparation_args)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/nextcloud-data-persmissions.sh b/scripts/nextcloud-data-persmissions.sh
new file mode 100644
index 0000000..4156fa5
--- /dev/null
+++ b/scripts/nextcloud-data-persmissions.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+voldata='/home/lemon/Nextcloud/'
+
+printf "chmod Files and Directories\n"
+find ${voldata}/ -type f -print0 | xargs -0 chmod 0640
+find ${voldata}/ -type d -print0 | xargs -0 chmod 0750
+
diff --git a/scripts/org-gcal-sync b/scripts/org-gcal-sync
new file mode 100644
index 0000000..cd0880e
--- /dev/null
+++ b/scripts/org-gcal-sync
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# customize these
+WGET=/usr/bin/wget
+ICS2ORG=/home/lemon/bin/ical2org.awk
+WORK_ICSFILE=/home/lemon/ownCloud/org/work.ics
+WORK_ORGFILE=/home/lemon/ownCloud/org/work_cal.org
+WORK_URL=https://calendar.google.com/calendar/ical/matthew.lemon%40gmail.com/private-5b9d1efdec3e07b601e48e01e6b2d5c9/basic.ics
+
+HOME_ICSFILE=/home/lemon/ownCloud/org/home.ics
+HOME_ORGFILE=/home/lemon/ownCloud/org/home_cal.org
+HOME_URL=https://calendar.google.com/calendar/ical/12panp3nqdbmm9df4if9jigigo%40group.calendar.google.com/private-4b7e890b479d67c3cf66c4119c80ec63/basic.ics
+
+ONCALL_ICSFILE=/home/lemon/ownCloud/org/oncall.ics
+ONCALL_ORGFILE=/home/lemon/ownCloud/org/oncall_cal.org
+ONCALL_URL=https://calendar.google.com/calendar/ical/od5ch3rahhapi4e3sgkij8jkhg%40group.calendar.google.com/private-ee0dcd7197d05da273de5c32db73ac5d/basic.ics
+
+MYTASKSCALL_ICSFILE=/home/lemon/ownCloud/org/mytasks.ics
+MYTASKSCALL_ORGFILE=/home/lemon/ownCloud/org/mytasks_cal.org
+MYTASKSCALL_URL=https://calendar.google.com/calendar/ical/1egrujsm7tkp6unaenu2354mq4%40group.calendar.google.com/private-5d95863285306565a20aeb791d591f55/basic.ics
+# no customization needed below
+$WGET -O $WORK_ICSFILE $WORK_URL
+gawk -f $ICS2ORG $WORK_ICSFILE > $WORK_ORGFILE
+
+$WGET -O $HOME_ICSFILE $HOME_URL
+gawk -f $ICS2ORG $HOME_ICSFILE > $HOME_ORGFILE
+
+$WGET -O $ONCALL_ICSFILE $ONCALL_URL
+gawk -f $ICS2ORG $ONCALL_ICSFILE > $ONCALL_ORGFILE
+
+$WGET -O $MYTASKSCALL_ICSFILE $MYTASKSCALL_URL
+gawk -f $ICS2ORG $MYTASKSCALL_ICSFILE > $MYTASKSCALL_ORGFILE
diff --git a/scripts/top_ten_directories.sh b/scripts/top_ten_directories.sh
new file mode 100644
index 0000000..5da89cb
--- /dev/null
+++ b/scripts/top_ten_directories.sh
@@ -0,0 +1,2 @@
+#!/usr/bin
+sudo find . -type d -print0 | xargs -0 du | sort -n | tail -10 | cut -f2 | xargs -I{} du -sh {}
diff --git a/scripts/wireless_fix.sh b/scripts/wireless_fix.sh
new file mode 100755
index 0000000..7c6e32a
--- /dev/null
+++ b/scripts/wireless_fix.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo "Removing rtl8xxxu. Please wait.\n"
+modprobe -r rtl8xxxu
+sleep 20
+echo "Enabling rtl8xxxu. Please wait.\n"
+modprobe rtl8xxxu