text:
package utils

import java.util.UUID._

import models.yesNo.{YesNoWith2Text, YesNoWithAddress, YesNoMandWithAddress}
import org.specs2.mutable._
import models.{DayMonthYear, SortCode, MultiLineAddress, NationalInsuranceNumber}
import models.domain.BankBuildingSocietyDetails
import javax.xml.bind.DatatypeConverter
import gov.dwp.carers.security.encryption.EncryptorAES
import app.ConfigProperties._

class C3EncryptionSpec extends Specification {
  def saveForLaterKey = getStringProperty("saveForLater.uuid.secret.key")
  object ValuesToBeUsed {
    val string = "Barney"
    val optionalString = Some("Barney")
    val multiLineAddress = MultiLineAddress(Some("123"), Some("Fake Street"), None)
    val nationalInsuranceNumber = NationalInsuranceNumber(Some("AA123456A"))
    val optionalNationalInsuranceNumber = Some(NationalInsuranceNumber(Some("AA123456A")))
    val optionalMultiLineAddress = Some(MultiLineAddress(Some("123"), Some("Fake Street"), None))
    val yesNoMandWithAddress = YesNoMandWithAddress("No",
      Some(MultiLineAddress(Some("123"), Some("Fake street"), None)), Some("PL18 1AA"))
    val yesNoWithAddress = YesNoWithAddress(Some("No"),
      Some(MultiLineAddress(Some("123"), Some("Fake street"), None)), Some("PL18 1AA"))
    val sortCode = SortCode("00", "00", "00")
    val optionalBankBuildingSoceityDetails = Some(BankBuildingSocietyDetails("blah", "blah", SortCode("00", "00", "00"),
      "blah", "blah"))
    val yesNoWith2Text = YesNoWith2Text("blah", Some("blah"), Some("blah"))
    val optionalDayMonthYear = Some(DayMonthYear(1, 2, 2000))
  }

  section("unit")
  "C3Encryption" should {
    "Not decrypt an already decrypted string" in new WithApplication {
      val encryptedString = C3Encryption.encryptString(ValuesToBeUsed.string)
      val decryptedString = C3Encryption.decryptString(encryptedString)
      val reDecryptedString = C3Encryption.decryptString(decryptedString)
      decryptedString mustEqual reDecryptedString
    }

    "Encrypt Option[String] values" in new WithApplication {
      val encryptedOptionalString = C3Encryption.encryptOptionalString(ValuesToBeUsed.optionalString)
      val decryptedOptionalString = Some((new EncryptorAES).decrypt(DatatypeConverter.parseBase64Binary(encryptedOptionalString.get)))
      ValuesToBeUsed.optionalString mustNotEqual encryptedOptionalString
      ValuesToBeUsed.optionalString mustEqual decryptedOptionalString
      C3Encryption.encryptOptionalString(None) mustEqual None
    }

    "Decrypt Option[String] values" in new WithApplication {
      val encryptedOptionalString = C3Encryption.encryptOptionalString(ValuesToBeUsed.optionalString)
      val decryptedOptionalString = C3Encryption.decryptOptionalString(encryptedOptionalString)
      ValuesToBeUsed.optionalString mustNotEqual encryptedOptionalString
      ValuesToBeUsed.optionalString mustEqual decryptedOptionalString
      C3Encryption.decryptOptionalString(None) mustEqual None
    }

    "Encrypt MultiLineAddress values" in new WithApplication {
      val encryptedMultiLineAddress = C3Encryption.encryptMultiLineAddress(ValuesToBeUsed.multiLineAddress)
      val decryptedLineOne = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.lineOne)
      val decryptedLineTwo = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.lineTwo)
      val decryptedLineThree = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.lineThree)
      ValuesToBeUsed.multiLineAddress mustNotEqual encryptedMultiLineAddress
      ValuesToBeUsed.multiLineAddress.lineOne mustEqual decryptedLineOne
      ValuesToBeUsed.multiLineAddress.lineTwo mustEqual decryptedLineTwo
      ValuesToBeUsed.multiLineAddress.lineThree mustEqual decryptedLineThree
    }

    "Decrypt MultiLineAddress values" in new WithApplication {
      val encryptedMultiLineAddress = C3Encryption.encryptMultiLineAddress(ValuesToBeUsed.multiLineAddress)
      val decryptedMultiLineAddress = C3Encryption.decryptMultiLineAddress(encryptedMultiLineAddress)
      ValuesToBeUsed.multiLineAddress mustNotEqual encryptedMultiLineAddress
      ValuesToBeUsed.multiLineAddress mustEqual decryptedMultiLineAddress
    }

    "Encrypt NationalInsuranceNumber values" in new WithApplication {
      val encryptedNationalInsuranceNumber = C3Encryption.encryptNationalInsuranceNumber(ValuesToBeUsed.nationalInsuranceNumber)
      val decryptedNationalInsuranceNumber = NationalInsuranceNumber(Some((new EncryptorAES).decrypt(DatatypeConverter.parseBase64Binary(encryptedNationalInsuranceNumber.nino.get))))
      ValuesToBeUsed.nationalInsuranceNumber mustNotEqual encryptedNationalInsuranceNumber
      ValuesToBeUsed.nationalInsuranceNumber mustEqual decryptedNationalInsuranceNumber
    }

    "Decrypt NationalInsuranceNumber values" in new WithApplication {
      val encryptedNationalInsuranceNumber = C3Encryption.encryptNationalInsuranceNumber(ValuesToBeUsed.nationalInsuranceNumber)
      val decryptedNationalInsuranceNumber = C3Encryption.decryptNationalInsuranceNumber(encryptedNationalInsuranceNumber)
      ValuesToBeUsed.nationalInsuranceNumber mustNotEqual encryptedNationalInsuranceNumber
      ValuesToBeUsed.nationalInsuranceNumber mustEqual decryptedNationalInsuranceNumber
    }

    "Encrypt Option[NationalInsuranceNumber] values" in new WithApplication {
      val encryptedNationalInsuranceNumber = C3Encryption.encryptOptionalNationalInsuranceNumber(ValuesToBeUsed.optionalNationalInsuranceNumber)
      val decryptedNationalInsuranceNumber = Some(NationalInsuranceNumber(Some((new EncryptorAES).decrypt(DatatypeConverter.parseBase64Binary(encryptedNationalInsuranceNumber.get.nino.get)))))
      ValuesToBeUsed.optionalNationalInsuranceNumber mustNotEqual encryptedNationalInsuranceNumber
      ValuesToBeUsed.optionalNationalInsuranceNumber mustEqual decryptedNationalInsuranceNumber
      C3Encryption.encryptOptionalNationalInsuranceNumber(None) mustEqual None
    }

    "Decrypt Option[NationalInsuranceNumber] values" in new WithApplication {
      val encryptedNationalInsuranceNumber = C3Encryption.encryptOptionalNationalInsuranceNumber(ValuesToBeUsed.optionalNationalInsuranceNumber)
      val decryptedNationalInsuranceNumber = C3Encryption.decryptOptionalNationalInsuranceNumber(encryptedNationalInsuranceNumber)
      ValuesToBeUsed.optionalNationalInsuranceNumber mustNotEqual encryptedNationalInsuranceNumber
      ValuesToBeUsed.optionalNationalInsuranceNumber mustEqual decryptedNationalInsuranceNumber
      C3Encryption.decryptOptionalNationalInsuranceNumber(None) mustEqual None
    }

    "Encrypt Option[MultiLineAddress] values" in new WithApplication {
      val encryptedMultiLineAddress = C3Encryption.encryptOptionalMultiLineAddress(ValuesToBeUsed.optionalMultiLineAddress)
      val decryptedLineOne = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.get.lineOne)
      val decryptedLineTwo = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.get.lineTwo)
      val decryptedLineThree = C3Encryption.decryptOptionalString(encryptedMultiLineAddress.get.lineThree)
      ValuesToBeUsed.optionalMultiLineAddress mustNotEqual encryptedMultiLineAddress
      ValuesToBeUsed.optionalMultiLineAddress.get.lineOne mustEqual decryptedLineOne
      ValuesToBeUsed.optionalMultiLineAddress.get.lineTwo mustEqual decryptedLineTwo
      ValuesToBeUsed.optionalMultiLineAddress.get.lineThree mustEqual decryptedLineThree
      C3Encryption.encryptOptionalMultiLineAddress(None) mustEqual None
    }

    "Decrypt Option[MultiLineAddress] values" in new WithApplication {
      val encryptedMultiLineAddress = C3Encryption.encryptOptionalMultiLineAddress(ValuesToBeUsed.optionalMultiLineAddress)
      val decryptedMultiLineAddress = C3Encryption.decryptOptionalMultiLineAddress(encryptedMultiLineAddress)
      ValuesToBeUsed.optionalMultiLineAddress mustNotEqual encryptedMultiLineAddress
      ValuesToBeUsed.optionalMultiLineAddress mustEqual decryptedMultiLineAddress
      C3Encryption.decryptOptionalMultiLineAddress(None) mustEqual None
    }

    "Encrypt YesNoMandWithAddress values" in new WithApplication {
      val encryptedAddress = C3Encryption.encryptYesNoMandWithAddress(ValuesToBeUsed.yesNoMandWithAddress)
      val decryptedAnswer = (new EncryptorAES).decrypt(DatatypeConverter.parseBase64Binary(encryptedAddress.answer))
      val decryptedLineOne = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoMandWithAddress.address).get.lineOne
      val decryptedLineTwo = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoMandWithAddress.address).get.lineTwo
      val decryptedLineThree = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoMandWithAddress.address).get.lineThree
      val decryptedPostCode = C3Encryption.decryptOptionalString(ValuesToBeUsed.yesNoMandWithAddress.postCode)
      ValuesToBeUsed.yesNoMandWithAddress mustNotEqual encryptedAddress
      ValuesToBeUsed.yesNoMandWithAddress.answer mustEqual decryptedAnswer
      ValuesToBeUsed.yesNoMandWithAddress.address.get.lineOne mustEqual decryptedLineOne
      ValuesToBeUsed.yesNoMandWithAddress.address.get.lineTwo mustEqual decryptedLineTwo
      ValuesToBeUsed.yesNoMandWithAddress.address.get.lineThree mustEqual decryptedLineThree
      ValuesToBeUsed.yesNoMandWithAddress.postCode mustEqual decryptedPostCode
    }

    "Decrypt YesNoMandWithAddress values" in new WithApplication {
      val encryptedAddress = C3Encryption.encryptYesNoMandWithAddress(ValuesToBeUsed.yesNoMandWithAddress)
      val decryptedAddress = C3Encryption.decryptYesNoMandWithAddress(encryptedAddress)
      ValuesToBeUsed.yesNoMandWithAddress mustNotEqual encryptedAddress
      ValuesToBeUsed.yesNoMandWithAddress mustEqual decryptedAddress
    }

    "Encrypt YesNoWithAddress values" in new WithApplication {
      val encryptedAddress = C3Encryption.encryptYesNoWithAddress(ValuesToBeUsed.yesNoWithAddress)
      val decryptedAnswer = C3Encryption.decryptOptionalString(encryptedAddress.answer)
      val decryptedLineOne = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoWithAddress.address).get.lineOne
      val decryptedLineTwo = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoWithAddress.address).get.lineTwo
      val decryptedLineThree = C3Encryption.decryptOptionalMultiLineAddress(ValuesToBeUsed.yesNoWithAddress.address).get.lineThree
      val decryptedPostCode = C3Encryption.decryptOptionalString(ValuesToBeUsed.yesNoWithAddress.postCode)
      ValuesToBeUsed.yesNoWithAddress mustNotEqual encryptedAddress
      ValuesToBeUsed.yesNoWithAddress.answer mustEqual decryptedAnswer
      ValuesToBeUsed.yesNoWithAddress.address.get.lineOne mustEqual decryptedLineOne
      ValuesToBeUsed.yesNoWithAddress.address.get.lineThree mustEqual decryptedLineThree
      ValuesToBeUsed.yesNoWithAddress.postCode mustEqual decryptedPostCode
    }

    "Encrypt Option[DayMonthYear] values" in new WithApplication {
      // Tests for DayMonthYear are in models.DayMonthYearSpec
      val encryptedOptionalDayMonthYear = C3Encryption.encryptOptionalDayMonthYear(ValuesToBeUsed.optionalDayMonthYear)
      val decryptedOptionalDayMonthYear = Some(encryptedOptionalDayMonthYear.get.decrypt)
      ValuesToBeUsed.optionalDayMonthYear mustNotEqual encryptedOptionalDayMonthYear
      ValuesToBeUsed.optionalDayMonthYear mustEqual decryptedOptionalDayMonthYear
    }

    "Decrypt Option[DayMonthYear] values" in new WithApplication {
      // Tests for DayMonthYear are in models.DayMonthYearSpec
      val encryptedOptionalDayMonthYear = C3Encryption.encryptOptionalDayMonthYear(ValuesToBeUsed.optionalDayMonthYear)
      val decryptedOptionalDayMonthYear = C3Encryption.decryptOptionalDayMonthYear(encryptedOptionalDayMonthYear)
      ValuesToBeUsed.optionalDayMonthYear mustEqual decryptedOptionalDayMonthYear
    }

    "Decrypt YesNoWithAddress values" in new WithApplication {
      val encryptedAddress = C3Encryption.encryptYesNoWithAddress(ValuesToBeUsed.yesNoWithAddress)
      val decryptedAddress = C3Encryption.decryptYesNoWithAddress(encryptedAddress)
      ValuesToBeUsed.yesNoWithAddress mustNotEqual encryptedAddress
      ValuesToBeUsed.yesNoWithAddress mustEqual decryptedAddress
    }

    "Encrypt SortCode values" in new WithApplication {
      val encryptedSortCode = C3Encryption.encryptSortCode(ValuesToBeUsed.sortCode)
      val decryptedSort1 = C3Encryption.decryptString(encryptedSortCode.sort1)
      val decryptedSort2 = C3Encryption.decryptString(encryptedSortCode.sort2)
      val decryptedSort3 = C3Encryption.decryptString(encryptedSortCode.sort3)
      ValuesToBeUsed.sortCode mustNotEqual encryptedSortCode
      ValuesToBeUsed.sortCode.sort1 mustEqual decryptedSort1
      ValuesToBeUsed.sortCode.sort2 mustEqual decryptedSort2
      ValuesToBeUsed.sortCode.sort3 mustEqual decryptedSort3
    }

    "Decrypt SortCode values" in new WithApplication {
      val encryptedSortCode = C3Encryption.encryptSortCode(ValuesToBeUsed.sortCode)
      val decryptedSortCode = C3Encryption.decryptSortCode(encryptedSortCode)
      ValuesToBeUsed.sortCode mustNotEqual encryptedSortCode
      ValuesToBeUsed.sortCode mustEqual decryptedSortCode
    }

    "Encrypt Option[BankBuildingSoceityDetails]" in new WithApplication {
      val encryptedBankBuildingSoceityDetails = C3Encryption.encryptOptionalBankBuildingSoceityDetails(ValuesToBeUsed.optionalBankBuildingSoceityDetails)
      val decryptedAccountHolderName = C3Encryption.decryptString(encryptedBankBuildingSoceityDetails.get.accountHolderName)
      val decryptedBankFullName = C3Encryption.decryptString(encryptedBankBuildingSoceityDetails.get.bankFullName)
      val decryptedSortCode = C3Encryption.decryptSortCode(encryptedBankBuildingSoceityDetails.get.sortCode)
      val decryptedAccountNumber = C3Encryption.decryptString(encryptedBankBuildingSoceityDetails.get.accountNumber)
      val decryptedRollOrReference = C3Encryption.decryptString(encryptedBankBuildingSoceityDetails.get.rollOrReferenceNumber)
      ValuesToBeUsed.optionalBankBuildingSoceityDetails mustNotEqual encryptedBankBuildingSoceityDetails
      ValuesToBeUsed.optionalBankBuildingSoceityDetails.get.accountHolderName mustEqual decryptedAccountHolderName
      ValuesToBeUsed.optionalBankBuildingSoceityDetails.get.bankFullName mustEqual decryptedBankFullName
      ValuesToBeUsed.optionalBankBuildingSoceityDetails.get.sortCode mustEqual decryptedSortCode
      ValuesToBeUsed.optionalBankBuildingSoceityDetails.get.accountNumber mustEqual decryptedAccountNumber
      ValuesToBeUsed.optionalBankBuildingSoceityDetails.get.rollOrReferenceNumber mustEqual decryptedRollOrReference
      C3Encryption.encryptOptionalBankBuildingSoceityDetails(None) mustEqual None
    }

    "Decrypt Option[BankBuildingSoceityDetails] values" in new WithApplication {
      val encryptedBankBuildingSoceityDetails = C3Encryption.encryptOptionalBankBuildingSoceityDetails(ValuesToBeUsed.optionalBankBuildingSoceityDetails)
      val decryptedBankBuildingSoceityDetails = C3Encryption.decryptOptionalBankBuildingSoceityDetails(encryptedBankBuildingSoceityDetails)
      ValuesToBeUsed.optionalBankBuildingSoceityDetails mustNotEqual encryptedBankBuildingSoceityDetails
      ValuesToBeUsed.optionalBankBuildingSoceityDetails mustEqual decryptedBankBuildingSoceityDetails
      C3Encryption.decryptOptionalBankBuildingSoceityDetails(None) mustEqual None
    }

    "Encrypt YesNoWith2Text values" in new WithApplication {
      val encryptedYesNoWith2Text = C3Encryption.encryptYesNoWith2Text(ValuesToBeUsed.yesNoWith2Text)
      val decryptedYesNo = C3Encryption.decryptString(encryptedYesNoWith2Text.answer)
      val decryptedText1 = C3Encryption.decryptOptionalString(encryptedYesNoWith2Text.text1)
      val decryptedText2 = C3Encryption.decryptOptionalString(encryptedYesNoWith2Text.text2)
      ValuesToBeUsed.yesNoWith2Text mustNotEqual encryptedYesNoWith2Text
      ValuesToBeUsed.yesNoWith2Text.answer mustEqual decryptedYesNo
      ValuesToBeUsed.yesNoWith2Text.text1 mustEqual decryptedText1
      ValuesToBeUsed.yesNoWith2Text.text2 mustEqual decryptedText2
    }

    "Decrypt YesNoWith2Text values" in new WithApplication {
      val encryptedYesNoWith2Text = C3Encryption.encryptYesNoWith2Text(ValuesToBeUsed.yesNoWith2Text)
      val decryptedYesNoWith2Text = C3Encryption.decryptYesNoWith2Text(encryptedYesNoWith2Text)
      ValuesToBeUsed.yesNoWith2Text mustNotEqual encryptedYesNoWith2Text
      ValuesToBeUsed.yesNoWith2Text mustEqual decryptedYesNoWith2Text
    }

    "Encrypt uppercase uuid returns empty string" in new WithApplication {
      val uuid = "ABCD1234-0000-0000-0000-ABCD1234CDEF"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      encrypted mustEqual ""
    }

    "Encrypt short uuid returns empty string" in new WithApplication {
      val uuid = "ABCD1234-0000-0000-0000-ABCD1234CDE"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      encrypted mustEqual ""
    }

    "Encrypt and decrypt a typical lowercase uuid back to original" in new WithApplication {
      val uuid = "abcd1234-0000-0000-0000-abcd1234cdef"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      val decrypted = XorEncryption.decryptUuid(encrypted, saveForLaterKey)
      encrypted mustNotEqual uuid
      decrypted mustEqual uuid
    }

    "Encrypt and decrypt a typical 0 leading uuid back to original" in new WithApplication {
      val uuid = "0bcd1234-0000-0000-0000-abcd1234cdef"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      val decrypted = XorEncryption.decryptUuid(encrypted, saveForLaterKey)
      encrypted mustNotEqual uuid
      decrypted mustEqual uuid
    }

    "Encrypt and decrypt a random claim uuid back to original" in new WithApplication {
      val uuid = randomUUID.toString
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      println( "encrypted uuid:"+uuid+" to "+encrypted)
      val decrypted = XorEncryption.decryptUuid(encrypted, saveForLaterKey)
      encrypted mustNotEqual uuid
      decrypted mustEqual uuid
    }

    "Encrypt and decrypt a zero uuid back to original" in new WithApplication {
      val uuid = "00000000-0000-0000-0000-000000000000"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      val decrypted = XorEncryption.decryptUuid(encrypted, saveForLaterKey)
      encrypted mustNotEqual uuid
      decrypted mustEqual uuid
    }

    "Encrypt when no key in properties should return empty string" in new WithApplication(app = LightFakeApplication(additionalConfiguration = Map("saveForLater.uuid.secret.key" -> ""))) {
      val uuid = randomUUID.toString
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      encrypted mustEqual ""
    }

    "Encrypt when uppercase key in properties should return empty string" in new WithApplication(app = LightFakeApplication(additionalConfiguration = Map("saveForLater.uuid.secret.key" -> "8F7A0412-DF0E-485E-92C6-5B0F17E339C8"))) {
      val uuid = randomUUID.toString
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      encrypted mustEqual ""
    }

    "Generate a decryption pair-value for use in other tests" in new WithApplication {
      val uuid = "0bcd1234-0000-0000-0000-abcd1234cdef"
      val encrypted = XorEncryption.encryptUuid(uuid, saveForLaterKey)
      encrypted mustNotEqual uuid
      println("With secretkey of:"+getStringProperty("saveForLater.uuid.secret.key")+" created xor pair of:"+uuid+" and:"+encrypted)
    }
  }

  section("unit")
}


