Example #1
0
int ShowFolderInOSWindow(ExtensionString pathname)
{
    int error = NO_ERROR;
    GError *gerror = NULL;
    gchar *uri = NULL, *parentdir = NULL;

    if (g_file_test(pathname.c_str(), G_FILE_TEST_IS_DIR)) {
        uri = g_filename_to_uri(pathname.c_str(), NULL, NULL);
        if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) {
            error = ConvertGnomeErrorCode(gerror);
            g_warning("%s", gerror->message);
            g_error_free(gerror);
        }
        g_free(uri);
    }
    else {
        if (!FileManager1_ShowItems(pathname.c_str())) {
            // Fall back to using gtk_show_uri on the dirname (without highlighting the file)
            parentdir = g_path_get_dirname(pathname.c_str());
            uri = g_filename_to_uri(parentdir, NULL, NULL);
            if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) {
                error = ConvertGnomeErrorCode(gerror);
                g_warning("%s", gerror->message);
                g_error_free(gerror);
            }
            g_free(parentdir);
            g_free(uri);
        }
    }

    return error;
}
Example #2
0
int32 ShowOpenDialog(bool allowMultipleSelection,
                     bool chooseDirectory,
                     ExtensionString title,
                     ExtensionString initialDirectory,
                     ExtensionString fileTypes,
                     CefRefPtr<CefListValue>& selectedFiles)
{
    GtkWidget *dialog;
    GtkFileChooserAction file_or_directory = chooseDirectory ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : GTK_FILE_CHOOSER_ACTION_OPEN ;
    dialog = gtk_file_chooser_dialog_new (title.c_str(),
                  NULL,
                  file_or_directory,
                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                  NULL);
    
    if (!initialDirectory.empty())
    {
        ExtensionString folderURI = std::string("file:///") + initialDirectory;
        gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), folderURI.c_str());
    }

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
        char *filename;
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        selectedFiles->SetString(0,filename);
        g_free (filename);
    }
    
    gtk_widget_destroy (dialog);
    return NO_ERROR;
}
int32 ShowSaveDialog(ExtensionString title,
                     ExtensionString initialDirectory,
                     ExtensionString proposedNewFilename,
                     ExtensionString& newFilePath)
{
    GtkWidget *openSaveDialog;
    
    openSaveDialog = gtk_file_chooser_dialog_new(title.c_str(),
        NULL,
        GTK_FILE_CHOOSER_ACTION_SAVE,
        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
        NULL);
    
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (openSaveDialog), TRUE);	
    if (!initialDirectory.empty())
    {
        gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (openSaveDialog), proposedNewFilename.c_str());
        
        ExtensionString folderURI = std::string("file:///") + initialDirectory;
        gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (openSaveDialog), folderURI.c_str());
    }
    
    if (gtk_dialog_run (GTK_DIALOG (openSaveDialog)) == GTK_RESPONSE_ACCEPT)
    {
        char* filePath;
        filePath = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (openSaveDialog));
        newFilePath = filePath;
        g_free (filePath);
    }
    
    gtk_widget_destroy (openSaveDialog);
    return NO_ERROR;
}
int Rename(ExtensionString oldName, ExtensionString newName)
{
    const char *newNameStr = newName.c_str();

    if (g_file_test(newNameStr, G_FILE_TEST_EXISTS)) {
        return ERR_FILE_EXISTS;
    }

    if (rename(oldName.c_str(), newNameStr) == -1) {
        return ConvertLinuxErrorCode(errno);
    }
}
int32 DeleteFileOrDirectory(ExtensionString filename)
{
    DWORD dwAttr = GetFileAttributes(filename.c_str());

    if (dwAttr == INVALID_FILE_ATTRIBUTES)
        return ERR_NOT_FOUND;

    if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0)
        return ERR_NOT_FILE;

    if (!DeleteFile(filename.c_str()))
        return ConvertWinErrorCode(GetLastError());

    return NO_ERROR;
}
int32 OpenURLInDefaultBrowser(ExtensionString url)
{
    GError* error = NULL;
    gtk_show_uri(NULL, url.c_str(), GDK_CURRENT_TIME, &error);
    g_error_free(error);
    return NO_ERROR;
}
Example #7
0
int ReadFile(ExtensionString filename, ExtensionString encoding, std::string& contents)
{
    if (encoding != "utf8") {
        return ERR_UNSUPPORTED_ENCODING;
    }

    int error = NO_ERROR;
    GError *gerror = NULL;
    gchar *file_get_contents = NULL;
    gsize len = 0;
    
    if (!g_file_get_contents(filename.c_str(), &file_get_contents, &len, &gerror)) {
        error = GErrorToErrorCode(gerror);
        if (error == ERR_NOT_FILE) {
            error = ERR_CANT_READ;
        }
    } else {
        if (has_utf16_32_BOM(file_get_contents, len)) {
            error = ERR_UNSUPPORTED_ENCODING;
        } else  if (has_utf8_BOM(file_get_contents, len)) {
            contents.assign(file_get_contents + utf8_BOM_Len, len);        
        } else if (!g_locale_to_utf8(file_get_contents, -1, NULL, NULL, &gerror)) {
            error = ERR_UNSUPPORTED_ENCODING;
        } else {
            contents.assign(file_get_contents, len);
        }
        g_free(file_get_contents);
    }

    return error;
}
int32 WriteFile(ExtensionString filename, std::string contents, ExtensionString encoding)
{
    const char *filenameStr = filename.c_str();    
    int error = NO_ERROR;
    GError *gerror = NULL;

    if (encoding != "utf8") {
        return ERR_UNSUPPORTED_ENCODING;
    } else if (g_file_test(filenameStr, G_FILE_TEST_EXISTS) && g_access(filenameStr, W_OK) == -1) {
        return ERR_CANT_WRITE;
    }
    
    FILE* file = fopen(filenameStr, "w");
    if (file) {
        size_t size = fwrite(contents.c_str(), sizeof(gchar), contents.length(), file);
        if (size != contents.length()) {
            error = ERR_CANT_WRITE;
        }

        fclose(file);
    } else {
        return ConvertLinuxErrorCode(errno);
    }

    return error;
}
int32 CopyFile(ExtensionString src, ExtensionString dest)
{
    int error = NO_ERROR;
    GFile *source = g_file_new_for_path(src.c_str());
    GFile *destination = g_file_new_for_path(dest.c_str());
    GError *gerror = NULL;

    if (!g_file_copy(source, destination, (GFileCopyFlags)(G_FILE_COPY_OVERWRITE|G_FILE_COPY_NOFOLLOW_SYMLINKS|G_FILE_COPY_TARGET_DEFAULT_PERMS), NULL, NULL, NULL, &gerror)) {
        error = ConvertGnomeErrorCode(gerror);
        g_error_free(gerror);
    }
    g_object_unref(source);
    g_object_unref(destination);

    return error;    
}
int SetPosixPermissions(ExtensionString filename, int32 mode)
{
    if (chmod(filename.c_str(),mode) == -1) {
        return ConvertLinuxErrorCode(errno);
    }

    return NO_ERROR;
}
int DeleteFileOrDirectory(ExtensionString filename)
{
    GFile *file = g_file_new_for_path(filename.c_str());
    int error = _doDeleteFileOrDirectory(file);
    g_object_unref(file);

    return error;
}
int32 GetFileModificationTime(ExtensionString filename, uint32& modtime, bool& isDir)
{
    DWORD dwAttr = GetFileAttributes(filename.c_str());

    if (dwAttr == INVALID_FILE_ATTRIBUTES) {
        return ConvertWinErrorCode(GetLastError()); 
    }

    isDir = ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0);

    WIN32_FILE_ATTRIBUTE_DATA   fad;
    if (!GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &fad)) {
        return ConvertWinErrorCode(GetLastError());
    }

    modtime = FiletimeToTime(fad.ftLastWriteTime);

    return NO_ERROR;
}
int32 SetPosixPermissions(ExtensionString filename, int32 mode)
{
    DWORD dwAttr = GetFileAttributes(filename.c_str());

    if (dwAttr == INVALID_FILE_ATTRIBUTES)
        return ERR_NOT_FOUND;

    if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0)
        return NO_ERROR;

    bool write = (mode & 0200) != 0; 
    bool read = (mode & 0400) != 0;
    int mask = (write ? _S_IWRITE : 0) | (read ? _S_IREAD : 0);

    if (_wchmod(filename.c_str(), mask) == -1) {
        return ConvertErrnoCode(errno); 
    }

    return NO_ERROR;
}
int32 OpenURLInDefaultBrowser(ExtensionString url)
{
    DWORD result = (DWORD)ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);

    // If the result > 32, the function suceeded. If the result is <= 32, it is an
    // error code.
    if (result <= 32)
        return ConvertWinErrorCode(result);

    return NO_ERROR;
}
int32 AddMenuItem(CefRefPtr<CefBrowser> browser, ExtensionString parentCommand, ExtensionString itemTitle,
                  ExtensionString command, ExtensionString key, ExtensionString displayStr,
                  ExtensionString position, ExtensionString relativeId)
{
    GtkWidget* entry = gtk_menu_item_new_with_label(itemTitle.c_str());
    g_signal_connect(entry, "activate", FakeCallback, NULL);
    // FIXME add lookup for menu widgets
    gtk_menu_shell_append(GTK_MENU_SHELL(_menuWidget), entry);
    gtk_widget_show(entry);

    return NO_ERROR;
}
int32 ReadFile(ExtensionString filename, ExtensionString encoding, std::string& contents)
{
    if (encoding != L"utf8")
        return ERR_UNSUPPORTED_ENCODING;

    DWORD dwAttr;
    dwAttr = GetFileAttributes(filename.c_str());
    if (INVALID_FILE_ATTRIBUTES == dwAttr)
        return ConvertWinErrorCode(GetLastError());

    if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
        return ERR_CANT_READ;

    HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ,
        0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    int32 error = NO_ERROR;

    if (INVALID_HANDLE_VALUE == hFile)
        return ConvertWinErrorCode(GetLastError()); 

    DWORD dwFileSize = GetFileSize(hFile, NULL);
    DWORD dwBytesRead;
    char* buffer = (char*)malloc(dwFileSize);
    if (buffer && ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL)) {
        contents = std::string(buffer, dwFileSize);
    }
    else {
        if (!buffer)
            error = ERR_UNKNOWN;
        else
            error = ConvertWinErrorCode(GetLastError());
    }
    CloseHandle(hFile);
    if (buffer)
        free(buffer);

    return error; 
}
void MoveFileOrDirectoryToTrash(ExtensionString filename, CefRefPtr<CefBrowser> browser, CefRefPtr<CefProcessMessage> response)
{
    int error = NO_ERROR;
    GFile *file = g_file_new_for_path(filename.c_str());
    GError *gerror = NULL;
    if (!g_file_trash(file, NULL, &gerror)) {
        error = ConvertGnomeErrorCode(gerror);
        g_error_free(gerror);
    }
    g_object_unref(file);
    
    response->GetArgumentList()->SetInt(1, error);
    browser->SendProcessMessage(PID_RENDERER, response);
}
int32 OpenLiveBrowser(ExtensionString argURL, bool enableRemoteDebugging)
{
    const char *remoteDebuggingFormat = "--no-first-run --no-default-browser-check --allow-file-access-from-files --temp-profile --user-data-dir=%s --remote-debugging-port=9222";
    gchar *remoteDebugging;
    gchar *cmdline;
    int error = ERR_BROWSER_NOT_INSTALLED;
    GError *gerror = NULL;
    
    if (enableRemoteDebugging) {
        CefString appSupportDirectory = ClientApp::AppGetSupportDirectory();

        // TODO: (INGO) to better understand to string conversion issue, I need a consultant
        // here. Getting the char* from CefString I had to call ToString().c_str()
        // Calling only c_str() didn't return anything.
        gchar *userDataDir = g_strdup_printf("%s/live-dev-profile",
                                        appSupportDirectory.ToString().c_str());  
        g_message("USERDATADIR= %s", userDataDir);
        remoteDebugging = g_strdup_printf(remoteDebuggingFormat, userDataDir);
        
        g_free(userDataDir);
    } else {
        remoteDebugging = g_strdup("");
    }

    // check for supported browsers (in PATH directories)
    for (size_t i = 0; i < sizeof(browsers) / sizeof(browsers[0]); i++) {
        cmdline = g_strdup_printf("%s %s %s", browsers[i].c_str(), argURL.c_str(), remoteDebugging);

        if (g_spawn_command_line_async(cmdline, &gerror)) {
            // browser is found in os; stop iterating
            error = NO_ERROR;
        } else {
            error = ConvertGnomeErrorCode(gerror);
        }

        g_free(cmdline);
        
        if (error == NO_ERROR) {
            break;
        } else {
            g_error_free(gerror);
            gerror = NULL;
        }
    }
    
    g_free(remoteDebugging);

    return error;
}
int ShowFolderInOSWindow(ExtensionString pathname)
{
    int error = NO_ERROR;
    GError *gerror = NULL;
    gchar *uri = g_strdup_printf("file://%s", pathname.c_str());
    
    if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &gerror)) {
        error = ConvertGnomeErrorCode(gerror);
        g_warning("%s", gerror->message);
        g_error_free(gerror);
    }
    
    g_free(uri);

    return error;
}
int GetFileInfo(ExtensionString filename, uint32& modtime, bool& isDir, double& size, ExtensionString& realPath)
{
    struct stat buf;
    if(stat(filename.c_str(),&buf)==-1)
        return ConvertLinuxErrorCode(errno);

    modtime = buf.st_mtime;
    isDir = S_ISDIR(buf.st_mode);
    size = (double)buf.st_size;
    
    // TODO: Implement realPath. If "filename" is a symlink, realPath should be the actual path
    // to the linked object.
    realPath = "";
    
    return NO_ERROR;
}
int32 ReadDir(ExtensionString path, CefRefPtr<CefListValue>& directoryContents)
{
    if (path.length() && path[path.length() - 1] != '/')
        path += '/';

    path += '*';

    WIN32_FIND_DATA ffd;
    HANDLE hFind = FindFirstFile(path.c_str(), &ffd);

    std::vector<ExtensionString> resultFiles;
    std::vector<ExtensionString> resultDirs;

    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            // Ignore '.' and '..'
            if (!wcscmp(ffd.cFileName, L".") || !wcscmp(ffd.cFileName, L".."))
                continue;

            // Collect file and directory names separately
            if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                resultDirs.push_back(ExtensionString(ffd.cFileName));
            } else {
                resultFiles.push_back(ExtensionString(ffd.cFileName));
            }
        }
        while (FindNextFile(hFind, &ffd) != 0);

        FindClose(hFind);
    } 
    else {
        return ConvertWinErrorCode(GetLastError());
    }

    // On Windows, list directories first, then files
    size_t i, total = 0;
    for (i = 0; i < resultDirs.size(); i++)
        directoryContents->SetString(total++, resultDirs[i]);
    for (i = 0; i < resultFiles.size(); i++)
        directoryContents->SetString(total++, resultFiles[i]);

    return NO_ERROR;
}
int32 WriteFile(ExtensionString filename, std::string contents, ExtensionString encoding)
{
    if (encoding != L"utf8")
        return ERR_UNSUPPORTED_ENCODING;

    HANDLE hFile = CreateFile(filename.c_str(), GENERIC_WRITE,
        0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD dwBytesWritten;
    int error = NO_ERROR;

    if (INVALID_HANDLE_VALUE == hFile)
        return ConvertWinErrorCode(GetLastError(), false); 

    // TODO (issue 67) -  Should write to temp file and handle encoding
    if (!WriteFile(hFile, contents.c_str(), contents.length(), &dwBytesWritten, NULL)) {
        error = ConvertWinErrorCode(GetLastError(), false);
    }

    CloseHandle(hFile);
    return error;
}
int32 MakeDir(ExtensionString path, int mode)
{
    const char *pathStr = path.c_str();
    GFile *file;
    GError *gerror = NULL;
    int32 error = NO_ERROR;

    if (g_file_test(pathStr, G_FILE_TEST_EXISTS)) {
        return ERR_FILE_EXISTS;
    }

    file = g_file_new_for_path(pathStr);
    mode = mode | 0777;

    if (!g_file_make_directory(file, NULL, &gerror)) {
        error = GErrorToErrorCode(gerror);
    }
    g_object_unref(file);

    return error;
}
int32 AddMenu(CefRefPtr<CefBrowser> browser, ExtensionString title, ExtensionString command,
              ExtensionString position, ExtensionString relativeId)
{
    // if (tag == kTagNotFound) {
    //     tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, ExtensionString());
    // } else {
    //     // menu already there
    //     return NO_ERROR;
    // }

    GtkWidget* menuBar = GetMenuBar(browser);
    GtkWidget* menuWidget = gtk_menu_new();
    GtkWidget* menuHeader = gtk_menu_item_new_with_label(title.c_str());
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuHeader), menuWidget);
    gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuHeader);
    gtk_widget_show(menuHeader);

    // FIXME add lookup for menu widgets
    _menuWidget = menuWidget;
    
    return NO_ERROR;
}
int32 ShowFolderInOSWindow(ExtensionString pathname) {
    ShellExecute(NULL, L"open", pathname.c_str(), NULL, NULL, SW_SHOWDEFAULT);
    return NO_ERROR;
}
int32 ShowOpenDialog(bool allowMultipleSelection,
                     bool chooseDirectory,
                     ExtensionString title,
                     ExtensionString initialDirectory,
                     ExtensionString fileTypes,
                     CefRefPtr<CefListValue>& selectedFiles)
{
    wchar_t szFile[MAX_PATH];
    szFile[0] = 0;

    // TODO (issue #64) - This method should be using IFileDialog instead of the
    /* outdated SHGetPathFromIDList and GetOpenFileName.
       
    Useful function to parse fileTypesStr:
    template<class T>
    int inline findAndReplaceString(T& source, const T& find, const T& replace)
    {
    int num=0;
    int fLen = find.size();
    int rLen = replace.size();
    for (int pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
    {
    num++;
    source.replace(pos, fLen, replace);
    }
    return num;
    }
    */

    // SHBrowseForFolder can handle Windows path only, not Unix path.
    // ofn.lpstrInitialDir also needs Windows path on XP and not Unix path.
    ConvertToNativePath(initialDirectory);

    if (chooseDirectory) {
        BROWSEINFO bi = {0};
        bi.hwndOwner = GetActiveWindow();
        bi.lpszTitle = title.c_str();
        bi.ulFlags = BIF_NEWDIALOGSTYLE;
        bi.lpfn = SetInitialPathCallback;
        bi.lParam = (LPARAM)initialDirectory.c_str();

        LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
        if (pidl != 0) {
            if (SHGetPathFromIDList(pidl, szFile)) {
                // Add directory path to the result
                ExtensionString pathName(szFile);
                ConvertToUnixPath(pathName);
                selectedFiles->SetString(0, pathName);
            }
            IMalloc* pMalloc = NULL;
            SHGetMalloc(&pMalloc);
            if (pMalloc) {
                pMalloc->Free(pidl);
                pMalloc->Release();
            }
        }
    } else {
        OPENFILENAME ofn;

        ZeroMemory(&ofn, sizeof(ofn));
        ofn.hwndOwner = GetActiveWindow();
        ofn.lStructSize = sizeof(ofn);
        ofn.lpstrFile = szFile;
        ofn.nMaxFile = MAX_PATH;

        // TODO (issue #65) - Use passed in file types. Note, when fileTypesStr is null, all files should be shown
        /* findAndReplaceString( fileTypesStr, std::string(" "), std::string(";*."));
        LPCWSTR allFilesFilter = L"All Files\0*.*\0\0";*/

        ofn.lpstrFilter = L"All Files\0*.*\0Web Files\0*.js;*.css;*.htm;*.html\0\0";
           
        ofn.lpstrInitialDir = initialDirectory.c_str();
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER;
        if (allowMultipleSelection)
            ofn.Flags |= OFN_ALLOWMULTISELECT;

        if (GetOpenFileName(&ofn)) {
            if (allowMultipleSelection) {
                // Multiple selection encodes the files differently

                // If multiple files are selected, the first null terminator
                // signals end of directory that the files are all in
                std::wstring dir(szFile);

                // Check for two null terminators, which signal that only one file
                // was selected
                if (szFile[dir.length() + 1] == '\0') {
                    ExtensionString filePath(dir);
                    ConvertToUnixPath(filePath);
                    selectedFiles->SetString(0, filePath);
                } else {
                    // Multiple files are selected
                    wchar_t fullPath[MAX_PATH];
                    for (int i = (dir.length() + 1), fileIndex = 0; ; fileIndex++) {
                        // Get the next file name
                        std::wstring file(&szFile[i]);

                        // Two adjacent null characters signal the end of the files
                        if (file.length() == 0)
                            break;

                        // The filename is relative to the directory that was specified as
                        // the first string
                        if (PathCombine(fullPath, dir.c_str(), file.c_str()) != NULL) {
                            ExtensionString filePath(fullPath);
                            ConvertToUnixPath(filePath);
                            selectedFiles->SetString(fileIndex, filePath);
                        }

                        // Go to the start of the next file name
                        i += file.length() + 1;
                    }
                }

            } else {
                // If multiple files are not allowed, add the single file
                selectedFiles->SetString(0, szFile);
            }
        }
    }

    return NO_ERROR;
}
int32 ReadDir(ExtensionString path, CefRefPtr<CefListValue>& directoryContents)
{
    //# Add trailing /slash if neccessary
    if (path.length() && path[path.length() - 1] != '/')
        path += '/';

    DIR *dp;
    struct dirent *files;
    struct stat statbuf;
    ExtensionString curFile;
    
    /*struct dirent
    {
        unsigned char  d_type; #not supported on all systems, faster than stat
        char d_name[]
    }*/
    

    if((dp=opendir(path.c_str()))==NULL)
        return ConvertLinuxErrorCode(errno,true);

    std::vector<ExtensionString> resultFiles;
    std::vector<ExtensionString> resultDirs;

    while((files=readdir(dp))!=NULL)
    {
        if(!strcmp(files->d_name,".") || !strcmp(files->d_name,".."))
            continue;
        
        if(files->d_type==DT_DIR)
            resultDirs.push_back(ExtensionString(files->d_name));
        else if(files->d_type==DT_REG)
            resultFiles.push_back(ExtensionString(files->d_name));
        else
        {
            // Some file systems do not support d_type we use
            // for faster type detection. So on these file systems
            // we may get DT_UNKNOWN for all file entries, but just  
            // to be safe we will use slower stat call for all 
            // file entries that are not DT_DIR or DT_REG.
            curFile = path + files->d_name;
            if(stat(curFile.c_str(), &statbuf) == -1)
                continue;
        
            if(S_ISDIR(statbuf.st_mode))
                resultDirs.push_back(ExtensionString(files->d_name));
            else if(S_ISREG(statbuf.st_mode))
                resultFiles.push_back(ExtensionString(files->d_name));
        }
    }

    closedir(dp);

    //# List dirs first, files next
    size_t i, total = 0;
    for (i = 0; i < resultDirs.size(); i++)
        directoryContents->SetString(total++, resultDirs[i]);
    for (i = 0; i < resultFiles.size(); i++)
        directoryContents->SetString(total++, resultFiles[i]);

    return NO_ERROR;
}