summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-08-30 16:17:10 -0400
committerBen Morrison <ben@gbmor.dev>2019-08-30 16:17:17 -0400
commitebc4efa5d0cc8bf552d528baa5b4e68956aea764 (patch)
tree7dd1cb6e6a74e5241ca4d15020d82d81ebfb788f
parentf3c780970b05a1e78152920d4dfc5e154e82e212 (diff)
downloadclinte-ebc4efa5d0cc8bf552d528baa5b4e68956aea764.tar.gz
enabled deletion of posts v0.3.0
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs38
3 files changed, 38 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c613889..07b835b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -119,7 +119,7 @@ dependencies = [
 
 [[package]]
 name = "clinte"
-version = "0.2.0"
+version = "0.3.0"
 dependencies = [
  "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index 81b163b..0b9779f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clinte"
-version = "0.2.0"
+version = "0.3.0"
 authors = ["Ben Morrison <ben@gbmor.dev>"]
 edition = "2018"
 
diff --git a/src/main.rs b/src/main.rs
index ff6e8fd..ff1783a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -18,11 +18,11 @@ fn main() {
                 .about("Update a notice you've posted")
                 .arg(clap::Arg::with_name("id").help("Numeric ID of the post")),
         )
-        /*.subcommand(
+        .subcommand(
             clap::SubCommand::with_name("delete")
                 .about("Delete a notice you've posted")
                 .arg(clap::Arg::with_name("id").help("Numeric ID of the post")),
-        )*/
+        )
         .get_matches();
 
     let start = time::Instant::now();
@@ -42,6 +42,9 @@ fn main() {
     } else if arg_matches.subcommand_matches("update").is_some() {
         info!("Updating post ...");
         update(&db);
+    } else if arg_matches.subcommand_matches("delete").is_some() {
+        info!("Deleting post");
+        delete(&db);
     }
 
     list_matches(&db);
@@ -176,3 +179,34 @@ fn update(db: &db::Conn) {
     let mut stmt = db.conn.prepare(&body_stmt).unwrap();
     stmt.execute_named(&[(":body", &new_body)]).unwrap();
 }
+
+fn delete(db: &db::Conn) {
+    let cur_user = users::get_current_username()
+        .unwrap()
+        .into_string()
+        .unwrap();
+
+    println!();
+    println!("ID of the post to delete?");
+    let mut id_num_in = String::new();
+    io::stdin().read_line(&mut id_num_in).unwrap();
+    let id_num_in: u32 = id_num_in.trim().parse().unwrap();
+
+    let del_stmt = format!("DELETE FROM posts WHERE id = {}", id_num_in);
+    let get_stmt = format!("SELECT * FROM posts WHERE id = {}", id_num_in);
+
+    let mut get_stmt = db.conn.prepare(&get_stmt).unwrap();
+    let mut del_stmt = db.conn.prepare(&del_stmt).unwrap();
+
+    let user_in_post: String = get_stmt
+        .query_row(rusqlite::NO_PARAMS, |row| row.get(2))
+        .unwrap();
+
+    if cur_user != user_in_post {
+        println!("Users don't match. Can't delete!");
+        println!();
+        return;
+    }
+
+    del_stmt.execute(rusqlite::NO_PARAMS).unwrap();
+}
background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
import streams

when defined(posix):
  import posix

import buffer/buffer
import config/config
import io/loader
import io/request
import io/window
import ips/serialize
import ips/serversocket
import types/buffersource
import utils/twtstr

type
  ForkCommand* = enum
    FORK_BUFFER, FORK_LOADER, REMOVE_CHILD, LOAD_CONFIG

  ForkServer* = ref object
    process*: Pid
    istream*: Stream
    ostream*: Stream

  ForkServerContext = object
    istream: Stream
    ostream: Stream
    children: seq[(Pid, Pid)]

proc newFileLoader*(forkserver: ForkServer, defaultHeaders: HeaderList = DefaultHeaders): FileLoader =
  forkserver.ostream.swrite(FORK_LOADER)
  forkserver.ostream.swrite(defaultHeaders)
  forkserver.ostream.flush()
  forkserver.istream.sread(result)

proc loadForkServerConfig*(forkserver: ForkServer, config: Config) =
  forkserver.ostream.swrite(LOAD_CONFIG)
  forkserver.ostream.swrite(config.getForkServerConfig())
  forkserver.ostream.flush()

proc removeChild*(forkserver: Forkserver, pid: Pid) =
  forkserver.ostream.swrite(REMOVE_CHILD)
  forkserver.ostream.swrite(pid)
  forkserver.ostream.flush()

proc forkLoader(ctx: var ForkServerContext, defaultHeaders: HeaderList): FileLoader =
  var pipefd: array[2, cint]
  if pipe(pipefd) == -1:
    raise newException(Defect, "Failed to open pipe.")
  let pid = fork()
  if pid == 0:
    # child process
    for i in 0 ..< ctx.children.len: ctx.children[i] = (Pid(0), Pid(0))
    ctx.children.setLen(0)
    zeroMem(addr ctx, sizeof(ctx))
    discard close(pipefd[0]) # close read
    runFileLoader(pipefd[1], defaultHeaders)
    assert false
  let readfd = pipefd[0] # get read
  discard close(pipefd[1]) # close write
  var readf: File
  if not open(readf, FileHandle(readfd), fmRead):
    raise newException(Defect, "Failed to open output handle.")
  assert readf.readChar() == char(0u8)
  close(readf)
  discard close(pipefd[0])
  return FileLoader(process: pid)

proc forkBuffer(ctx: var ForkServerContext): Pid =
  var source: BufferSource
  var config: BufferConfig
  var attrs: WindowAttributes
  var mainproc: Pid
  ctx.istream.sread(source)
  ctx.istream.sread(config)
  ctx.istream.sread(attrs)
  ctx.istream.sread(mainproc)
  let loader = ctx.forkLoader(DefaultHeaders) #TODO make this configurable
  let pid = fork()
  if pid == 0:
    for i in 0 ..< ctx.children.len: ctx.children[i] = (Pid(0), Pid(0))
    ctx.children.setLen(0)
    zeroMem(addr ctx, sizeof(ctx))
    launchBuffer(config, source, attrs, loader, mainproc)
    assert false
  ctx.children.add((pid, loader.process))
  return pid

proc runForkServer() =
  var ctx: ForkServerContext
  ctx.istream = newFileStream(stdin)
  ctx.ostream = newFileStream(stdout)
  while true:
    try:
      var cmd: ForkCommand
      ctx.istream.sread(cmd)
      case cmd
      of REMOVE_CHILD:
        var pid: Pid
        ctx.istream.sread(pid)
        for i in 0 .. ctx.children.high:
          if ctx.children[i][0] == pid:
            ctx.children.del(i)
            break
      of FORK_BUFFER:
        ctx.ostream.swrite(ctx.forkBuffer())
      of FORK_LOADER:
        var defaultHeaders: HeaderList
        ctx.istream.sread(defaultHeaders)
        let loader = ctx.forkLoader(defaultHeaders)
        ctx.ostream.swrite(loader)
        ctx.children.add((loader.process, Pid(-1)))
      of LOAD_CONFIG:
        var config: ForkServerConfig
        ctx.istream.sread(config)
        width_table = makewidthtable(config.ambiguous_double)
        SocketDirectory = config.tmpdir
      ctx.ostream.flush()
    except IOError:
      # EOF
      break
  ctx.istream.close()
  ctx.ostream.close()
  # Clean up when the main process crashed.
  for childpair in ctx.children:
    let a = childpair[0]
    let b = childpair[1]
    discard kill(cint(a), cint(SIGTERM))
    if b != -1:
      discard kill(cint(b), cint(SIGTERM))
  quit(0)

proc newForkServer*(): ForkServer =
  new(result)
  var pipefd_in: array[2, cint]
  var pipefd_out: array[2, cint]
  if pipe(pipefd_in) == -1:
    raise newException(Defect, "Failed to open input pipe.")
  if pipe(pipefd_out) == -1:
    raise newException(Defect, "Failed to open output pipe.")
  let pid = fork()
  if pid == -1:
    raise newException(Defect, "Failed to fork the fork process.")
  elif pid == 0:
    # child process
    let readfd = pipefd_in[0]
    discard close(pipefd_in[1]) # close write
    let writefd = pipefd_out[1]
    discard close(pipefd_out[0]) # close read
    discard dup2(readfd, stdin.getFileHandle())
    discard dup2(writefd, stdout.getFileHandle())
    discard close(pipefd_in[0])
    discard close(pipefd_out[1])
    runForkServer()
    assert false
  else:
    discard close(pipefd_in[0]) # close read
    discard close(pipefd_out[1]) # close write
    var readf, writef: File
    if not open(writef, pipefd_in[1], fmWrite):
      raise newException(Defect, "Failed to open output handle")
    if not open(readf, pipefd_out[0], fmRead):
      raise newException(Defect, "Failed to open input handle")
    result.ostream = newFileStream(writef)
    result.istream = newFileStream(readf)