OSDN Git Service

Correct problem parsing notes where carriage returns did not separate some XML lines...
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / utilities / FileImporter.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 \r
20 package cx.fbn.nevernote.utilities;\r
21 \r
22 import java.io.File;\r
23 import java.security.MessageDigest;\r
24 import java.security.NoSuchAlgorithmException;\r
25 import java.util.ArrayList;\r
26 import java.util.Calendar;\r
27 import java.util.GregorianCalendar;\r
28 \r
29 import com.evernote.edam.type.Data;\r
30 import com.evernote.edam.type.Note;\r
31 import com.evernote.edam.type.NoteAttributes;\r
32 import com.evernote.edam.type.Resource;\r
33 import com.evernote.edam.type.ResourceAttributes;\r
34 import com.trolltech.qt.core.QByteArray;\r
35 import com.trolltech.qt.core.QFile;\r
36 import com.trolltech.qt.core.QFileInfo;\r
37 import com.trolltech.qt.core.QIODevice;\r
38 import com.trolltech.qt.webkit.QWebPage;\r
39 \r
40 import cx.fbn.nevernote.Global;\r
41 import cx.fbn.nevernote.NeverNote;\r
42 import cx.fbn.nevernote.sql.DatabaseConnection;\r
43 \r
44 \r
45 \r
46 public class FileImporter  {\r
47 \r
48         private final ApplicationLogger logger;\r
49         private String                          fileName;\r
50         private String                          content;\r
51         private QFileInfo                       fileInfo;\r
52         private Note                            newNote;\r
53         private String                          noteString;\r
54         private final DatabaseConnection        conn;\r
55         \r
56         \r
57         public FileImporter(ApplicationLogger l, DatabaseConnection c) {\r
58                 logger = l;\r
59                 conn = c;\r
60         }\r
61         \r
62         \r
63         //********************************************************\r
64         //* Begin to import the file\r
65         //********************************************************\r
66         public boolean importFile() {\r
67                 if (fileInfo.isFile()) {\r
68                         if (!validAttachment(fileInfo.completeSuffix()))\r
69                                 return false;\r
70                         if (fileInfo.completeSuffix().equalsIgnoreCase("txt"))\r
71                                 return importTextFile();\r
72                         return importAttachment();\r
73                 }\r
74                 return false;\r
75         }\r
76         \r
77         //********************************************************\r
78         //* Import text files \r
79         //********************************************************\r
80         public boolean importTextFile() {\r
81                 QFile file = new QFile(fileName);\r
82                 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {\r
83                         // If we can't get to the file, it is probably locked.  We'll try again later.\r
84                         logger.log(logger.LOW, "Unable to save externally edited file - locked.  Saving for later.");\r
85                         return false;\r
86                 }\r
87                 QByteArray binData = file.readAll();\r
88                 file.close();\r
89                 if (binData.size() == 0) {\r
90                         // If we can't get to the file, it is probably locked.  We'll try again later.\r
91                         logger.log(logger.LOW, "Unable to save externally edited file - zero size.  Saving for later.");\r
92                         return false;\r
93                 }\r
94         \r
95                 String fileData =binData.toString();\r
96                 \r
97                 // Fix \r\n & \n and turn inte HTML\r
98                 QWebPage page = new QWebPage();\r
99                 page.mainFrame().setContent(binData);\r
100                 fileData = page.mainFrame().toHtml();\r
101                 fileData = fileData.replace("\n", "<br>\n");\r
102 \r
103                 noteString = new String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +\r
104                                 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +\r
105                                 "<en-note>\n<br clear=\"none\" />"+fileData+"</en-note>");\r
106 \r
107                 noteString = fileData;\r
108                 buildEmptyNote();\r
109         newNote.setAttributes(new NoteAttributes());\r
110                         \r
111             return true;\r
112         }\r
113 \r
114         //********************************************************\r
115         //* Import an image\r
116         //********************************************************\r
117         public boolean importAttachment() {\r
118                 QFile file = new QFile(fileName);\r
119                 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {\r
120                         // If we can't get to the file, it is probably locked.  We'll try again later.\r
121                         logger.log(logger.LOW, "Unable to save externally edited file - locked.  Saving for later.");\r
122                         return false;\r
123                 }\r
124                 QByteArray binData = file.readAll();\r
125                 file.close();\r
126                 if (binData.size() == 0) {\r
127                         // If we can't get to the file, it is probably locked.  We'll try again later.\r
128                         logger.log(logger.LOW, "Unable to save externally edited file - zero size.  Saving for later.");\r
129                         return false;\r
130                 }\r
131                         \r
132                 buildEmptyNote();\r
133         newNote.setAttributes(new NoteAttributes());\r
134     \r
135         // Start building the resource itself\r
136         StringBuffer buffer = new StringBuffer();\r
137         buffer.append("<html><head></head><body>\n");\r
138         \r
139         Resource newRes;\r
140         \r
141         // If we have an image\r
142         if (isImage(fileInfo.completeSuffix())) {\r
143                 String mimeType = "image/" +fileInfo.completeSuffix();\r
144                 if (mimeType.equals("image/jpg"))\r
145                         mimeType = "image/jpeg";\r
146                 newRes = createResource(mimeType, false);\r
147                 \r
148                 buffer.append("<img src=\"" +fileName);\r
149                 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""\r
150                                 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
151                                 +" guid=\"" +newRes.getGuid() +"\">");\r
152         } else {\r
153                 // We have an attachment, not an image.\r
154                 \r
155                 \r
156                 String mimeType = "application/" +fileInfo.completeSuffix();\r
157                 newRes = createResource(mimeType, false);\r
158                 newRes.getAttributes().setFileName(fileInfo.fileName());\r
159                 \r
160                 String icon = findIcon(fileInfo.completeSuffix());\r
161                 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));\r
162                 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");\r
163                         buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");\r
164                         buffer.append("<img src=\"" + imageURL +"\" title=\"" +newRes.getAttributes().getFileName());\r
165                         buffer.append("\">");\r
166                         buffer.append("</a>");\r
167         }\r
168                 buffer.append("</body></html>");\r
169                 \r
170                 content = buffer.toString();\r
171                 noteString = buffer.toString();\r
172                 newNote.setContent(content);\r
173                 newNote.setResources(new ArrayList<Resource>());\r
174                 newNote.getResources().add(newRes);\r
175                 newNote.setResourcesIsSet(true);\r
176         \r
177         return true;\r
178         }\r
179         \r
180         //********************************************************\r
181         //* Check if we found a valid file type\r
182         //********************************************************\r
183         // Check if the account supports this type of attachment\r
184         private boolean validAttachment(String type) {\r
185                 if (Global.isPremium())\r
186                         return true;\r
187                 if (type.equalsIgnoreCase("JPG"))\r
188                         return true;\r
189                 if (type.equalsIgnoreCase("PNG"))\r
190                         return true;\r
191                 if (type.equalsIgnoreCase("GIF"))\r
192                         return true;\r
193                 if (type.equalsIgnoreCase("MP3"))\r
194                         return true;\r
195                 if (type.equalsIgnoreCase("WAV"))\r
196                         return true;\r
197                 if (type.equalsIgnoreCase("AMR"))\r
198                         return true;\r
199                 if (type.equalsIgnoreCase("PDF"))\r
200                         return true;\r
201                 if (type.equalsIgnoreCase("TXT"))\r
202                         return true;\r
203                 return false;\r
204         }\r
205         \r
206         //********************************************************\r
207         //* Check if we found an image\r
208         //********************************************************\r
209         // Check if the account supports this type of attachment\r
210         private boolean isImage(String type) {\r
211                 if (type.equalsIgnoreCase("JPG"))\r
212                         return true;\r
213                 if (type.equalsIgnoreCase("JPEG"))\r
214                         return true;\r
215                 if (type.equalsIgnoreCase("PNG"))\r
216                         return true;\r
217                 if (type.equalsIgnoreCase("GIF"))\r
218                         return true;\r
219                 if (!Global.isPremium()) \r
220                         return false;\r
221                 if (type.equalsIgnoreCase("XPM"))\r
222                         return true;\r
223                 if (type.equalsIgnoreCase("BMP"))\r
224                         return true;\r
225 \r
226                 return false;\r
227         }\r
228 \r
229         //********************************************************\r
230         //* Build an empty note\r
231         //********************************************************\r
232         private void buildEmptyNote() {\r
233                 Calendar currentTime = new GregorianCalendar();\r
234                 String baseNote = new String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +\r
235                                 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +\r
236                                 "<en-note>\n<br clear=\"none\" /></en-note>");\r
237                 Long l = new Long(currentTime.getTimeInMillis());\r
238                 long prevTime = l;\r
239                 while (prevTime==l) {\r
240                         currentTime = new GregorianCalendar();\r
241                         l=currentTime.getTimeInMillis();\r
242                 }\r
243                 \r
244                 String randint = new String(Long.toString(l));\r
245                 \r
246         newNote = new Note();\r
247         newNote.setUpdateSequenceNum(0);\r
248         newNote.setGuid(randint);\r
249         newNote.setTitle(fileName);\r
250         newNote.setContent(baseNote);\r
251         newNote.setDeleted(0);\r
252         int cdate = fileInfo.created().toTime_t();\r
253         int mdate = fileInfo.lastModified().toTime_t();\r
254         newNote.setCreated((long)cdate*1000);\r
255         newNote.setUpdated((long)mdate*1000);\r
256         newNote.setActive(true);\r
257         NoteAttributes na = new NoteAttributes();\r
258         na.setLatitude(0.0);\r
259         na.setLongitude(0.0);\r
260         na.setAltitude(0.0);\r
261         }\r
262         //********************************************************\r
263         //* Check valid file types\r
264         //********************************************************\r
265         public boolean isValidType() {\r
266                 if (!checkFileAttachmentSize(fileName))\r
267                         return false;\r
268                 if (fileInfo.completeSuffix().equalsIgnoreCase("txt"))\r
269                         return true;\r
270                 if (validAttachment(fileInfo.completeSuffix()))\r
271                         return true;\r
272                 return false;\r
273         }\r
274         //**************************************************************\r
275         //* Check the file attachment to be sure it isn't over 25 mb\r
276         //**************************************************************\r
277         private boolean checkFileAttachmentSize(String url) {\r
278                 QFile resourceFile = new QFile(fileName);\r
279                 resourceFile.open(new QIODevice.OpenMode(\r
280                                 QIODevice.OpenModeFlag.ReadOnly));\r
281                 long size = resourceFile.size();\r
282                 resourceFile.close();\r
283                 size = size / 1024 / 1024;\r
284                 if (size < 50 && Global.isPremium())\r
285                         return true;\r
286                 if (size < 25)\r
287                         return true;\r
288                 return false;\r
289         }\r
290 \r
291         //********************************************************\r
292         //* Build a new resource\r
293         //********************************************************\r
294         private Resource createResource(String mime, boolean attachment) {\r
295                 QFile resourceFile;\r
296         resourceFile = new QFile(fileName); \r
297         resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));\r
298         byte[] fileData = resourceFile.readAll().toByteArray();\r
299         resourceFile.close();\r
300         if (fileData.length == 0)\r
301                 return null;\r
302         MessageDigest md;\r
303         try {\r
304                 md = MessageDigest.getInstance("MD5");\r
305                 md.update(fileData);\r
306                 byte[] hash = md.digest();\r
307   \r
308                 Resource r = new Resource();\r
309                 Calendar time = new GregorianCalendar();\r
310                 Long l = time.getTimeInMillis();\r
311                 long prevTime = l;\r
312                 while (l==prevTime) {\r
313                         time = new GregorianCalendar();\r
314                         l=time.getTimeInMillis();\r
315                 }\r
316                 r.setGuid(new Long(l).toString());\r
317                 r.setNoteGuid(newNote.getGuid());\r
318                 r.setMime(mime);\r
319                 r.setActive(true);\r
320                 r.setUpdateSequenceNum(0);\r
321                 r.setWidth((short) 0);\r
322                 r.setHeight((short) 0);\r
323                 r.setDuration((short) 0);\r
324                                 \r
325                 Data d = new Data();\r
326                 d.setBody(fileData);\r
327                 d.setBodyIsSet(true);\r
328                 d.setBodyHash(hash);\r
329                 d.setBodyHashIsSet(true);\r
330                 r.setData(d);\r
331                 d.setSize(fileData.length);\r
332                 \r
333                 ResourceAttributes a = new ResourceAttributes();\r
334                 a.setAltitude(0);\r
335                 a.setAltitudeIsSet(false);\r
336                 a.setLongitude(0);\r
337                 a.setLongitudeIsSet(false);\r
338                 a.setLatitude(0);\r
339                 a.setLatitudeIsSet(false);\r
340                 a.setCameraMake("");\r
341                 a.setCameraMakeIsSet(false);\r
342                 a.setCameraModel("");\r
343                 a.setCameraModelIsSet(false);\r
344                 a.setAttachment(attachment);\r
345                 a.setAttachmentIsSet(true);\r
346                 a.setClientWillIndex(false);\r
347                 a.setClientWillIndexIsSet(true);\r
348                 a.setRecoType("");\r
349                 a.setRecoTypeIsSet(false);\r
350                 a.setSourceURLIsSet(false);\r
351                 a.setTimestamp(0);\r
352                 a.setTimestampIsSet(false);\r
353                 a.setFileName(fileInfo.fileName());\r
354                 a.setFileNameIsSet(true);\r
355                 r.setAttributes(a);\r
356                 \r
357                 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);\r
358                 return r;\r
359         } catch (NoSuchAlgorithmException e1) {\r
360                 e1.printStackTrace();\r
361                 }\r
362         return null;\r
363         }\r
364         \r
365         //********************************************************\r
366         //* set file name\r
367         //********************************************************\r
368         public void setFileInfo(QFileInfo f) {\r
369                 fileInfo = f;           \r
370         }\r
371         //********************************************************\r
372         //* Set file name\r
373         //********************************************************\r
374         public void setFileName(String f) {\r
375                 fileName = f;\r
376         }\r
377         //********************************************************\r
378         //* Get file contents\r
379         //********************************************************\r
380         public String getContent() {\r
381                 return content;\r
382         }\r
383         //********************************************************\r
384         //* Return the new note\r
385         //********************************************************\r
386         public Note getNote() {\r
387                 return newNote;\r
388         }\r
389         //********************************************************\r
390         //* Get just the content of the new note\r
391         //********************************************************\r
392         public String getNoteContent() {\r
393                 return noteString;\r
394         }\r
395 \r
396     /**\r
397      * find the appropriate icon for an attachment\r
398      * NFC TODO: duplicate of {@link NeverNote#findIcon(String)}\r
399      */\r
400     private String findIcon(String appl) {\r
401         appl = appl.toLowerCase();\r
402         String relativePath = appl + ".png";\r
403         File f = Global.getFileManager().getImageDirFile(relativePath);\r
404         if (f.exists()) {\r
405             return relativePath;\r
406         }\r
407         return "attachment.png";\r
408     }\r
409 \r
410 }\r