package net.frontlinesms.messaging.mms; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import javax.mail.internet.ContentType; import javax.mail.internet.ParseException; import net.frontlinesms.FrontlineUtils; import net.frontlinesms.data.domain.FrontlineMultimediaMessage; import net.frontlinesms.data.domain.FrontlineMultimediaMessagePart; import net.frontlinesms.data.domain.FrontlineMessage.Status; import net.frontlinesms.data.domain.FrontlineMessage.Type; import net.frontlinesms.mms.BinaryMmsMessagePart; import net.frontlinesms.mms.MmsMessage; import net.frontlinesms.mms.MmsMessagePart; import net.frontlinesms.mms.TextMmsMessagePart; import net.frontlinesms.mms.email.receive.parser.EmailMmsParser; import net.frontlinesms.mms.email.receive.parser.GenericMmsParser; import net.frontlinesms.mms.email.receive.parser.fr.VirginMobileFrMmsParser; import net.frontlinesms.mms.email.receive.parser.ke.SafaricomKeMmsParser; import net.frontlinesms.mms.email.receive.parser.ru.MtsRuMmsParser; import net.frontlinesms.mms.email.receive.parser.uk.*; import net.frontlinesms.mms.email.receive.parser.us.AttUsMmsParser; import net.frontlinesms.mms.email.receive.parser.us.VerizonUsMmsParser; import net.frontlinesms.resources.ResourceUtils; import org.apache.log4j.Logger; public class MmsUtils { private static final String MMS_DATA_DIRECTORY = "data/mms/"; private static final Logger log = FrontlineUtils.getLogger(MmsUtils.class); /** Create a new {@link FrontlineMultimediaMessage} from a {@link MmsMessage} */ public static FrontlineMultimediaMessage create(MmsMessage mms) { StringBuilder textContent = new StringBuilder(); List<FrontlineMultimediaMessagePart> multimediaParts = new ArrayList<FrontlineMultimediaMessagePart>(); List<MmsMessagePart> mmsParts = mms.getParts(); for(MmsMessagePart part : mmsParts) { if(textContent.length() > 0) textContent.append("; "); String text; FrontlineMultimediaMessagePart mmPart; if (part instanceof TextMmsMessagePart) { TextMmsMessagePart textPart = (TextMmsMessagePart) part; text = textPart.toString(); mmPart = FrontlineMultimediaMessagePart.createTextPart(textPart.getContent()); } else if (part instanceof BinaryMmsMessagePart) { BinaryMmsMessagePart binaryPart = (BinaryMmsMessagePart) part; text = "File: " + binaryPart.getFilename(); mmPart = createBinaryPart(binaryPart); } else { text = "Unhandled: " + part.toString(); mmPart = FrontlineMultimediaMessagePart.createTextPart("Unhandled part!"); } textContent.append(text); multimediaParts.add(mmPart); } String subject = mms.getSubject(); if(subject == null) subject = ""; FrontlineMultimediaMessage message = new FrontlineMultimediaMessage(Type.RECEIVED, subject, textContent.toString(), multimediaParts); message.setRecipientMsisdn(mms.getReceiver()); message.setSenderMsisdn(mms.getSender()); message.setStatus(Status.RECEIVED); if (mms.getDate() != null) { message.setDate(mms.getDate().getTime()); } return message; } /** Binary files utils */ private static FrontlineMultimediaMessagePart createBinaryPart(BinaryMmsMessagePart imagePart) { // save the binary data to file FrontlineMultimediaMessagePart fmmPart = FrontlineMultimediaMessagePart.createBinaryPart(imagePart.getFilename()); File localFile = getUniqueFilename(appendFileExtensionIfNeeded(fmmPart, imagePart.getMimeType())); writeBinaryFile(localFile, imagePart.getData()); return fmmPart; } private static FrontlineMultimediaMessagePart appendFileExtensionIfNeeded(FrontlineMultimediaMessagePart fmmPart, String mimeType) { if (mimeType != null && (fmmPart.getFilename().indexOf('.') < 0 || fmmPart.getFilename().endsWith("."))) { fmmPart.setFilename(fmmPart.getFilename() + getExtensionFromImageMimeType(mimeType)); } return fmmPart; } private static String getExtensionFromImageMimeType(String mimeType) { try { return "." + new ContentType(mimeType).getSubType(); } catch (ParseException e) { return ""; } } private static void writeBinaryFile(File file, byte[] data) { FileOutputStream fos = null; BufferedOutputStream out = null; try { file.getParentFile().mkdirs(); fos = new FileOutputStream(file); out = new BufferedOutputStream(fos); out.write(data); } catch (IOException ex) { log.warn("Failed to write MMS file: " + file.getAbsolutePath(), ex); } finally { if(out != null) try { out.close(); } catch(IOException ex) { /* ah well :/ */ } if(fos != null) try { fos.close(); } catch(IOException ex) { /* ah well :/ */ } } } private static File getUniqueFilename(FrontlineMultimediaMessagePart fmmPart) { File localFile = getFile(fmmPart); while(localFile.exists()) { // need to handle file collisions here - e.g. rename the file fmmPart.setFilename(getAlternateFilename(fmmPart.getFilename())); localFile = getFile(fmmPart); } return localFile; } private static String getAlternateFilename(String filename) { String namePart = FrontlineUtils.getFilenameWithoutAnyExtension(filename); String extension = FrontlineUtils.getWholeFileExtension(filename); return namePart + '_' + new Random().nextInt(99) + '.' + extension; } public static File getFile(FrontlineMultimediaMessagePart part) { return new File(getMmsPartsDirectory(), part.getFilename().replaceAll(" ", "_")); } public static String getAbsolutePath(String filename) { return new File(getMmsPartsDirectory(), filename).getPath(); } public static File getMmsPartsDirectory() { return new File(ResourceUtils.getConfigDirectoryPath(), MMS_DATA_DIRECTORY); } public static List<EmailMmsParser> getAllEmailMmsParsers () { return Arrays.asList(new EmailMmsParser[]{ new O2UkMmsParser(), new OrangeUkMmsParser(), new ThreeUkMmsParser(), new TmobileUkMmsParser(), new VodafoneUkMmsParser(), new AttUsMmsParser(), new MtsRuMmsParser(), new SafaricomKeMmsParser(), new VerizonUsMmsParser(), new VirginMobileFrMmsParser(), new GenericMmsParser(), }); } }