#!/bin/bash

# item-create reformats a new item, then adds it to mal.rec and to the
# relevant pages.

# Usage:
# - Check README.md in this directory if you haven't done so yet.
# - Write the new item to a file called "item" (item-start can be used
#   as a helper), or use the blank item that has been created by a
#   previous run.
# - Run item-create without argument.
#
# Note: item-create can't be used on an item that has been successfully
# added. Any further changes should be made in mal.rec, and pages should
# then be regenerated with malgen.

# Copyright (C) 2018, 2019 Free Software Foundation, Inc.

# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without any warranty.

# Written by Therese <thg@gnu.org> and Ineiev.


export LC_ALL=C
set -e

temp1=$(mktemp -t mal.XXXXXX) || (echo 1>&2 "Can't make temp1";  exit 1)
temp2=$(mktemp -t mal.XXXXXX) || (echo 1>&2 "Can't make temp2";  exit 1)
trap 'rm -f "$temp1" "$temp2"' EXIT

rm -f item.rec item.html mal.rec.temp *.html.temp

## Preliminary checks on 'item'

# List English pages in proprietary/.
pages=$(ls ../*.html |
        grep -Ev '\.([[:alpha:]]{2}-)?[[:alpha:]]{2}\.html$' |
        sed 's,^\.\./,,')

if [ ! -f item ]; then
  echo 1>&2 "!!! 'item' file doesn't exist."
  exit 1
fi
if [ ! -r item ]; then
  echo 1>&2 "!!! 'item' file isn't readable."
  exit 1
fi

files=$(awk '/Target:/ {print $2}' item)
if [ -z "$files" ]; then
  echo 1>&2 "!!! This item has no Target field.  It can't be added
    anywhere."
  exit 1
fi
if ! id=$(grep '^Id:' item); then
  echo 1>&2 "!!! This item doesn't have an Id."
  exit 1
fi
if [ `echo "$id" | wc -l` -gt 1 ]; then
  echo 1>&2 "!!! This item has multiple Id lines."
  exit 1
fi
if [ "$id" = 'Id: 200000000' ]; then
  echo 1>&2 "!!! This item still has the default Id."
  exit 1
fi
if echo "$id" | grep -Eqv '^Id: 20[0-9]{7}(\..)?$'; then
  echo 1>&2 "!!! This item has a malformed Id, '$id'."
  exit 1
fi
if echo "x$files" | sed '1s,.,,' | grep -q '^proprietary\.html$'; then
  echo 1>&2 "!!! proprietary.html is not a primary target for malware items."
  exit 1
fi
if grep -q "$id" mal.rec; then
  echo 1>&2 "!!! An item with same Id is already in mal.rec.
    - If the two items are different, please change the last digit.
    - If you are editing an item that has been added already, you should
    do it in mal.rec, and regenerate the pages with malgen. See README.md."
  exit 1
fi

wrong_files=$(echo "x$files" | sed '1s,.,,' | while read f; do
  if ! echo "x$pages" | sed '1s,.,,' | grep -q "^${f//./[.]}$"; then
    echo "    $f"
  fi
done)
if [ -n "$wrong_files" ]; then
  echo 1>&2 "!!! These pages don't exist:
$wrong_files"
  exit 1
fi

## Standardize the format.

# Remove comments, blank lines, linefeeds, leading & trailing spaces; unwrap.
sed -e 's,[ \t]*$,,' \
    -e '/^$/d; /^#/d' item |
sed ':a /Blurb:.*$/ { N; s,\(.\+\)\n\(.\+\)$,\1 \2,; ba }' |
sed 's,Blurb:[ \t]*,Blurb:\n,' > $temp1

# Reformat.
for tag in p dl dt dd ul ol li blockquote; do
  sed -i "s,[ \t]*\(<$tag[^>]*>\)[ \t]*\(.\),\1\2,g" $temp1
  sed -i "s,[ \t]*</$tag>[ \t]*,</$tag>,g" $temp1
done

sed -i -e 's,</p>\(<[^/]\),</p>\n\n\1,g' \
       -e 's,</blockquote><,</blockquote>\n\n<,g' \
       -e 's,\(</[ou]l>\)<,\n\1\n\n<,g' \
       -e 's,</li>\(</[ou]l>\),</li>\n\1,g' \
       -e 's,\(<[ou]l>\)<li>,\1\n<li>,g' \
       -e 's,</li><li>,</li>\n\n<li>,g' \
       -e 's,</dl><,\n</dl>\n\n<,g' \
       -e 's,</dt><dd>,</dt>\n<dd>,g' \
       -e 's,</dd><dt>,</dd>\n\n<dt>,g' \
       -e 's,<dl><dt>,<dl>\n<dt>,g' $temp1

for tag in p dl /dl ul /ul ol /ol blockquote; do
  sed -i "s,^<$tag,    <$tag," $temp1
done

for tag in dd dt li; do
  sed -i "s,^<$tag,      <$tag," $temp1
done

# Wrap the text.
fmt -s -w 76 $temp1 > $temp2

# Convert to rec format.
sed -e '/^Blurb:/ {N; s,\n[ ]\+<, <,}' \
    -e 's,^ ,+,' \
    -e 's,^$,+,' $temp2 > item.rec

# Create the 'Added' field.
today=$(date +'%Y-%m-%d')
sed -i "/^Id:/ s,^,\\nAdded: $today\\n", item.rec

it='<li id="M'${id#* }'"'

error_html=""
for f in $files proprietary.html; do
  # Check that the page doesn't already have an item with same Id.
  if grep -q "$it" ../$f; then
    echo "$it is already in $f."
  else
    # Check the target.
    target=$(sed "/^Target: ${f//./[.]} /{s/.* //;q};d" item.rec)
    # If no target id is specified, make sure the page only has one list.
    # Get the id for the second list.
    t2=$(awk 'BEGIN { RS = "" }'"/^Page: ${f//./[.]}\n/"'{ print $5 }' \
         targets.rec)

    # If there is one, the item can't be added. Switch error warning.
    if [ -z "$target" ] &&  [ -n "$t2" ]; then
      error_html=1
      echo 1>&2 "!!! $f: A target id should be specified."
    else
      # Otherwise, use the first target id.
      if [ -z "$target" ]; then
        target=$(awk 'BEGIN { RS = "" }'"/${f//./[.]}/"'{ print $4 }' \
                 targets.rec)
        # Add it to the Target field in mal.rec. This keeps the
        # regeneration script (malgen) simpler.
        sed -i "s,Target:[ \t]*${f//./[.]}[ \t]*$,Target: $f $target," item.rec
      fi
    fi
  fi
done
# Quit on errors.
if [ -n "$error_html" ]; then
  exit 2
fi

# Add the item to the recfile.
sed '/^# ADD NEW BLURB HERE/r item.rec' mal.rec > mal.rec.temp
if ! grep -q "$id" mal.rec.temp; then
  echo 1>&2 "!!! $id couldn't be added to mal.rec."
  exit 2
fi

mv mal.rec.temp mal.rec

./malgen $files proprietary.html all.html

# Emit a warning if addition fails.
error_html=""
for f in $files proprietary.html; do
  if ! grep -q "$it" ../$f; then
    echo 1>&2 "!!! $f:$it couldn't be added."
    error_html=1
  fi
done

# Make sure the added item isn't going to be reused for creating
# another one.
cp item item-old
cp item-start item
