All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jsuereth.pgp.hkp.client.scala Maven / Gradle / Ivy

The newest version!
package com.jsuereth.pgp
package hkp

/** Represents a client connected to a PGP public key server. */
trait Client {
  /** Retreives a PGP Public Key from the server. */
  def getKey(id: Long): Option[PublicKeyRing]
  /** Pushes a public key to a key server. */
  def pushKey(key: PublicKey, logger: String => Unit): Unit
  /** Pushes a public key to a key server. */
  def pushKeyRing(key: PublicKeyRing, logger: String => Unit): Unit
  /** Searches for a term on the keyserver and returns all the results. */
  def search(term: String): Seq[LookupKeyResult]
}

// case class KeyIndexResult(id: String, identity: String, date: java.util.Date)

private[hkp] class DispatchClient(serverUrl: String) extends Client {
  
  import dispatch.classic._
  import Http._
  import util.control.Exception.catching
  
  /** Attempts to pull a public key from the HKP server.
   * @return Some(key) if successful, None otherwise.
   */
  def getKey(id: Long): Option[PublicKeyRing] =
    for {
      ring <- catching(classOf[Exception]) opt Http(
          initiateRequest(GetKey(id)) >> (PublicKeyRing.load _))
      // we have to look for ids matching the string, since IDs tend to be sent with lower 32 bits.
      key <- ring.publicKeys find { k => idToString(k.keyID) contains idToString(id) } 
    } yield ring
  
  /** Pushes a key to the given public key server. */
  def pushKey(key: PublicKey, logger: String => Unit): Unit =
    Http(initiateFormPost(AddKey(key)) >- { c => logger("received: " + c) })
  
  /** Pushes a key to the given public key server. */
  def pushKeyRing(key: PublicKeyRing, logger: String => Unit): Unit =
    Http(initiateFormPost(AddKey(key)) >- { c => logger("received: " + c) })
    
  /** Searches for a term on the keyserver and returns all the results. */
  def search(term: String): Seq[LookupKeyResult] = 
    (catching(classOf[Exception]) opt 
        Client.LookupParser.parseFile(Http(
            initiateRequest(Find(term)).as_str)) getOrElse Seq.empty)
  
  // TODO - Allow search and parse format: http://keyserver.ubuntu.com:11371/pks/lookup?op=index&search=suereth
  /*
info:1:2
pub:E29DF322:1:2048:1315150989::
uid:Josh Suereth :1315150989::
pub:EF5DDCCC:17:1024:1137516901::
uid:Terry Suereth (CE2008) :1137516901::

Note: Type bits/keyID    Date
   */
  private[this] def initiateRequest(cmd: HkpCommand): Request =
    url(serverUrl + cmd.url) < new DispatchClient("http://%s:11371" format (server))
    case HkpWithPort(server, port) => new DispatchClient("http://%s:%s" format (server,port))
    case _                         => new DispatchClient(url)
  }
  
  object LookupParser extends scala.util.parsing.combinator.RegexParsers {
    def s: Parser[String] = ":"
    def eol: Parser[String] = "[\r\n]+".r
    def pub: Parser[String] = "pub"
    def uid: Parser[String] = "uid"
    def info: Parser[String] = "info"
    def name: Parser[String] = guard(not(info | uid | pub)) ~> ("[^\\:\n\r]*".r)
    def line: Parser[Seq[String]] = (pub <~ s) ~ rep1sep(name, s) ^^ {
      case x ~ xs => x +: xs
    }
    def userId: Parser[String] = ("uid" ~ s) ~> rep1sep(name,s) ^^ {
      case Seq(name, date, _*) => name
    }
    def keyHeader: Parser[(String, java.util.Date)] = line ^? {
      case Seq("pub", name, _, _, date, _*) => (name, new java.util.Date(date.toLong * 1000L))
    }
    def key: Parser[LookupKeyResult] = keyHeader ~ rep1(userId) ^^ {
      case (id, ts) ~ users => LookupKeyResult(id, ts, users)
    }
    def infoheader = "info" ~ s ~ rep1sep(name,s)
    def queryresponse: Parser[Seq[LookupKeyResult]] = infoheader ~> rep(key)
    
    def parseFile(input: String): Seq[LookupKeyResult] = {
      println("Parsing lookup value: " + input)
      parseAll(queryresponse, input) match {
        case Success(data, _) => data
        case _                => error("Issues")
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy