private boolean handleSpot(MimeMessage message) throws IOException, MessagingException { String spotTime = getSpotHeader(message, "X-SPOT-Time"); if (spotTime != null) { String spotLatitude = getSpotHeader(message, "X-SPOT-Latitude"); String spotLongitude = getSpotHeader(message, "X-SPOT-Longitude"); String spotMessenger = getSpotHeader(message, "X-SPOT-Messenger"); String spotType = getSpotHeader(message, "X-SPOT-Type"); Date time = new Date(Long.parseLong(spotTime) * 1000); GeoPt geoPt = new GeoPt(Float.parseFloat(spotLatitude), Float.parseFloat(spotLongitude)); DS ds = DS.get(); ds.addPlacemark(time, geoPt, spotMessenger, spotType); return true; } return false; }
private void sendMail( HttpServletRequest request, BlogAuthor blogAuthor, Entity blog, Settings settings) throws IOException { if (settings.dontSendEmail()) { return; } try { String digest = DS.getBlogDigest(blog); MailService mailService = MailServiceFactory.getMailService(); Message reply = new Message(); reply.setSender(blogAuthor.toString()); Email sender = (Email) blog.getProperty(SenderProperty); reply.setTo(sender.getEmail()); String subject = (String) blog.getProperty(SubjectProperty); reply.setSubject("Blog: " + subject + " received"); StringBuilder sb = new StringBuilder(); URI reqUri = new URI(request.getScheme(), NamespaceManager.get(), "", ""); if (!settings.isPublishImmediately()) { sb.append("<div>"); sb.append( "<p>Blog is not yet published because it was sent from untrusted email address " + sender.getEmail() + ". </p>"); URI publishUri = reqUri.resolve( "/blog?action=publish&blog=" + KeyFactory.keyToString(blog.getKey()) + "&auth=" + digest); sb.append("<a href=\"" + publishUri.toASCIIString() + "\">Publish Blog</a>"); sb.append("</div>"); } sb.append("<div>"); sb.append("<p>If blog is not ok, you can delete and then resend it.</p>"); URI deleteUri = reqUri.resolve( "/blog?action=remove&blog=" + KeyFactory.keyToString(blog.getKey()) + "&auth=" + digest); sb.append("<a href=\"" + deleteUri.toASCIIString() + "\">Delete Blog</a>"); sb.append("</div>"); reply.setHtmlBody(sb.toString()); mailService.send(reply); } catch (URISyntaxException ex) { throw new IOException(ex); } }
private void remove(String encoded, HttpServletResponse response) throws IOException { BlobstoreService blobstore = BlobstoreServiceFactory.getBlobstoreService(); DatastoreService datastore = DS.get(); Key key = KeyFactory.stringToKey(encoded); Transaction tr = datastore.beginTransaction(); try { Entity blog = datastore.get(key); datastore.delete(key); response.setContentType("text/plain"); PrintWriter writer = response.getWriter(); writer.println("Deleted blog: " + blog.getProperty("Subject")); tr.commit(); } catch (EntityNotFoundException ex) { throw new IOException(ex); } finally { if (tr.isActive()) { tr.rollback(); } } }
public GeoData(DS ds) { Iterable<Entity> tracksIterable = ds.fetchTracks(); Iterable<Entity> imageLocationsIterable = ds.fetchImageLocations(); Iterable<Entity> blogLocationsIterable = ds.fetchBlogLocations(); boxList = new HashMapList<>(); Date lastBegin = null; for (Entity track : tracksIterable) { BoundingBox bbTrack = new BoundingBox(track); for (Entity trackSeq : ds.fetchTrackSeqs(track.getKey())) { BoundingBox bbTrackSeq = new BoundingBox(trackSeq); boxList.add(bbTrack, new Pair<BoundingBox, Key>(bbTrackSeq, trackSeq.getKey())); Date begin = (Date) trackSeq.getProperty(BeginProperty); if (lastBegin == null || lastBegin.before(begin)) { lastBegin = begin; } } } Iterable<Entity> placemarksIterable; if (lastBegin != null) { placemarksIterable = ds.fetchPlacemarks(lastBegin); } else { placemarksIterable = ds.fetchPlacemarks(); } firstPlacemarkKey = null; placemarkBoundingBox = new BoundingBox(); for (Entity placemark : placemarksIterable) { if (firstPlacemarkKey == null) { firstPlacemarkKey = placemark.getKey(); } GeoPt location = (GeoPt) placemark.getProperty(LocationProperty); placemarkBoundingBox.add(location); } locationList = new ArrayList<>(); for (Entity metadata : imageLocationsIterable) { GeoPt location = (GeoPt) metadata.getProperty(LocationProperty); if (location != null) { locationList.add(new Pair<>(location, metadata.getKey())); } } for (Entity blog : blogLocationsIterable) { GeoPt location = (GeoPt) blog.getProperty(LocationProperty); if (location != null) { locationList.add(new Pair<>(location, blog.getKey())); } } }
private Collection<Future<HTTPResponse>> handleBodyPart( HttpServletRequest request, Entity blog, BodyPart bodyPart, final Settings settings) throws MessagingException, IOException { ImagesService imagesService = ImagesServiceFactory.getImagesService(); DS ds = DS.get(); Collection<Future<HTTPResponse>> futures = new ArrayList<>(); String contentType = bodyPart.getContentType(); log(contentType); Object content = bodyPart.getContent(); if (content instanceof InputStream) { String filename = bodyPart.getFileName(); byte[] bytes = getBytes(bodyPart); String digestString = DS.getDigest(bytes); Entity metadata = createMetadata(digestString, filename, contentType, bytes); if (contentType.startsWith("image/")) { int oWidth; int oHeight; int wWidth; int wHeight; Image image = ImagesServiceFactory.makeImage(bytes); if (settings.isFixPic()) { Transform makeImFeelingLucky = ImagesServiceFactory.makeImFeelingLucky(); image = imagesService.applyTransform(makeImFeelingLucky, image); } oWidth = image.getWidth(); oHeight = image.getHeight(); if (image.getHeight() > settings.getPicMaxHeight() || image.getWidth() > settings.getPicMaxWidth()) { log( "shrinking [" + image.getHeight() + ", " + image.getWidth() + "] > [" + settings.getPicMaxHeight() + ", " + settings.getPicMaxWidth() + "]"); Transform makeResize = ImagesServiceFactory.makeResize( settings.getPicMaxHeight(), settings.getPicMaxWidth()); Image shrinken = imagesService.applyTransform(makeResize, image); wWidth = shrinken.getWidth(); wHeight = shrinken.getHeight(); Future<HTTPResponse> res = postBlobs( filename, contentType, digestString, shrinken.getImageData(), WebSizeProperty, request, wWidth, wHeight); futures.add(res); } else { wWidth = image.getWidth(); wHeight = image.getHeight(); Future<HTTPResponse> res = postBlobs( filename, contentType, digestString, bytes, WebSizeProperty, request, wWidth, wHeight); futures.add(res); } Future<HTTPResponse> res = postBlobs( filename, contentType, digestString, bytes, OriginalSizeProperty, request, oWidth, oHeight); futures.add(res); String[] cids = bodyPart.getHeader("Content-ID"); if (cids != null && cids.length > 0) { String alt = (String) metadata.getProperty(UserCommentProperty); if (alt == null) { alt = ""; } replaceBlogRef(blog, cids[0], digestString, wWidth, wHeight, alt); } } if (contentType.startsWith("application/vnd.google-earth.kml+xml") || filename.endsWith(".kml")) { try { InputStream is = (InputStream) content; KML kml = new KML(is); PlacemarkUpdater pu = new PlacemarkUpdater(ds, kml, LocatorLevel.Field); pu.visit(kml, null); } catch (JAXBException ex) { log("reading kml failed", ex); } } if (contentType.startsWith("application/vnd.google-earth.kmz") || filename.endsWith(".kmz")) { try { InputStream is = (InputStream) content; KMZ kmz = new KMZ(is); PlacemarkUpdater pu = new PlacemarkUpdater(ds, kmz, LocatorLevel.Field); pu.visit(kmz, null); } catch (JAXBException ex) { log("reading kmz failed", ex); } } if (filename.endsWith(".gpx")) { try { InputStream is = (InputStream) content; final GPX gpx = new GPX(is); final OpenCPNTrackHandler handler = new OpenCPNTrackHandler(ds); RunInNamespace rin = new RunInNamespace() { @Override protected Object run() { gpx.browse( settings.getTrackBearingTolerance(), settings.getTrackMinimumDistance(), settings.getTrackMaxSpeed(), handler); return null; } }; rin.doIt(null, settings.isCommonPlacemarks()); } catch (JAXBException ex) { log("reading gpx failed", ex); } } if (filename.endsWith(".trc")) { InputStream is = (InputStream) content; final TrackInput trackInput = new TrackInput(is); final CompressedTrackHandler cth = new CompressedTrackHandler(ds); RunInNamespace rin = new RunInNamespace() { @Override protected Object run() { try { cth.handle(trackInput); } catch (IOException ex) { log(ex.getMessage(), ex); } return null; } }; rin.doIt(null, settings.isCommonPlacemarks()); } if (contentType.startsWith("application/X-jsr179-location-nmea") || filename.endsWith(".nmea")) { log("NMEA not yet supported"); } } return futures; }
private void handleMail( HttpServletRequest request, HttpServletResponse response, BlogAuthor blogAuthor) throws IOException, ServletException, EntityNotFoundException, MessagingException, HttpException { DS ds = DS.get(); Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); MimeMessage message = new MimeMessage(session, request.getInputStream()); String messageId = getMessageId(message); String contentType = message.getContentType(); if (messageId == null) { log("messageID missing"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } log("Message-ID=" + messageId); // TODO authorization if (handleSpot(message)) { return; } InternetAddress sender = (InternetAddress) message.getSender(); log("sender=" + sender); if (sender == null) { Address[] from = message.getFrom(); if (from != null && from.length != 0) { sender = (InternetAddress) from[0]; } } if (sender == null) { log("Sender missing"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } Email senderEmail = new Email(sender.getAddress()); Settings settings = ds.getSettingsFor(senderEmail); if (settings == null) { log(senderEmail.getEmail() + " not allowed to send blogs"); response.sendError(HttpServletResponse.SC_FORBIDDEN); return; } String[] ripperDate = message.getHeader(BlogRipper + "Date"); boolean ripping = ripperDate != null && ripperDate.length > 0; Object content = message.getContent(); if (content instanceof Multipart) { Multipart multipart = (Multipart) message.getContent(); List<BodyPart> bodyPartList = findParts(multipart); try { Entity blog = null; String htmlBody = getHtmlBody(bodyPartList); if (htmlBody != null && htmlBody.length() > 10) { boolean publishImmediately = settings.isPublishImmediately(); blog = updateBlog(messageId, message, htmlBody, publishImmediately, senderEmail); if (!ripping) { if (blog != null) { sendMail(request, blogAuthor, blog, settings); } } else { log("not sending email because ripping"); } } else { log("no html body"); } List<Future<HTTPResponse>> futureList = new ArrayList<Future<HTTPResponse>>(); for (BodyPart bodyPart : bodyPartList) { Collection<Future<HTTPResponse>> futures = handleBodyPart(request, blog, bodyPart, settings); if (futures != null) { futureList.addAll(futures); } } long remainingMillis = ApiProxy.getCurrentEnvironment().getRemainingMillis(); log("remainingMillis=" + remainingMillis); for (Future<HTTPResponse> res : futureList) { try { HTTPResponse hr = res.get(); log("code=" + hr.getResponseCode()); if (hr.getResponseCode() != HttpServletResponse.SC_OK) { throw new ServletException("blob upload failed code=" + hr.getResponseCode()); } } catch (InterruptedException ex) { throw new IOException(ex); } catch (ExecutionException ex) { throw new IOException(ex); } } } catch (MessagingException ex) { throw new IOException(ex); } } else { if (content instanceof String) { String bodyPart = (String) content; if (contentType.startsWith("text/plain")) { bodyPart = textPlainToHtml(bodyPart); } boolean publishImmediately = settings.isPublishImmediately(); Entity blog = updateBlog(messageId, message, bodyPart, publishImmediately, senderEmail); if (blog != null) { sendMail(request, blogAuthor, blog, settings); } } else { log("body not MultiPart of String"); } } }