bool LiteEditorFile::open(const QString &fileName, const QString &mimeType, bool bCheckCodec) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) { return false; } const QFileInfo fi(fileName); m_bReadOnly = !fi.isWritable(); m_mimeType = mimeType; m_fileName = fileName; QByteArray buf = file.readAll(); m_hasDecodingError = false; if (bCheckCodec) { if (mimeType == "text/html" || mimeType == "text/xml") { m_codec = QTextCodec::codecForHtml(buf,QTextCodec::codecForName("utf-8")); } else { LiteApi::IMimeType *im = m_liteApp->mimeTypeManager()->findMimeType(mimeType); if (im) { QString codecName = im->codec(); if (!codecName.isEmpty()) { m_codec = QTextCodec::codecForName(codecName.toAscii()); } } int bytesRead = buf.size(); QTextCodec *codec = m_codec; // code taken from qtextstream if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0) || (uchar(buf[0]) == 0 && uchar(buf[1]) == 0 && uchar(buf[2]) == 0xfe && uchar(buf[3]) == 0xff))) { codec = QTextCodec::codecForName("UTF-32"); } else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe) || (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) { codec = QTextCodec::codecForName("UTF-16"); } else if (bytesRead >= 3 && uchar(buf[0]) == 0xef && uchar(buf[1]) == 0xbb && uchar(buf[2])== 0xbf) { codec = QTextCodec::codecForName("UTF-8"); } else if (!codec) { codec = QTextCodec::codecForLocale(); } // end code taken from qtextstream m_codec = codec; } } QTextCodec::ConverterState state; QString text = m_codec->toUnicode(buf,buf.size(),&state); if (state.invalidChars > 0 || state.remainingChars > 0) { m_hasDecodingError = true; } //qDebug() << state.invalidChars << state.remainingChars; /* QByteArray verifyBuf = m_codec->fromUnicode(text); // slow // the minSize trick lets us ignore unicode headers int minSize = qMin(verifyBuf.size(), buf.size()); m_hasDecodingError = (minSize < buf.size()- 4 || memcmp(verifyBuf.constData() + verifyBuf.size() - minSize, buf.constData() + buf.size() - minSize, minSize)); */ /* if (text.length()*2+4 < buf.length()) { m_hasDecodingError = true; } */ int lf = text.indexOf('\n'); if (lf < 0) { m_lineTerminatorMode = NativeLineTerminator; } else if (lf == 0) { m_lineTerminatorMode = LFLineTerminator; } else { lf = text.indexOf(QRegExp("[^\r]\n"),lf-1); if (lf >= 0) { m_lineTerminatorMode = LFLineTerminator; } else { m_lineTerminatorMode = CRLFLineTerminator; } } bool noprintCheck = m_liteApp->settings()->value(EDITOR_NOPRINTCHECK,true).toBool(); if (noprintCheck) { for (int i = 0; i < text.length(); i++) { if (!text[i].isPrint() && !text[i].isSpace() && text[i] != '\r' && text[i] != '\n') { text[i] = '.'; m_hasDecodingError = true; } } } m_document->setPlainText(text); return true; }
bool LiteEditorFile::loadFileHelper(const QString &fileName, const QString &mimeType, bool bCheckCodec, QString &outText) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) { return false; } const QFileInfo fi(fileName); m_bReadOnly = !fi.isWritable(); m_mimeType = mimeType; m_fileName = fileName; if (file.size() > (3 << 24)) { m_liteApp->appendLog("LiteEditor","Large file not open in the text editor! "+fileName,true); m_hasDecodingError = true; return false; } QByteArray buf = file.readAll(); m_hasDecodingError = false; if (HasBinaryData(buf,32)) { m_liteApp->appendLog("LiteEditor","Binary file not open in the text editor! "+fileName,true); m_hasDecodingError = true; //outText = "error load binary file!!!"; return false; } if (bCheckCodec) { m_codec = QTextCodec::codecForName("UTF-8"); m_hasUtf8Bom = false; if (mimeType == "text/html" || mimeType == "text/xml") { m_codec = QTextCodec::codecForHtml(buf,QTextCodec::codecForName("utf-8")); } else { LiteApi::IMimeType *im = m_liteApp->mimeTypeManager()->findMimeType(mimeType); if (im) { QString codecName = im->codec(); if (!codecName.isEmpty()) { m_codec = QTextCodec::codecForName(codecName.toLatin1()); } } int bytesRead = buf.size(); QTextCodec *codec = m_codec; // code taken from qtextstream if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0) || (uchar(buf[0]) == 0 && uchar(buf[1]) == 0 && uchar(buf[2]) == 0xfe && uchar(buf[3]) == 0xff))) { codec = QTextCodec::codecForName("UTF-32"); } else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe) || (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) { codec = QTextCodec::codecForName("UTF-16"); } else if (bytesRead >= 3 && uchar(buf[0]) == 0xef && uchar(buf[1]) == 0xbb && uchar(buf[2])== 0xbf) { codec = QTextCodec::codecForName("UTF-8"); buf.remove(0,3); m_hasUtf8Bom = true; } else if (!codec){ codec = QTextCodec::codecForLocale(); } // end code taken from qtextstream m_codec = codec; } } QTextCodec::ConverterState state; outText = m_codec->toUnicode(buf,buf.size(),&state); if (state.invalidChars > 0 || state.remainingChars > 0) { m_hasDecodingError = true; } if (m_hasDecodingError && bCheckCodec) { QByteArray testName = m_libucd.parse(buf); if (!testName.isEmpty()) { QTextCodec *c = QTextCodec::codecForName(testName); if (c && (c->mibEnum() != m_codec->mibEnum()) ) { QTextCodec::ConverterState testState; QString testText = c->toUnicode(buf,buf.size(),&testState); if (testState.invalidChars == 0 && testState.remainingChars == 0) { m_hasDecodingError = false; m_codec = c; outText = testText; } } } } /* QByteArray verifyBuf = m_codec->fromUnicode(text); // slow // the minSize trick lets us ignore unicode headers int minSize = qMin(verifyBuf.size(), buf.size()); m_hasDecodingError = (minSize < buf.size()- 4 || memcmp(verifyBuf.constData() + verifyBuf.size() - minSize, buf.constData() + buf.size() - minSize, minSize)); */ /* if (text.length()*2+4 < buf.length()) { m_hasDecodingError = true; } */ int lf = outText.indexOf('\n'); if (lf < 0) { m_lineTerminatorMode = NativeLineTerminator; } else if (lf == 0) { m_lineTerminatorMode = LFLineTerminator; } else { lf = outText.indexOf(QRegExp("[^\r]\n"),lf-1); if (lf >= 0) { m_lineTerminatorMode = LFLineTerminator; } else { m_lineTerminatorMode = CRLFLineTerminator; } } if (m_lineTerminatorMode == CRLFLineTerminator) { outText.replace("\r\n","\n"); } bool noprintCheck = m_liteApp->settings()->value(EDITOR_NOPRINTCHECK,true).toBool(); if (noprintCheck && !LiteApi::mimeIsText(mimeType)) { for (int i = 0; i < outText.length(); i++) { // if (!outText[i].isPrint() && !outText[i].isSpace() && outText[i] != '\r' && outText[i] != '\n') { // outText[i] = '.'; // m_hasDecodingError = true; // } if (IsBinaryCode(outText[i].unicode())) { outText[i] = '.'; m_hasDecodingError = true; } } } if (m_hasDecodingError) { m_liteApp->appendLog("LiteEditor",QString("Decode file error! file:\"%1\" codec:%2").arg(fileName).arg(textCodec()),true); } return true; }