text:
Nikon confirms the D850 DSLR is in development, but details are scarce
By Hillary K. Grigonis	 July 25, 2017
Nikon is updating the D810 (above) with the D850, but images, full specs and a release date are not yet available.
Nikon will soon be adding another high-end, full-frame camera to its ranks. Today, July 25, on the company's 100th anniversary, Nikon announced the development of the successor to the D810, the Nikon D850. While few details on the upcoming camera were released, Nikon says the camera is a high-resolution, high-speed DSLR.
Nikon is incorporating feedback from users of the D810, originally launched in 2014, into the camera. Nikon calls the D850 a "formidable tool" for landscapes, weddings, sports, fashion, commercial work, and multi-media, as well as serving as another option for hobbyists.
Nikon hasn't released any specific details about the camera — just the camera's name and that it will be able to shoot 8K time-lapses. Assuming the camera improves on the D810 is, of course, a pretty safe bet, but improvements may not be across the board — Nikon's update to the D7200, the D7500, for example, steps down in megapixels to step up in low-light performance.
The launch of the D750 made the choice between Nikon full-frame bodies a tougher one — naming the camera the D850 instead of the D820 suggests the camera could have some similarities with the D750. While the D750 doesn't have the resolution of the D810, it added more speed as well as being Nikon's first full-frame to include a tilting LCD screen.
Enhancing speed has been a common thread among Nikon's latest and pricier DSLRs, with the D7500, released earlier this year, adding a faster burst speed, and the D500, launched last year, hitting 10 frames per second. Both cameras use Nikon's Expeed 5 processor, while the D810 uses the older Expeed 4.
Nikon also has been adding more video capabilities to its high-end DSLRs, equipping the D7500, D500 and D5 with 4K resolution. With the D850 capable of capturing 8K time-lapses, 4K wouldn't be surprising. If Nikon jumps to 4K, the move would make 4K available in a full-frame DSLR camera at a lower cost. Compared to Canon, whose flagship also has 4K, its more affordable DSLRs haven't yet adopted the features, with Canon saying it is approaching 4K with caution.
Wi-Fi and Bluetooth are also becoming standard options for Nikon, now even included in the budget D3400. Adding connectivity to the Nikon D850 wouldn't be surprising, considering how common the feature is now compared to when the D810 first launched in 2014.
For now, Nikon has only confirmed that the D850 is under development, leaving the specifications and launch date up to speculation until the company releases more official information. Stay tuned.
Update: Added sample time-lapse footage and confirmed 8K time-lapse feature.
Samsung Galaxy Tab S8 series' Amazon listing reveals it all
Cricket is making mobile data more affordable with FCC help

