 	/// Increments to this component represent backwards-compatible bug fixes.
 	public let patch: Int
 
+	/// The raw version string specified in the cartfile.
+	///
+	/// eg. "v2.3.1".
+	public let raw: String
+
 	/// A list of the version components, in order from most significant to
 	/// least significant.
 	public var components: [Int] {
 		return [ major, minor, patch ]
 	}
 
-	public init(major: Int, minor: Int, patch: Int) {
+	public init(major: Int, minor: Int, patch: Int, raw: String) {
 		self.major = major
 		self.minor = minor
 		self.patch = patch
+		self.raw = raw
 	}
 
 	/// Attempts to parse a semantic version from a human-readable string of the
 	/// form "a.b.c".
 	static public func fromString(specifier: String) -> Result<Version> {
-		let components = split(specifier, { $0 == "." }, allowEmptySlices: false)
+		let validChars = NSCharacterSet(charactersInString: "0123456789.")
+		let scanner = NSScanner(string: specifier)
+		var sanitizedSpecifier : NSString? = nil
+
+		if !scanner.scanCharactersFromSet(validChars, intoString: &sanitizedSpecifier) {
+			return failure()
+		}
+
+		let components = split(sanitizedSpecifier! as String, { $0 == "." }, allowEmptySlices: false)
 		if components.count == 0 {
 			return failure()
 		}

		let minor = (components.count > 1 ? components[1].toInt() : 0)
		let patch = (components.count > 2 ? components[2].toInt() : 0)

		return success(self(major: major!, minor: minor ?? 0, patch: patch ?? 0))
	}
}


	public static func fromScanner(scanner: NSScanner) -> Result<VersionSpecifier> {
		func scanVersion() -> Result<Version> {
			var version: NSString? = nil

			if scanner.scanUpToString("\n", intoString: &version) {
				if let version = version {
					return Version.fromString(version)
				}