redpajama_set_name: RedPajamaCommonCrawl


text:
Amazon's Fire TV Stick is here, but the Indian Apps Just Don't Seem Ready
Amazon has finally launched the Fire TV Stick in India
The launch was accompanied by a large number of Indian apps
Most of these offer a poor experience on the television screen
On Wednesday, Amazon launched its Fire TV Stick in India, priced at Rs. 3,999 (there's a Rs. 499 cashback for Prime members), which means that for the first time since the launch of Amazon Prime Video in India four months ago in December, there's an easy way to get your content on to the television screen. Of course, that's not all the Fire TV Stick does – you can install apps for Netflix, Hotstar, Gaana, Eros Now, DittoTV, and others, though, at 8GB, storage space is a little limited on the Fire TV Stick.
Although you could import a Fire TV or Fire TV Stick to India before this, there were limitations. For one, there were almost no Indian apps available, so if you wanted to watch the IPL on Hotstar, for example, then you were out of luck.
And of course, Amazon's own Prime Video wasn't supported. What's more, the service wasn't available on other devices that support it internationally, such as game consoles. Yes, you could AirPlay it onto an Apple TV if you have an iOS device, but not many people in India live wholly inside Apple's ecosystem. With the official launch of the Fire TV Stick in India, that's changed, and you can now queue up an episode of The Man in the High Castle without having to use your phone to force it to launch, but most of the new Indian apps leave a lot to be desired.
Poor design not optimised for televisions
The Fire TV stick is great if you're a Prime Video subscriber who also uses Netflix and YouTube. These are easily our favourite services on the platform, because of how aesthetically pleasing and simple to use they are.
On the other hand, out of the various Indian applications that we tried after the announcement on Wednesday, only Gaana's music stream app seems like one that doesn't need a complete overhaul. The app's fairly basic, but the search works fine, the different UI elements are at least clearly readable, and the UI is easy to navigate with the Fire TV remote. Meanwhile one of the worst experiences was while using Hotstar.
On one hand, given Hotstar's catalogue and relatively reasonable pricing, we're happy to see it as a Fire TV app. On the other hand, the UI is practically an incitement to violence. Scrolling through is not smooth, the focus seems to get 'stuck' at times when you're nearing the edges of the screen, requiring one or sometimes even two extra keypresses to continue to scroll, and there are times when it's is even more inconsistent.
Sometimes, for example, you're trying to scroll down the list of categories on the home screen, and the focus will jump up to the categories bar on the top of the screen, so you're now on the Sports tab. Tapping the left or right keys at this point is fine, but tap down again, and you're back to scrolling through the list you were on.
Sometimes, pressing the back button will take you to the categories bar. At other times, it will ask you if you want to exit Hotstar. Accurately scrubbing is next to impossible, and there are no subtitles available.
A clear lack of testing
We tried out a number of other apps – having used an imported Fire TV for a couple of years we've got a fair amount of exposure to how apps can and should look on the device.
What we found was that just about every other app had some issues. For example, although Hotstar was definitely the worst experience, DittoTV also suffered from poor navigation, and felt more like something that was designed for mobile displays – and touchscreens.
Eros Now was the best looking app, but there were a couple of major shortcomings that keep us from wholeheartedly praising it. For one, there's no search function in the application, which is pretty much unforgivable. Secondly, the content is a little too small to read easily on the screen. It looks like you should either be watching it on a big, 70-inch display, or you should be sitting just two feet away from the television.
This led to – for example – looking at the Rangeela poster thinking, "this doesn't look like I remember", and on loading you realise it's actually the poster for Rangeeley. In that case, it wasn't just the title text under the poster that was too small to be seen – that's the case with every entry on Eros Now – but also the text on the poster itself. Finally, a minor quibble – in the settings the first option is select languages. The only choice in there is 'All languages', which makes us wonder why the option was added at all.
Things will get better
The good thing about all of this is that apps can and likely will be updated, and get better. And unlike the Apple TV, which is expensive and – according to completely unofficial estimates – doesn't have a wide install base in India, Amazon's offering is relatively cheap. Add in the fact that it's the 'official' – and for many, the only – way to watch Amazon Prime Video on your TV, and Prime Video itself is a service that's pretty reasonably priced, you can see a number of people being interested in the Fire TV Stick.
And if there are users, then the developers will also be motivated to improve their offerings and provide better solutions. What's surprising though is why Amazon, which has been in this business for some time now, didn't work more closely with the developers to ensure that the first experience people have with its hardware doesn't have these kinds of issues.
Amazon's Apps but don't fire Here Indian is just Ready Seem Stick The TV 2017-06-30


Small Wars Council > Conflicts -- Current & Future > Operation Iraqi Freedom > Who is Fighting Whom? How and Why? > Al Qaeda's Outrages Swing Sunnis to U.S.
View Full Version : Al Qaeda's Outrages Swing Sunnis to U.S.
17 February UPI via Washington Times - Al Qaeda's Outrages Swing Sunnis to U.S. (http://www.washtimes.com/world/20070217-123319-5645r.htm) by Pamela Hess.
Sunni tribes in troubled Anbar province have begun working closely with U.S. and government forces, contributing nearly 2,400 men to the police department and 1,600 to a newly organized tribal security force, authorities say.
U.S. troops are training and equipping the new tribal forces, which are called Emergency Response Units (ERUs), and are charged with defending the areas where they live, according to the local U.S. commander.
By a U.S. count, 12 of the Ramadi area's 21 tribes are cooperating in the security effort, six are considered neutral, and three are actively hostile. That is almost the reverse of the tribal posture last June, when three were cooperative and 12 were hostile.
For nearly four years, the tribes around Ramadi survived by playing both sides, working with U.S. forces when it suited them, while at the same time helping or tolerating Sunni insurgent groups and al Qaeda in Iraq -- the terrorist organization once led by Jordanian Abu Musab Zarqawi.
This is a good answer to all those who I have heard calling for us to "take the gloves off" in al-Anbar. I have seen a number of people who seem to think that the key to victory in al-Anbar is to essentially be more brutal than the terrorists. The idea being that we could intimidate them into submission. AQ thought the same thing and it apparently isn't working out for them as well as they had hoped. I have read in other places that some of the insurgent groups a learning that being indiscriminate in their targeting is counterproductive. I hope it is a lesson they learn slowly.
His most recent post talks about this.
In the blog "Healing Iraq" the author makes the suggestion that the US quit fighting the "bad guys" and cut a deal that they will live with, instead. It seems that he has decided that the fighting is worse than political oppression in Iraq.
So, what "deal" can we make that will prop up the most "bad guys" that we can live with?
Tribal security force? Sounds like another militia.
I know I kind of sound like a broken record, here, but in nearly every successful COIN effort that I'm aware of, sooner or later the "good guys" break down and make use of "militias" as part of the solution.
I think "peace" in Iraq will be relative; and we will have to incorporate some former "bad guys" in the political solution. Including their "militias".
19 February AP - Anger at Foreign Arabs Builds in Iraq (http://www.washingtonpost.com/wp-dyn/content/article/2007/02/19/AR2007021900112.html) by Bassem Mroue.
... Suspicion toward foreign Arabs stems, in part, from the fact that the Sunni-led insurgency has included many foreign fighters, most of them Arabs, who are blamed for deadly attacks that have claimed thousands of Iraqi lives.
Foreign Arabs who live in Iraq often try to hide their identities by faking an Iraqi accent or staying silent. Iraqis are usually suspicious when they hear a person speaking Arabic with a non-Iraqi accent.
An Associated Press reporter riding a public bus last month heard one of the passengers telling the driver in conversational Egyptian Arabic to drop him at a stop. After the man, carrying a bag, left the bus, Iraqis began arguing with the driver about why he had let the man on. Several passengers searched the seat where the man had been sitting to make sure he had not left a bomb.
19 February LA Times - U.S. Forces Try to Win the Trust of Iraqis (http://www.latimes.com/news/nationworld/world/la-fg-embed19feb19,0,4653346.story?coll=la-home-headlines) by Tina Susman.
The chunky man in the beige velour tracksuit emphasized that he wanted to help the U.S. troops, who politely sipped the Pepsis he had produced after they arrived unannounced Saturday night at his modest home in the northeast neighborhood of Shaab.
Without the Americans, the man said, kidnappers and killers who have terrorized Sunni Muslims in the Shiite-dominated area would resurface. Drawing his index finger across his neck in a slicing motion, he indicated what happened to Sunnis when U.S. forces were not around.
18 February The Belmont Club - Degrees of Freedom (http://fallbackbelmont.blogspot.com/2007/02/degrees-of-freedom.html) by Wretchard.
nearly every successful COIN effort that I'm aware of, sooner or later the "good guys" break down and make use of "militias" as part of the solution.
I agree completely. Ive been an equally broken record on this forum in support of a CAP-like program, which should include some kind of arming-of-the-people, militia style defense. Im a huge supporter of the 2nd Amendment here in the US and a person who LOATHES gun control. I know that people must be able to protect themselves since the authorities cant be everywhere at once. Im just very skeptical of militias in Iraq. They dont have a very good track record.
I also agree on the relativity of peace and the incorporation of militias, but the real question is how relative are we willing to get? Most militias in Iraq are as bad as the old regime, they just havent had enough time to rack up an equivalent body count. I would view acceptance of some of these groups as outright failure of the mission.
I'm just as skeptical, especially as far as a long-run solution. Relying on and building up the Ramadi tribes into the security forces is, IMO, a long-run nightmare in waiting if the Shia-dominated government ever tries to extend its power over Anbar.
Anyway, AQI appears to be hitting back (http://news.yahoo.com/s/nm/20070219/wl_nm/iraq_bombs_dc;_ylt=Akir_iXfW3qkiAPbRB9jpYPMWM0F).
In Monday's deadliest attack, suspected al Qaeda militants pulled the family of mourners from a minibus in daylight and gunned them down, including two young boys, after finding out they were from a Sunni tribe opposed to al Qaeda, police said.
The western city of Falluja is in the Sunni Arab insurgent bastion of Anbar province.
In Ramadi, capital of Anbar, two suicide bombers killed 11 people when they targeted the house of Sattar al-Buzayi, a tribal leader who has led a government-backed effort to fight al Qaeda.
One suicide car bomb hit the blast walls outside his house, then a bomber blew up his truck near the house, witnesses said.
GuardianFilms penetrates Iraq's most dangerous province to report on how the Iraqis themselves have turned on al-Qaida.
This film first appeared on Channel 4 News on Tuesday March 13.
The fighting also comes as the Iraqi government has said it believes it is close to capturing the organisation's new leader in Iraq, Abu Ayoub al-Masri. Although the power struggle has not reduced the number of attacks against the US-led coalition in Anbar province, it points to a complex reordering of the lines of conflict in the so-called "Sunni Triangle".
The conflict's underlying causes were highlighted by the leaking of a letter from al-Qaida's leadership to Abu Musab al-Zarqawi, the organisation's former leader in Iraq, who was killed earlier this year.
In the letter, written in December and found at the house where he died, Zarqawi is rebuked by Atiyah Abd al-Rahman, who is allegedly close to senior al-Qaida figures. He is warned "against attempting to kill any religious scholar or tribal leader who is obeyed, and of good repute in Iraq from among the Sunnis, no matter what." Zarqawi is told to improve relationships with other Sunni groups, use the al-Qaida name more judiciously and told ominously that he might be replaced.
It is these issues that have been at the heart of the rift between al-Qaida and the tribes, many of whose members support the nationalist resistance.
Part of the sheik's mission is rooted in the tribal law of revenge. His father was killed by Al Qaeda in 2004 for opposing its kind of fundamentalism. Two brothers were abducted and never heard from again, and a third brother was shot dead, he said. He has survived three car bombs outside the home he shares with his wife and five children.
Residents in parts of Anbar say the split in the Sunni insurgency is widening, with moderate tribal leaders and nationalist guerrillas pitted against fundamentalist warriors and rival tribes. That has led to a sharp increase in Sunni-on-Sunni violence across Anbar, especially in the past week, deepening the chaos of Iraq's civil war.
Al Qaeda remains a major force, and the relentless violence from all sides has turned the province into a failed region, according to a classified Marine intelligence assessment that was leaked to reporters last year.
As part of a broad review of options in Iraq, President Bush is looking at whether to give greater support to Sunni Arab tribal leaders who have grown disillusioned with the radical arm of the insurgency. It is a strategy long urged by officials in Sunni-dominated Saudi Arabia and now vigorously backed by Secretary of State Condoleezza Rice.
The effort would have echoes of the American military's promotion of South Vietnamese "village militias" during the Vietnam War, which some American counterinsurgency experts say was a relative success.
Sheik Abdul Sattar and the Anbar Salvation Council, the group of 25 tribes that the sheik said he had helped pull together to fight Al Qaeda, would be central to any such move by the Americans.
The sheik said he and his allies, who also call themselves the Anbar Awakening, had recruited 6,000 fighters from the tribes into the Anbar police, helped appoint a new provincial police chief and formed a 2,500-member "emergency brigade" answering to him.