text:
//
//  RKManagedObjectMappingOperation.m
//  RestKit
//
//  Created by Blake Watters on 5/31/11.
//  Copyright 2011 Two Toasters. All rights reserved.
//

#import "RKManagedObjectMappingOperation.h"
#import "RKManagedObjectMapping.h"
#import "NSManagedObject+ActiveRecord.h"
#import "../Support/RKLog.h"

/**
 Progressively enhance the RKObjectMappingOperation base class to inject Core Data
 specifics without leaking into the object mapper abstractions
 */
@implementation RKObjectMappingOperation (CoreData)

/*
 Trampoline the initialization through RKManagedObjectMapping so the mapper uses RKManagedObjectMappingOperation
 at the right moments
 */
+ (RKObjectMappingOperation*)mappingOperationFromObject:(id)sourceObject toObject:(id)destinationObject withMapping:(RKObjectMapping*)objectMapping {
    if ([objectMapping isKindOfClass:[RKManagedObjectMapping class]]) {
        return [[[RKManagedObjectMappingOperation alloc] initWithSourceObject:sourceObject destinationObject:destinationObject mapping:objectMapping] autorelease];
    }

    return [[[RKObjectMappingOperation alloc] initWithSourceObject:sourceObject destinationObject:destinationObject mapping:objectMapping] autorelease];
}

@end

@implementation RKManagedObjectMappingOperation

// TODO: Move this to a better home to take exposure out of the mapper
- (Class)operationClassForMapping:(RKObjectMapping*)mapping {
    Class managedMappingClass = NSClassFromString(@"RKManagedObjectMapping");
    Class managedMappingOperationClass = NSClassFromString(@"RKManagedObjectMappingOperation");
    if (managedMappingClass != nil && [mapping isMemberOfClass:managedMappingClass]) {
        return managedMappingOperationClass;
    }

    return [RKObjectMappingOperation class];
}

- (void)connectRelationships {
    if ([self.objectMapping isKindOfClass:[RKManagedObjectMapping class]]) {
        NSDictionary* relationshipsAndPrimaryKeyAttributes = [(RKManagedObjectMapping*)self.objectMapping relationshipsAndPrimaryKeyAttributes];
        for (NSString* relationshipName in relationshipsAndPrimaryKeyAttributes) {
            NSString* primaryKeyAttribute = [relationshipsAndPrimaryKeyAttributes objectForKey:relationshipName];
            RKObjectRelationshipMapping* relationshipMapping = [self.objectMapping mappingForKeyPath:relationshipName];
            id<RKObjectMappingDefinition> mapping = relationshipMapping.mapping;
            if (! [mapping isKindOfClass:[RKObjectMapping class]]) {
                RKLogWarning(@"Can only connect relationships for RKObjectMapping relationships. Found %@: Skipping...", NSStringFromClass([mapping class]));
                continue;
            }
            RKObjectMapping* objectMapping = (RKObjectMapping*)mapping;
            NSAssert(relationshipMapping, @"Unable to find relationship mapping '%@' to connect by primaryKey", relationshipName);
            NSAssert([relationshipMapping isKindOfClass:[RKObjectRelationshipMapping class]], @"Expected mapping for %@ to be a relationship mapping", relationshipName);
            NSAssert([relationshipMapping.mapping isKindOfClass:[RKManagedObjectMapping class]], @"Can only connect RKManagedObjectMapping relationships");
            NSString* primaryKeyAttributeOfRelatedObject = [(RKManagedObjectMapping*)objectMapping primaryKeyAttribute];
            NSAssert(primaryKeyAttributeOfRelatedObject, @"Cannot connect relationship: mapping for %@ has no primary key attribute specified", NSStringFromClass(objectMapping.objectClass));
            id valueOfLocalPrimaryKeyAttribute = [self.destinationObject valueForKey:primaryKeyAttribute];
            if (valueOfLocalPrimaryKeyAttribute) {
                id relatedObject = [objectMapping.objectClass findFirstByAttribute:primaryKeyAttributeOfRelatedObject withValue:valueOfLocalPrimaryKeyAttribute];
                [self.destinationObject setValue:relatedObject forKey:relationshipName];
                // TODO: Logging
            }
        }
    }
}

- (BOOL)performMapping:(NSError**)error {
    BOOL success = [super performMapping:error];
    [self connectRelationships];
    return success;
}

@end


text:
/**
 * @author  Thomas Baumann <teebaum@ymail.com>
 *
 * @section LICENSE
 * See LICENSE for more informations.
 *
 */

#ifndef VIEWAPPLICATION_H
#define VIEWAPPLICATION_H

#include <include/ApplicationInterface.h>

#include <QPointer>

class HighlightingDialog;

/*!
 * \brief The ViewApplication class
 * Is the implementation for the ApplicationInterface that is used by the views to communicate
 * with the application.
 */
class ViewApplication : public ApplicationInterface
{
public:
   ViewApplication();

   // ApplicationInterface interface
public:
   void addWordHighlightingRule(const HighlightingRule &rule) override;
   void addLineHighlightingRule(const HighlightingRule &rule) override;

   QPointer<HighlightingDialog> highlightingDialog() const;
   void setHighlightingDialog(const QPointer<HighlightingDialog> &highlightingDialog);

private:
   QPointer<HighlightingDialog> m_highlightingDialog;
};

#endif // VIEWAPPLICATION_H

redpajama_set_name: RedPajamaGithub


text:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

$lang['modules.core_list']				= 'Módulos del Núcleo';
$lang['modules.addon_list']				= 'Módulos Agregados';
$lang['modules.introduction']			= 'Debajo hay una lista de los módulos instalados y su información, como la descripción y la versión del mismo.';
$lang['modules.core_introduction']		 = 'Below is a list of core modules and their information. You may disable them but do so with extreme care. Disabling modules such as Users will render your site inoperable.'; #translate
$lang['modules.disable_error'] 			= 'No se pudo desactivar el módulo "%s".';
$lang['modules.disable_success']		= 'El módulo "%s" ha sido desactivado.';
$lang['modules.enable_error']			= 'No se pudo activar el módulo "%s".';
$lang['modules.enable_success']			= 'El módulo "%s" ha sido activado.';
$lang['modules.install_error']			= 'No se pudo instalar el módulo.';
$lang['modules.install_success']		= 'El módulo ha sido instalado.';
$lang['modules.delete_success']			 = 'The module "%s" has been deleted.'; #translate
$lang['modules.delete_error']			 = 'Could not delete the module "%s".'; #translate
$lang['modules.uninstall_error']		= 'No se pudo desinstalar el módulo "%s".';
$lang['modules.uninstall_success']		= 'El módulo "%s" ha sido desinstalado.';
$lang['modules.upgrade_error']			= 'No se pudo actualizar el módulo "%s".';
$lang['modules.upgrade_success']		= 'El módulo "%s" se actualizó satisfactoriamente.';
$lang['modules.already_exists_error']	= 'Ya existe un módulo con el nombre "%s".';
$lang['modules.módulo_not_specified']	= 'Debes especificar un módulo.';
$lang['modules.details_error']			= 'Hay un error en el archivo details.php del módulo %s. Corrije el error y luego reinstala el módulo.';

$lang['modules.manually_remove']		= 'Debes eliminar manualmente "%s" para eliminar el módulo por completo.';
$lang['modules.upload_title']			= 'Subir Módulo';
$lang['modules.upload_desc']			= 'Por favor, elije un archivo y haz click en el botón "Subir"';

$lang['modules.confirm_enable']         = 'Estás seguro que quieres activar este módulo?';
$lang['modules.confirm_disable']        = 'Estás seguro que quieres desactivar este módulo?';
$lang['modules.confirm_install']        = 'Estás seguro que quieres instalar este módulo?';
$lang['modules.confirm_uninstall']		 = 'All database records will be removed! Are you sure you want to uninstall this module?'; #tranlate
$lang['modules.confirm_delete']      = 'Estás seguro que quieres desinstalar este módulo?';
$lang['modules.confirm_upgrade']		= 'Estás seguro que quieres actualizar este módulo?';

/* End of file modules_lang.php */


text:
using System;
using System.Collections.Generic;
using System.Compiler;
using System.IO;
using System.Diagnostics;

namespace Microsoft.Contracts.Foxtrot
{
    public class AssemblyResolver
    {
        public string[] EmptyExt = new[] {""};
        public string[] DllExt = new[] {".dll", ".winmd"};
        public string[] DllAndExeExt = new[] {".dll", ".winmd", ".exe"};
        public string[] EmptyAndDllExt = new[] {"", ".dll", ".winmd"};
        public string[] AllExt = new[] {"", ".dll", ".winmd", ".exe"};

        private IEnumerable<string> resolvedPaths;
        private IEnumerable<string> libpaths;

        private bool trace;
        private bool usePDB;
        private bool preserveShortBranches;
        private Action<AssemblyResolver, AssemblyNode> postLoad;

        public AssemblyResolver(IEnumerable<string> resolvedPaths, IEnumerable<string> libpaths, bool usePDB,
            bool preserveShortBranches, bool trace, Action<AssemblyResolver, AssemblyNode> postLoad)
        {
            this.resolvedPaths = resolvedPaths;
            this.libpaths = libpaths;
            this.trace = trace;
            this.usePDB = usePDB;
            this.preserveShortBranches = preserveShortBranches;
            this.postLoad = postLoad;
        }

        /// <summary>
        /// Resolves assembly references based on the library paths specified.
        /// Tries to resolve to ".dll" or ".exe". First found wins.
        /// </summary>
        /// <param name="assemblyReference">Reference to resolve.</param>
        /// <param name="referencingModule">Referencing module.</param>
        /// <returns>The resolved assembly node (null if not found).</returns>
        public AssemblyNode ResolveAssemblyReference(AssemblyReference assemblyReference, Module referencingModule)
        {
            AssemblyNode a = ProbeForAssembly(assemblyReference.Name, referencingModule.Directory, DllAndExeExt);

            return a;
        }

        public AssemblyNode ProbeForAssembly(string assemblyName, string referencingModuleDirectory, string[] exts)
        {
            AssemblyNode a = null;
            try
            {
                if (trace)
                {
                    LoadTracing(string.Format("Attempting to load: {0}", assemblyName));
                }

                // Location Priority (in decreasing order):
                // 0. list of candidate full paths specified by client
                // 1. list of directories specified by client
                // 2. referencing Module's directory
                // 3. directory original assembly was in
                //
                // Extension Priority (in decreasing order):
                // dll, exe, (any others?)

                // Check user-supplied candidate paths

                LoadTracing("AssemblyResolver: Attempting user-supplied candidates.");
                if (this.resolvedPaths != null)
                {
                    foreach (string candidate in this.resolvedPaths)
                    {
                        var candidateAssemblyName = Path.GetFileNameWithoutExtension(candidate);
                        if (String.Compare(candidateAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) != 0)
                            continue;

                        if (File.Exists(candidate))
                        {
                            a = ProbeForAssemblyWithExtension("", candidate, EmptyExt);
                            break;
                        }
                    }
                }

                if (a == null)
                {
                    if (this.resolvedPaths != null)
                    {
                    }
                }
                else
                {
                    goto End;
                }

                // Check user-supplied search directories

                LoadTracing("AssemblyResolver: Attempting user-supplied directories.");
                if (this.libpaths != null)
                {
                    foreach (string dir in this.libpaths)
                    {
                        a = ProbeForAssemblyWithExtension(dir, assemblyName, exts);
                        if (a != null)
                            break;
                    }
                }

                if (a == null)
                {
                    if (this.libpaths != null)
                    {
                    }
                }
                else
                {
                    goto End;
                }

                // Check referencing module's directory

                if (referencingModuleDirectory != null)
                {
                    a = ProbeForAssemblyWithExtension(referencingModuleDirectory, assemblyName, exts);
                }

                if (a == null)
                {
                    if (referencingModuleDirectory != null)
                    {
                    }
                }
                else
                {
                    goto End;
                }

                // Check input directory

                a = ProbeForAssemblyWithExtension("", assemblyName, exts);
                if (a == null)
                {
                }
                else
                {
                    goto End;
                }

            End:
                if (a == null)
                {
                }
            }
            catch (Exception e)
            {
                Trace.WriteLine("AssemblyResolver: Exception occurred. Unable to resolve reference.");
                Trace.WriteLine("Inner exception: " + e);
            }

            return a;
        }

        private AssemblyNode ProbeForAssemblyWithExtension(string directory, string assemblyName, string[] exts)
        {
            do
            {
                var result = ProbeForAssemblyWithExtensionAtomic(directory, assemblyName, exts);
                if (result != null) return result;

                if (directory.EndsWith("CodeContracts")) return null;

                // if directory is a profile directory, we need to look in parent directory too
                if (directory.Contains("Profile") || directory.Contains("profile"))
                {
                    try
                    {
                        var parent = Directory.GetParent(directory);
                        directory = parent.FullName;
                    }
                    catch
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            } while (!string.IsNullOrWhiteSpace(directory));

            return null;
        }

        private AssemblyNode ProbeForAssemblyWithExtensionAtomic(string directory, string assemblyName, string[] exts)
        {
            foreach (string ext in exts)
            {
                bool tempDebugInfo = this.usePDB;
                string fullName = Path.Combine(directory, assemblyName + ext);

                if (this.trace)
                {
                    LoadTracing(String.Format("Attempting load from {0}", fullName));
                }

                if (File.Exists(fullName))
                {
                    if (tempDebugInfo)
                    {
                        // Don't pass the debugInfo flag to GetAssembly unless the PDB file exists.
                        string pdbFullName;
                        if (String.IsNullOrEmpty(ext))
                        {
                            pdbFullName = Path.Combine(directory, Path.GetFileNameWithoutExtension(assemblyName) + ".pdb");
                        }
                        else
                        {
                            pdbFullName = Path.Combine(directory, assemblyName + ".pdb");
                        }

                        if (!File.Exists(pdbFullName))
                        {
                            tempDebugInfo = false;
                        }
                    }

                    if (this.trace)
                    {
                        LoadTracing(string.Format("Resolved assembly reference '{0}' to '{1}'. (Using directory {2})",
                            assemblyName, fullName, directory));
                    }

                    var result = AssemblyNode.GetAssembly(
                        fullName, // path to assembly
                        TargetPlatform.StaticAssemblyCache, // global cache to use for assemblies
                        true, // doNotLockFile
                        tempDebugInfo, // getDebugInfo
                        true, // useGlobalCache
                        this.preserveShortBranches, // preserveShortBranches
                        this.PostLoadHook
                        );

                    return result;
                }
            }

            return null;
        }

        public void PostLoadHook(AssemblyNode assemblyNode)
        {
            assemblyNode.AssemblyReferenceResolution += this.ResolveAssemblyReference;

            if (!SystemTypes.IsInitialized) return;

            if (this.postLoad != null) this.postLoad(this, assemblyNode);
        }

        private void LoadTracing(string msg)
        {
            if (this.trace)
            {
                Console.WriteLine("Trace: {0}", msg);
            }
        }

        public static string GetTargetPlatform(string platformOption, IEnumerable<string> resolvedPaths, IEnumerable<string> libPaths)
        {
            var stdlib = platformOption;
            if (stdlib == null)
            {
                stdlib = FindMscorlibCandidate(resolvedPaths);
            }

            if (stdlib == null)
            {
                stdlib = FindMscorlib(libPaths);
            }

            return stdlib;
        }

        private static string FindMscorlib(IEnumerable<string> p)
        {
            foreach (var path in p)
            {
                if (string.IsNullOrEmpty(path)) continue;

                var corlib = Path.Combine(path, "mscorlib.dll");

                if (File.Exists(corlib))
                {
                    return corlib;
                }
            }

            return null;
        }

        private static string FindMscorlibCandidate(IEnumerable<string> p)
        {
            foreach (var path in p)
            {
                try
                {
                    if (string.IsNullOrEmpty(path.Trim())) continue;

                    var candidate = Path.GetFullPath(path);

                    if (candidate.EndsWith(@"\mscorlib.dll") && File.Exists(candidate))
                    {
                        return candidate;
                    }
                }
                catch
                {
                    // ignore errors from GetFullPath
                }
            }

            return null;
        }
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.csc.og.kafka</groupId>
    <artifactId>kafka-modules</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>kafka-tutorials-dependencies</module>
        <module>schema-registry-client-support</module>
        <module>kafka-vanilla</module>

    </modules>

</project>


text:
/*
 * MTP device list, trying real bad to get all devices into
 * this list by stealing from everyone I know.
 * Some devices taken from the Rockbox device listing:
 * http://www.rockbox.org/twiki/bin/view/Main/DeviceDetection
 */

  /*
   * Creative Technology and ZiiLABS
   * Initially the Creative devices was all we supported so these are
   * the most thoroughly tested devices. Presumably only the devices
   * with older firmware (the ones that have 32bit object size) will
   * need the DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL flag. This bug
   * manifest itself when you have a lot of folders on the device,
   * some of the folders will start to disappear when getting all objects
   * and properties.
   */

  { "Samsung",  0x4e8, "Galaxy S2, S3, Note", 0x6860, DEVICE_FLAG_NONE},
  { "Motorola", 0x22b8, "Xoom", 0x70a9, DEVICE_FLAG_NONE },
  { "Motorola", 0x22b8, "Xoom", 0x70a8 , DEVICE_FLAG_NONE},
  { "Creative", 0x041e, "ZEN Vision", 0x411f, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "Portable Media Center", 0x4123, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Xtra (MTP mode)", 0x4128, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Dell", 0x041e, "DJ (2nd generation)", 0x412f, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Micro (MTP mode)", 0x4130, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Touch (MTP mode)", 0x4131, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Dell", 0x041e, "Dell Pocket DJ (MTP mode)", 0x4132, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Sleek (MTP mode)", 0x4137, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN MicroPhoto", 0x413c, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Sleek Photo", 0x413d, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Vision:M", 0x413e, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by marazm@o2.pl
  { "Creative", 0x041e, "ZEN V", 0x4150, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by danielw@iinet.net.au
  // This version of the Vision:M needs the no release interface flag,
  // unclear whether the other version above need it too or not.
  { "Creative", 0x041e, "ZEN Vision:M (DVP-HD0004)", 0x4151,
      DEVICE_FLAG_NO_RELEASE_INTERFACE |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL},
  // Reported by Darel on the XNJB forums
  { "Creative", 0x041e, "ZEN V Plus", 0x4152,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  { "Creative", 0x041e, "ZEN Vision W", 0x4153,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Don't add 0x4155: this is a Zen Stone device which is not MTP
  // Reported by Paul Kurczaba <paul@kurczaba.com>
  { "Creative", 0x041e, "ZEN", 0x4157, DEVICE_FLAG_IGNORE_HEADER_ERRORS |
    DEVICE_FLAG_BROKEN_SET_SAMPLE_DIMENSIONS |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by Ringofan <mcroman@users.sourceforge.net>
  { "Creative", 0x041e, "ZEN V 2GB", 0x4158,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by j norment <stormzen@gmail.com>
  { "Creative", 0x041e, "ZEN Mozaic", 0x4161,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by Aaron F. Gonzalez <sub_tex@users.sourceforge.net>
  { "Creative", 0x041e, "ZEN X-Fi", 0x4162,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by Todor Gyumyushev <yodor1@users.sourceforge.net>
  { "ZiiLABS", 0x041e, "Zii EGG", 0x6000,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },

  /*
   * Samsung
   * We suspect that more of these are dual mode.
   * We suspect more of these might need DEVICE_FLAG_NO_ZERO_READS
   * We suspect more of these might need DEVICE_FLAG_PLAYLIST_SPL_V1
   *  or DEVICE_FLAG_PLAYLIST_SPL_V2 to get playlists working.
   * YP-NEU, YP-NDU, YP-20, YP-800, YP-MF Series, YP-100, YP-30
   * YP-700 and YP-90 are NOT MTP, but use a Samsung custom protocol.
   */
  // From anonymous SourceForge user, not verified
  { "Samsung", 0x04e8, "YP-900", 0x0409, DEVICE_FLAG_NONE },
  // From MItch <dbaker@users.sourceforge.net>
  { "Samsung", 0x04e8, "I550W Phone", 0x04a4, DEVICE_FLAG_NONE },
  // From Gabriel Nunes <gabrielkm1@yahoo.com.br>
  { "Samsung", 0x04e8, "YH-920 (501d)", 0x501d, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Soren O'Neill
  { "Samsung", 0x04e8, "YH-920 (5022)", 0x5022, DEVICE_FLAG_UNLOAD_DRIVER },
  // Contributed by aronvanammers on SourceForge
  { "Samsung", 0x04e8, "YH-925GS", 0x5024, DEVICE_FLAG_NONE },
  // From libgphoto2, according to tests by Stephan Fabel it cannot
  // get all objects with the getobjectproplist command..
  { "Samsung", 0x04e8, "YH-820", 0x502e, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Contributed by polux2001@users.sourceforge.net
  { "Samsung", 0x04e8, "YH-925(-GS)", 0x502f, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Contributed by anonymous person on SourceForge
  { "Samsung", 0x04e8, "YH-J70J", 0x5033, DEVICE_FLAG_UNLOAD_DRIVER },
  // From XNJB user
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-Z5", 0x503c, DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // Don't add 0x5041 as this is YP-Z5 in USB mode
  // Contributed by anonymous person on SourceForge
  { "Samsung", 0x04e8, "YP-T7J", 0x5047, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by cstrickler@gmail.com
  { "Samsung", 0x04e8, "YP-U2J (YP-U2JXB/XAA)", 0x5054, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Andrew Benson
  { "Samsung", 0x04e8, "YP-F2J", 0x5057, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Patrick <skibler@gmail.com>
  // Just guessing but looks like .spl v1 http://www.anythingbutipod.com/forum/showthread.php?t=14160
  { "Samsung", 0x04e8, "YP-K5", 0x505a, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_NO_ZERO_READS | DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From dev.local@gmail.com - 0x4e8/0x507c is the UMS mode, apparently
  // do not add that device.
  // From m.eik michalke
  // This device does NOT use the special SPL playlist according to sypqgjxu@gmx.de.
  { "Samsung", 0x04e8, "YP-U3", 0x507d, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Matthew Wilcox <matthew@wil.cx>
  // Sergio <sfrdll@tiscali.it> reports this device need the BROKEN ALL flag.
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-T9", 0x507f, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL | DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Paul Clinch
  // Just guessing but looks like .spl v1 http://www.anythingbutipod.com/forum/showthread.php?t=14160
  // Some versions of the firmware reportedly support OGG, reportedly only the
  // UMS versions, so MTP+OGG is not possible on this device.
  { "Samsung", 0x04e8, "YP-K3", 0x5081, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From XNJB user
  // From Alistair Boyle, .spl v2 required for playlists
  // According to the device log it properly supports OGG
  { "Samsung", 0x04e8, "YP-P2", 0x5083, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_NO_ZERO_READS | DEVICE_FLAG_PLAYLIST_SPL_V2 },
  // From Paul Clinch
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-T10", 0x508a, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
      DEVICE_FLAG_PLAYLIST_SPL_V1 | DEVICE_FLAG_NO_ZERO_READS },
  // From Wim Verwimp <wimverwimp@gmail.com>
  // Not sure about the Ogg and broken proplist flags here. Just guessing.
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-S5", 0x508b, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
      DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Ludovic Danigo
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-S3", 0x5091, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
      DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Adrian Levi <adrian.levi@gmail.com>
  // Guessing on .spl flag
  // This one supports OGG properly through the correct MTP type.
  { "Samsung", 0x04e8, "YP-U4", 0x5093, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Anonymous SourceForge user, NOT VERIFIED TO BE MTP
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-Q1", 0x5115, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
      DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Anonymous SourceForge user
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-P3", 0x511a, DEVICE_FLAG_UNLOAD_DRIVER |
     DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
     DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Anonymous SourceForge user
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-Q2", 0x511d, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
      DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From Marco Pizzocaro <mpizzocaro@users.sourceforge.net>
  // Guessing on .spl flag
  { "Samsung", 0x04e8, "YP-U5", 0x5121,
     DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From a rouge .INF file,
  // this device ID seems to have been recycled for:
  // the Samsung SGH-A707 Cingular cellphone
  // the Samsung L760-V cellphone
  // the Samsung SGH-U900 cellphone
  { "Samsung", 0x04e8, "YH-999 Portable Media Center/SGH-A707/SGH-L760V/SGH-U900", 0x5a0f, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // From Santi Béjar <sbejar@gmail.com> - not sure this is MTP...
  // { "Samsung", 0x04e8, "Z170 Mobile Phone", 0x6601, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Santi Béjar <sbejar@gmail.com> - not sure this is MTP...
  // { "Samsung", 0x04e8, "E250 Mobile Phone", 0x663e, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Lionel Bouton
  { "Samsung", 0x04e8, "X830 Mobile Phone", 0x6702, DEVICE_FLAG_UNLOAD_DRIVER },
  // From James <jamestech@gmail.com>
  { "Samsung", 0x04e8, "U600 Mobile Phone", 0x6709, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Cesar Cardoso <cesar@cesarcardoso.tk>
  // No confirmation that this is really MTP.
  { "Samsung", 0x04e8, "F250 Mobile Phone", 0x6727, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Charlie Todd  2007-10-31
  { "Samsung", 0x04e8, "Juke (SCH-U470)", 0x6734, DEVICE_FLAG_UNLOAD_DRIVER},
  // Reported by Tenn
  { "Samsung", 0x04e8, "GT-B2700", 0x6752, DEVICE_FLAG_UNLOAD_DRIVER },
  // Added by Greg Fitzgerald <netzdamon@gmail.com>
  { "Samsung", 0x04e8, "SAMSUNG Trance", 0x6763, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_NO_ZERO_READS | DEVICE_FLAG_PLAYLIST_SPL_V1 },
  // From anonymous Sourceforge user
  { "Samsung", 0x04e8, "GT-S5230", 0xe20c, DEVICE_FLAG_NONE },

  /*
   * Intel
   */
  { "Intel", 0x045e, "Bandon Portable Media Center", 0x00c9, DEVICE_FLAG_NONE },
  // Reported by Tadimarri Sarath <sarath.tadi@gmail.com>
  // No idea why this use an Intel PID, perhaps a leftover from
  // the early PMC development days when Intel and Microsoft were
  // partnering.
  { "Microsoft", 0x045e, "Windows MTP Simulator", 0x0622, DEVICE_FLAG_NONE },

  /*
   * JVC
   */
  // From Mark Veinot
  { "JVC", 0x04f1, "Alneo XA-HD500", 0x6105, DEVICE_FLAG_NONE },

  /*
   * Philips
   */
  { "Philips", 0x0471, "HDD6320/00 or HDD6330/17", 0x014b, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Anonymous SourceForge user
  { "Philips", 0x0471, "HDD14XX,HDD1620 or HDD1630/17", 0x014c, DEVICE_FLAG_NONE },
  // from discussion forum
  { "Philips", 0x0471, "HDD085/00 or HDD082/17", 0x014d, DEVICE_FLAG_NONE },
  // from XNJB forum
  { "Philips", 0x0471, "GoGear SA9200", 0x014f, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // From John Coppens <jcoppens@users.sourceforge.net>
  { "Philips", 0x0471, "SA1115/55", 0x0164, DEVICE_FLAG_NONE },
  // From Gerhard Mekenkamp
  { "Philips", 0x0471, "GoGear Audio", 0x0165, DEVICE_FLAG_NONE },
  // from David Holm <wormie@alberg.dk>
  { "Philips", 0x0471, "Shoqbox", 0x0172, DEVICE_FLAG_ONLY_7BIT_FILENAMES },
  // from npedrosa
  { "Philips", 0x0471, "PSA610", 0x0181, DEVICE_FLAG_NONE },
  // From libgphoto2 source
  { "Philips", 0x0471, "HDD6320", 0x01eb, DEVICE_FLAG_NONE },
  // From Detlef Meier <dm@emlix.com>
  { "Philips", 0x0471, "GoGear SA6014/SA6015/SA6024/SA6025/SA6044/SA6045", 0x084e, DEVICE_FLAG_UNLOAD_DRIVER },
  // From anonymous Sourceforge user SA5145/02
  { "Philips", 0x0471, "GoGear SA5145", 0x0857, DEVICE_FLAG_UNLOAD_DRIVER },
  // From a
  { "Philips", 0x0471, "GoGear SA6125/SA6145/SA6185", 0x2002, DEVICE_FLAG_UNLOAD_DRIVER },
  // From anonymous Sourceforge user, not verified to be MTP!
  { "Philips", 0x0471, "GoGear SA3345", 0x2004, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Roberto Vidmar <rvidmar@libero.it>
  { "Philips", 0x0471, "SA5285", 0x2022, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Elie De Brauwer <elie@de-brauwer.be>
  { "Philips", 0x0471, "GoGear ViBE SA1VBE04", 0x2075,
    DEVICE_FLAG_UNLOAD_DRIVER },
  // From Elie De Brauwer <elie@de-brauwer.be>
  { "Philips", 0x0471, "GoGear ViBE SA1VBE08", 0x207b,
    DEVICE_FLAG_UNLOAD_DRIVER },
  // From josmtx <josmtx@users.sourceforge.net>
  { "Philips", 0x0471, "GoGear Aria", 0x207c,
    DEVICE_FLAG_UNLOAD_DRIVER },
  // from XNJB user
  { "Philips", 0x0471, "PSA235", 0x7e01, DEVICE_FLAG_NONE },

  /*
   * SanDisk
   * several devices (c150 for sure) are definately dual-mode and must
   * have the USB mass storage driver that hooks them unloaded first.
   * They all have problematic dual-mode making the device unload effect
   * uncertain on these devices.
   *
   * All older devices seem to need DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL.
   * Old chipsets: e200/c200 use PP5024 from Nvidia (formerly PortalPlayer).
   * m200 use TCC770 from Telechips.
   *
   * The newer Sansa v2 chipset, AD3525 from Austriamicrosystems (AMS) found
   * in e280 v2 c200 v2, Clip, Fuze etc require DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST
   * and DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR to work properly.
   *
   * For more info see: http://daniel.haxx.se/sansa/v2.html
   */
  // Reported by Brian Robison
  { "SanDisk", 0x0781, "Sansa m230/m240", 0x7400,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // From Rockbox device listing
  { "SanDisk", 0x0781, "Sansa m200-tcc (MTP mode)", 0x7401,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by tangent_@users.sourceforge.net
  { "SanDisk", 0x0781, "Sansa c150", 0x7410,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // From libgphoto2 source
  // Reported by <gonkflea@users.sourceforge.net>
  // Reported by Mike Owen <mikeowen@computerbaseusa.com>
  { "SanDisk", 0x0781, "Sansa e200/e250/e260/e270/e280", 0x7420,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Don't add 0x7421 as this is e280 in MSC mode
  // Reported by XNJB user
  { "SanDisk", 0x0781, "Sansa e260/e280 v2", 0x7422,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR |
    DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by XNJB user
  { "SanDisk", 0x0781, "Sansa m240/m250", 0x7430,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by Eugene Brevdo <ebrevdo@princeton.edu>
  { "SanDisk", 0x0781, "Sansa Clip", 0x7432,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR |
    DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED},
  // Reported by HackAR <hackar@users.sourceforge.net>
  { "SanDisk", 0x0781, "Sansa Clip v2", 0x7434,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR |
    DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED},
  // Reported by anonymous user at sourceforge.net
  { "SanDisk", 0x0781, "Sansa c240/c250", 0x7450,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by anonymous SourceForge user
  { "SanDisk", 0x0781, "Sansa c250 v2", 0x7452,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by Troy Curtis Jr.
  { "SanDisk", 0x0781, "Sansa Express", 0x7460,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by XNJB user, and Miguel de Icaza <miguel@gnome.org>
  // This has no dual-mode so no need to unload any driver.
  // This is a Linux based device!
  { "SanDisk", 0x0781, "Sansa Connect", 0x7480, DEVICE_FLAG_NONE },
  // Reported by anonymous SourceForge user
  { "SanDisk", 0x0781, "Sansa View", 0x74b0,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Reported by Patrick <skibler@gmail.com>
  // There are apparently problems with this device.
  { "SanDisk", 0x0781, "Sansa Fuze", 0x74c0,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR |
    DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },
  // Harry Phillips <tuxcomputers@users.sourceforge.net>
  { "SanDisk", 0x0781, "Sansa Fuze v2", 0x74c2,
    DEVICE_FLAG_UNLOAD_DRIVER |  DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR |
    DEVICE_FLAG_CANNOT_HANDLE_DATEMODIFIED },

  /*
   * iRiver
   * we assume that PTP_OC_MTP_GetObjPropList is essentially
   * broken on all iRiver devices, meaning it simply won't return
   * all properties for a file when asking for metadata 0xffffffff.
   * Please test on your device if you believe it isn't broken!
   */
  { "iRiver", 0x1006, "H300 Series MTP", 0x3004,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x1006, "Portable Media Center", 0x4002,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x1006, "Portable Media Center", 0x4003,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // From [st]anislav <iamstanislav@gmail.com>
  { "iRiver", 0x1042, "T7 Volcano", 0x1143, DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // From an anonymous person at SourceForge, uncertain about this one
  { "iRiver", 0x4102, "iFP-880", 0x1008,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // 0x4102, 0x1042 is a USB mass storage mode for E100 v2/Lplayer
  // From libgphoto2 source
  { "iRiver", 0x4102, "T10", 0x1113,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x4102, "T20 FM", 0x1114,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // This appears at the MTP-UMS site
  { "iRiver", 0x4102, "T20", 0x1115,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x4102, "U10", 0x1116,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x4102, "T10a", 0x1117,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x4102, "T20", 0x1118,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  { "iRiver", 0x4102, "T30", 0x1119,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Reported by David Wolpoff
  { "iRiver", 0x4102, "T10 2GB", 0x1120,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Rough guess this is the MTP device ID...
  { "iRiver", 0x4102, "N12", 0x1122,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Reported by Philip Antoniades <philip@mysql.com>
  // Newer iriver devices seem to have shaped-up firmware without any
  // of the annoying bugs.
  { "iRiver", 0x4102, "Clix2", 0x1126, DEVICE_FLAG_NONE },
  // Reported by Adam Torgerson
  { "iRiver", 0x4102, "Clix", 0x112a,
    DEVICE_FLAG_NO_ZERO_READS | DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Reported by Douglas Roth <dougaus@gmail.com>
  { "iRiver", 0x4102, "X20", 0x1132,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Reported by Robert Ugo <robert_ugo@users.sourceforge.net>
  { "iRiver", 0x4102, "T60", 0x1134,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_IRIVER_OGG_ALZHEIMER },
  // Reported by two anonymous SourceForge users
  // Needs the stronger OGG_IS_UNKNOWN flag to support OGG properly,
  // be aware of newer players that may be needing this too.
  { "iRiver", 0x4102, "E100", 0x1141,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },
  // Reported by anonymous SourceForge user
  // Need verification of whether this firmware really need all these flags
  { "iRiver", 0x4102, "E100 v2/Lplayer", 0x1142,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },
  // Reported by Richard Vennemann <vennemann@users.sourceforge.net>
  // In USB Mass Storage mode it is 0x4102/0x1047
  // Seems to use the new shaped-up firmware.
  { "iRiver", 0x4102, "Spinn", 0x1147, DEVICE_FLAG_NONE },
  // Reported by Tony Janssen <tonyjanssen@users.sourceforge.net>
  { "iRiver", 0x4102, "E50", 0x1151,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },
  // Reported by Scott Call
  // Assume this actually supports OGG though it reports it doesn't.
  { "iRiver", 0x4102, "H10 20GB", 0x2101,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },
  { "iRiver", 0x4102, "H10 5GB", 0x2102,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },
  // From Rockbox device listing
  { "iRiver", 0x4102, "H10 5.6GB", 0x2105,
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_NO_ZERO_READS |
    DEVICE_FLAG_OGG_IS_UNKNOWN },

  /*
   * Dell
   */
  { "Dell, Inc", 0x413c, "DJ Itty", 0x4500, DEVICE_FLAG_NONE },

  /*
   * Toshiba
   * Tentatively flagged all Toshiba devices with
   * DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST after one of them
   * showed erroneous behaviour.
   */
  { "Toshiba", 0x0930, "Gigabeat MEGF-40", 0x0009,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  { "Toshiba", 0x0930, "Gigabeat", 0x000c,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Nicholas Tripp
  { "Toshiba", 0x0930, "Gigabeat P20", 0x000f,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // From libgphoto2
  { "Toshiba", 0x0930, "Gigabeat S", 0x0010, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL |
      DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Rob Brown
  { "Toshiba", 0x0930, "Gigabeat P10", 0x0011,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by solanum@users.sourceforge.net
  { "Toshiba", 0x0930, "Gigabeat V30", 0x0014,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Michael Davis <slithy@yahoo.com>
  { "Toshiba", 0x0930, "Gigabeat U", 0x0016,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Devon Jacobs <devo@godevo.com>
  { "Toshiba", 0x0930, "Gigabeat MEU202", 0x0018,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Rolf <japan (at) dl3lar.de>
  { "Toshiba", 0x0930, "Gigabeat T", 0x0019,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by Phil Ingram <ukpbert@users.sourceforge.net>
  // Tentatively added - no real reports of this device ID being MTP,
  // reports as USB Mass Storage currently.
  { "Toshiba", 0x0930, "Gigabeat MEU201", 0x001a,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },
  // Reported by anonymous SourceForge user
  { "Toshiba", 0x0930, "Gigabeat MET401", 0x001d,
    DEVICE_FLAG_NO_RELEASE_INTERFACE |  DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },

  /*
   * Archos
   * These devices have some dual-mode interfaces which will really
   * respect the driver unloading, so DEVICE_FLAG_UNLOAD_DRIVER
   * really work on these devices!
   */
  // Reported by Alexander Haertig <AlexanderHaertig@gmx.de>
  { "Archos", 0x0e79, "Gmini XS100", 0x1207, DEVICE_FLAG_UNLOAD_DRIVER },
  // Added by Jan Binder
  { "Archos", 0x0e79, "XS202 (MTP mode)", 0x1208, DEVICE_FLAG_NONE },
  // Reported by gudul1@users.sourceforge.net
  { "Archos", 0x0e79, "104 (MTP mode)", 0x120a, DEVICE_FLAG_NONE },
  // Reported by anonymous Sourceforge user.
  { "Archos", 0x0e79, "404 (MTP mode)", 0x1301, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Etienne Chauchot <chauchot.etienne@free.fr>
  { "Archos", 0x0e79, "504 (MTP mode)", 0x1307, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Kay McCormick <kaym@modsystems.com>
  { "Archos", 0x0e79, "704 mobile dvr", 0x130d, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Joe Rabinoff
  { "Archos", 0x0e79, "605 (MTP mode)", 0x1313, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Jim Krehl <jimmuhk@users.sourceforge.net>
  { "Archos", 0x0e79, "5 (MTP mode)", 0x1331, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Adrien Guichard <tmor@users.sourceforge.net>
  { "Archos", 0x0e79, "5 (MTP mode)", 0x1333, DEVICE_FLAG_UNLOAD_DRIVER },

  /*
   * Dunlop (OEM of EGOMAN ltd?) reported by Nanomad
   * This unit is falsely detected as USB mass storage in Linux
   * prior to kernel 2.6.19 (fixed by patch from Alan Stern)
   * so on older kernels special care is needed to remove the
   * USB mass storage driver that erroneously binds to the device
   * interface.
   */
  { "Dunlop", 0x10d6, "MP3 player 1GB / EGOMAN MD223AFD", 0x2200, DEVICE_FLAG_UNLOAD_DRIVER},
  // Reported by Steven Black <stevenblack1956@users.sourceforge.net>
  // Obviously this company goes by many names.
  // This device is USB 2.0 only. Broken pipe on closing.
  { "Memorex", 0x10d6, "MMP 8585/8586", 0x2300, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_NO_RELEASE_INTERFACE},

  /*
   * Microsoft
   */
  // Reported by Farooq Zaman (used for all Zunes)
  { "Microsoft", 0x045e, "Zune", 0x0710, DEVICE_FLAG_NONE },

  /*
   * Sirius
   */
  { "Sirius", 0x18f6, "Stiletto", 0x0102, DEVICE_FLAG_NONE },
  // Reported by Chris Bagwell <chris@cnpbagwell.com>
  { "Sirius", 0x18f6, "Stiletto 2", 0x0110, DEVICE_FLAG_NONE },

  /*
   * Canon
   * This is actually a camera, but it has a Microsoft device descriptor
   * and reports itself as supporting the MTP extension.
   */
  { "Canon", 0x04a9, "PowerShot A640 (PTP/MTP mode)", 0x3139,
     DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },

  /*
   * Nokia
   * Please verify the low device IDs here, I suspect these might be for
   * things like USB storage or modem mode actually, whereas the higher
   * range (0x04nn) could be for MTP. Some of the devices were gathered
   * from the Nokia WMP drivers:
   * http://nds2.nokia.com/files/support/global/phones/software/
   * Address was gathered from going to:
   * nseries.com
   * -> support
   * -> select supported device
   *  -> PC software
   *    -> Music software
   *      -> Windows Media Player 10 driver
   */
  // From: DoomHammer <gaczek@users.sourceforge.net>
  { "Nokia", 0x0421, "N81 Mobile Phone", 0x000a, DEVICE_FLAG_NONE },
  // From an anonymous SourceForge user
  { "Nokia", 0x0421, "6120c Classic Mobile Phone", 0x002e, DEVICE_FLAG_NONE },
  // From Stefano
  { "Nokia", 0x0421, "N96 Mobile Phone", 0x0039, DEVICE_FLAG_NONE },
  // From Martijn van de Streek <martijn@vandestreek.net>
  { "Nokia", 0x0421, "6500c Classic Mobile Phone", 0x003c, DEVICE_FLAG_NONE },
  // From: DoomHammer <gaczek@users.sourceforge.net>
  { "Nokia", 0x0421, "3110c Mobile Phone", 0x005f, DEVICE_FLAG_NONE },
  // From: Vasily <spc-@users.sourceforge.net>
  { "Nokia", 0x0421, "3109c Mobile Phone", 0x0065, DEVICE_FLAG_NONE },
  // From: <rawc@users.sourceforge.net>
  { "Nokia", 0x0421, "5310 XpressMusic", 0x006c, DEVICE_FLAG_NONE },
  // From: robin (AT) headbank D0Tco DOTuk
  { "Nokia", 0x0421, "N95 Mobile Phone 8GB", 0x006e, DEVICE_FLAG_NONE },
  // From Bastien Nocera <hadess@hadess.net>
  { "Nokia", 0x0421, "N82 Mobile Phone", 0x0074, DEVICE_FLAG_NONE },
  // From Martijn van de Streek <martijn@vandestreek.net>
  { "Nokia", 0x0421, "N78 Mobile Phone", 0x0079, DEVICE_FLAG_NONE },
  // From William Pettersson <the_enigma@users.sourceforge.net>
  { "Nokia", 0x0421, "6220 Classic", 0x008d, DEVICE_FLAG_NONE },
  // From kellerkev@gmail.com
  { "Nokia", 0x0421, "N85 Mobile Phone", 0x0092, DEVICE_FLAG_NONE },
  // From: danielw
  { "Nokia", 0x0421, "E71", 0x00e4, DEVICE_FLAG_NONE },
  // From: Laurent Bigonville <bigon@users.sourceforge.net>
  { "Nokia", 0x0421, "E66", 0x00e5, DEVICE_FLAG_NONE },
  // From: Pier <pierlucalino@users.sourceforge.net>
  { "Nokia", 0x0421, "5320 XpressMusic", 0x00ea, DEVICE_FLAG_NONE },
  // From: Gausie <innerdreams@users.sourceforge.net>
  { "Nokia", 0x0421, "5800 XpressMusic", 0x0154, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // From: Willy Gardiol (web) <willy@gardiol.org>
  // Spurious errors for getting all objects, lead me to believe this flag atleast is needed
  { "Nokia", 0x0421, "5800 XpressMusic v2", 0x0155, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // From an anonymous SourceForge user
  // Not verified to be MTP
  { "Nokia", 0x0421, "E63", 0x0179, DEVICE_FLAG_NONE },
  // From: FunkyPenguin <awafaa@users.sourceforge.net>
  { "Nokia", 0x0421, "N97", 0x01f5, DEVICE_FLAG_NONE },
  // From: Alexander Kojevnikov <alex-kay@users.sourceforge.net>
  { "Nokia", 0x0421, "6600i", 0x0297, DEVICE_FLAG_NONE },
  // https://sourceforge.net/tracker/index.php?func=detail&aid=2692473&group_id=8874&atid=358874
  { "Nokia", 0x0421, "5200", 0x0421, DEVICE_FLAG_NONE },
  // From: http://nds2.nokia.com/files/support/global/phones/software/Nokia_3250_WMP10_driver.inf
  { "Nokia", 0x0421, "3250 Mobile Phone", 0x0462, DEVICE_FLAG_NONE },
  // From http://nds2.nokia.com/files/support/global/phones/software/Nokia_N93_WMP10_Driver.inf
  { "Nokia", 0x0421, "N93 Mobile Phone", 0x0478, DEVICE_FLAG_NONE },
  // From: http://nds2.nokia.com/files/support/global/phones/software/Nokia_5500_Sport_WMP10_driver.inf
  { "Nokia", 0x0421, "5500 Sport Mobile Phone", 0x047e, DEVICE_FLAG_NONE },
  // From http://nds2.nokia.com/files/support/global/phones/software/Nokia_N91_WMP10_Driver.inf
  { "Nokia", 0x0421, "N91 Mobile Phone", 0x0485, DEVICE_FLAG_NONE },
  // From: Christian Rusa <kristous@users.sourceforge.net>
  { "Nokia", 0x0421, "5700 XpressMusic Mobile Phone", 0x04b4, DEVICE_FLAG_NONE },
  // From: Mitchell Hicks <mitchix@yahoo.com>
  { "Nokia", 0x0421, "5300 Mobile Phone", 0x04ba, DEVICE_FLAG_NONE },
  // From Christian Arnold <webmaster@arctic-media.de>
  { "Nokia", 0x0421, "N73 Mobile Phone", 0x04d1, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Swapan <swapan@yahoo.com>
  { "Nokia", 0x0421, "N75 Mobile Phone", 0x04e1, DEVICE_FLAG_NONE },
  // From: http://nds2.nokia.com/files/support/global/phones/software/Nokia_N93i_WMP10_driver.inf
  { "Nokia", 0x0421, "N93i Mobile Phone", 0x04e5, DEVICE_FLAG_NONE },
  // From Anonymous Sourceforge User
  { "Nokia", 0x0421, "N95 Mobile Phone", 0x04ef, DEVICE_FLAG_NONE },
  // From: Pat Nicholls <pat@patandannie.co.uk>
  { "Nokia", 0x0421, "N80 Internet Edition (Media Player)", 0x04f1, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Richard Wall <richard@the-moon.net>
  { "Nokia", 0x05c6, "5530 Xpressmusic", 0x0229, DEVICE_FLAG_NONE },
  // Reported by anonymous SourceForge user
  // One thing stated by reporter (Nokia model) another by the detect log...
  { "Nokia/Verizon", 0x05c6, "6205 Balboa/Verizon Music Phone", 0x3196, DEVICE_FLAG_NONE },

  /*
   * LOGIK
   * Sold in the UK, seem to be manufactured by CCTech in China.
   */
  { "Logik", 0x13d1, "LOG DAX MP3 and DAB Player", 0x7002, DEVICE_FLAG_UNLOAD_DRIVER },

  /*
   * RCA / Thomson
   */
  // From kiki <omkiki@users.sourceforge.net>
  { "Thomson", 0x069b, "EM28 Series", 0x0774, DEVICE_FLAG_NONE },
  { "Thomson / RCA", 0x069b, "Opal / Lyra MC4002", 0x0777, DEVICE_FLAG_NONE },
  { "Thomson", 0x069b, "Lyra MC5104B (M51 Series)", 0x077c, DEVICE_FLAG_NONE },
  { "Thomson", 0x069b, "RCA H106", 0x301a, DEVICE_FLAG_UNLOAD_DRIVER },
  // From Svenna <svenna@svenna.de>
  // Not confirmed to be MTP.
  { "Thomson", 0x069b, "scenium E308", 0x3028, DEVICE_FLAG_NONE },
  // From XNJB user
  { "Thomson / RCA", 0x069b, "Lyra HC308A", 0x3035, DEVICE_FLAG_NONE },

  /*
   * NTT DoCoMo
   */
  { "FOMA", 0x04c5, "F903iX HIGH-SPEED", 0x1140, DEVICE_FLAG_NONE },

  /*
   * Palm device userland program named Pocket Tunes
   * Reported by Peter Gyongyosi <gyp@impulzus.com>
   */
  { "NormSoft, Inc.", 0x1703, "Pocket Tunes", 0x0001, DEVICE_FLAG_NONE },
  // Reported by anonymous submission
  { "NormSoft, Inc.", 0x1703, "Pocket Tunes 4", 0x0002, DEVICE_FLAG_NONE },

  /*
   * TrekStor, Medion and Maxfield devices
   * Their datasheet claims their devices are dualmode so probably needs to
   * unload the attached drivers here.
   */
  // Reported by Stefan Voss <svoss@web.de>
  // This is a Sigmatel SoC with a hard disk.
  { "TrekStor", 0x066f, "Vibez 8/12GB", 0x842a,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by anonymous SourceForge user.
  // This one done for Medion, whatever that is. Error reported so assume
  // the same bug flag as its ancestor above.
  { "Medion", 0x066f, "MD8333", 0x8550,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by anonymous SourceForge user
  { "Medion", 0x066f, "MD8333", 0x8588,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by anonymous SourceForge user
  { "Maxfield", 0x066f, "G-Flash NG 1GB", 0x846c,
    DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Cristi Magherusan <majeru@gentoo.ro>
  { "TrekStor", 0x0402, "i.Beat Sweez FM", 0x0611,
    DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Fox-ino <fox-ino@users.sourceforge.net>
  { "ALi Corp.", 0x0402, "MPMAN 2GB", 0x5668,
    DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Anonymous SourceForge user
  {"TrekStor", 0x1e68, "i.Beat Organix 2.0", 0x0002,
    DEVICE_FLAG_UNLOAD_DRIVER },

  /*
   * Disney/Tevion/MyMusix
   */
  // Reported by XNJB user
  { "Disney", 0x0aa6, "MixMax", 0x6021, DEVICE_FLAG_NONE },
  // Reported by anonymous Sourceforge user
  { "Tevion", 0x0aa6, "MD 81488", 0x3011, DEVICE_FLAG_NONE },
  // Reported by Peter Hedlund <peter@peterandlinda.com>
  { "MyMusix", 0x0aa6, "PD-6070", 0x9601, DEVICE_FLAG_UNLOAD_DRIVER |
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST |
    DEVICE_FLAG_NO_RELEASE_INTERFACE },

  /*
   * Cowon Systems, Inc.
   * The iAudio audiophile devices don't encourage the use of MTP.
   */
  // Reported by Patrik Johansson <Patrik.Johansson@qivalue.com>
  { "Cowon", 0x0e21, "iAudio U3 (MTP mode)", 0x0701,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Kevin Michael Smith <hai-etlik@users.sourceforge.net>
  { "Cowon", 0x0e21, "iAudio 6 (MTP mode)", 0x0711,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Roberth Karman
  { "Cowon", 0x0e21, "iAudio 7 (MTP mode)", 0x0751,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by an anonymous SourceForge user
  { "Cowon", 0x0e21, "iAudio U5 (MTP mode)", 0x0761,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by TJ Something <tjbk_tjb@users.sourceforge.net>
  { "Cowon", 0x0e21, "iAudio D2 (MTP mode)", 0x0801,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by anonymous Sourceforge user
  { "Cowon", 0x0e21, "iAudio D2+ FW 2.x (MTP mode)", 0x0861,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // From Rockbox device listing
  { "Cowon", 0x0e21, "iAudio D2+ DAB FW 4.x (MTP mode)", 0x0871,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // From Rockbox device listing
  { "Cowon", 0x0e21, "iAudio D2+ FW 3.x (MTP mode)", 0x0881,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // From Rockbox device listing
  { "Cowon", 0x0e21, "iAudio D2+ DMB FW 1.x (MTP mode)", 0x0891,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by <twkonefal@users.sourceforge.net>
  { "Cowon", 0x0e21, "iAudio S9 (MTP mode)", 0x0901,
   DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
   DEVICE_FLAG_OGG_IS_UNKNOWN | DEVICE_FLAG_FLAC_IS_UNKNOWN },

  /*
   * Insignia, dual-mode.
   */
  { "Insignia", 0x19ff, "NS-DV45", 0x0303, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by Rajan Bella <rajanbella@yahoo.com>
  { "Insignia", 0x19ff, "Sport Player", 0x0307, DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by "brad" (anonymous, sourceforge)
  { "Insignia", 0x19ff, "Pilot 4GB", 0x0309, DEVICE_FLAG_UNLOAD_DRIVER },

  /*
   * LG Electronics
   */
  // Not verified - anonymous submission
  { "LG Electronics Inc.", 0x043e, "UP3", 0x70b1, DEVICE_FLAG_NONE },
  // Reported by Joseph Nahmias <joe@nahimas.net>
  { "LG Electronics Inc.", 0x1004, "VX8550 V CAST Mobile Phone", 0x6010,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST | DEVICE_FLAG_ALWAYS_PROBE_DESCRIPTOR },
  // Reported by Cyrille Potereau <cyrille.potereau@wanadoo.fr>
  { "LG Electronics Inc.", 0x1004, "KC910 Renoir Mobile Phone", 0x608f,
      DEVICE_FLAG_UNLOAD_DRIVER },
  // Reported by anonymous sourceforge user
  { "LG Electronics Inc.", 0x1004, "KM900", 0x6132,
      DEVICE_FLAG_UNLOAD_DRIVER },

  /*
   * Sony
   * It could be that these PIDs are one-per hundred series, so
   * NWZ-A8xx is 0325, NWZ-S5xx is 0x326 etc. We need more devices
   * reported to see a pattern here.
   */
  // Reported by Alessandro Radaelli <alessandro.radaelli@aruba.it>
  { "Sony", 0x054c, "Walkman NWZ-A815/NWZ-A818", 0x0325,
      DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by anonymous Sourceforge user.
  { "Sony", 0x054c, "Walkman NWZ-S516", 0x0326, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Endre Oma <endre.88.oma@gmail.com>
  { "Sony", 0x054c, "Walkman NWZ-S615F/NWZ-S616F/NWZ-S618F", 0x0327,
      DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Jean-Marc Bourguet <jm@bourguet.org>
  { "Sony", 0x054c, "Walkman NWZ-S716F", 0x035a, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Anon SF User / Anthon van der Neut <avanderneut@avid.com>
  { "Sony", 0x054c, "Walkman NWZ-A826/NWZ-A828/NWZ-A829", 0x035b,
      DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Niek Klaverstijn <niekez@users.sourceforge.net>
  { "Sony", 0x054c, "Walkman NWZ-A726/NWZ-A728/NWZ-A768", 0x035c,
      DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Mehdi AMINI <mehdi.amini - at - ulp.u-strasbg.fr>
  { "Sony", 0x054c, "Walkman NWZ-B135", 0x036e, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by <tiagoboldt@users.sourceforge.net>
  { "Sony", 0x054c, "Walkman NWZ-E436F", 0x0385, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Michael Wilkinson
  { "Sony", 0x054c, "Walkman NWZ-W202", 0x0388, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Ondrej Sury <ondrej@sury.org>
  { "Sony", 0x054c, "Walkman NWZ-S739F", 0x038c, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Marco Filipe Nunes Soares Abrantes Pereira <marcopereira@ua.pt>
  { "Sony", 0x054c, "Walkman NWZ-S638F", 0x038e, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Elliot <orwells@users.sourceforge.net>
  { "Sony", 0x054c, "Walkman NWZ-X1050B/NWZ-X1060B",
    0x0397, DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Silvio J. Gutierrez <silviogutierrez@users.sourceforge.net>
  { "Sony", 0x054c, "Walkman NWZ-X1051/NWZ-X1061", 0x0398,
      DEVICE_FLAG_UNLOAD_DRIVER |
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },

  /*
   * SonyEricsson
   * These initially seemed to support GetObjPropList but later revisions
   * of the firmware seem to have broken it, so all are flagged as broken
   * for now.
   */
  // Reported by Thomas Schweitzer <thomas_-_s@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "K550i", 0xe000, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Øyvind Stegard <stegaro@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "K850i", 0x0075, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Michael Eriksson
  { "SonyEricsson", 0x0fce, "W910", 0x0076, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Zack <zackdvd@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "W890i", 0x00b3, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by robert dot ahlskog at gmail
  { "SonyEricsson", 0x0fce, "W760i", 0x00c6, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Linus Åkesson <linusakesson@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "C902", 0x00d4, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by an anonymous SourceForge user
  { "SonyEricsson", 0x0fce, "C702", 0x00d9, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Christian Zuckschwerdt <christian@zuckschwerdt.org>
  { "SonyEricsson", 0x0fce, "W980", 0x00da, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by David Taylor <davidt-libmtp@yadt.co.uk>
  { "SonyEricsson", 0x0fce, "C905", 0x00ef, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by David House <dmhouse@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "W595", 0x00f3,
      DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL | DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST },
  // Reported by Mattias Evensson <mevensson@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "W902", 0x00f5, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Sarunas <sarunas@users.sourceforge.net>
  // Doesn't need any flags according to reporter
  { "SonyEricsson", 0x0fce, "T700", 0x00fb, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by Stéphane Pontier <shadow_walker@users.sourceforge.net>
  { "SonyEricsson", 0x0fce, "W705/W715", 0x0105, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },
  // Reported by Håkan Kvist
  { "SonyEricsson", 0x0fce, "W995", 0x0112, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },

  /*
   * Motorola
   * Assume DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST on all of these.
   */
  // Reported by David Boyd <tiggrdave@users.sourceforge.net>
  { "Motorola", 0x22b8, "V3m/V750 verizon", 0x2a65, DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST |
    DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
  // Reported by Marcus Meissner to libptp2
  { "Motorola", 0x22b8, "K1", 0x4811, DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST },
  // Reported by Hans-Joachim Baader <hjb@pro-linux.de> to libptp2
  { "Motorola", 0x22b8, "A1200", 0x60ca, DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST },
  // http://mark.cdmaforums.com/Files/Motdmmtp.inf
  { "Motorola", 0x22b8, "MTP Test Command Interface", 0x6413, DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST },
  // Reported by anonymous user
  { "Motorola", 0x22b8, "RAZR2 V8/U9/Z6", 0x6415, DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST },

  /*
   * Media Keg
   */
  // Reported by Rajan Bella <rajanbella@yahoo.com>
  { "Kenwood", 0x0b28, "Media Keg HD10GB7 Sport Player", 0x100c, DEVICE_FLAG_UNLOAD_DRIVER},

  /*
   * Micro-Star International (MSI)
   */
  // Reported by anonymous sourceforge user.
  { "Micro-Star International", 0x0db0, "P610/Model MS-5557", 0x5572, DEVICE_FLAG_NONE },

  /*
   * FOMA
   */
  { "FOMA", 0x06d3, "D905i", 0x21ba, DEVICE_FLAG_NONE },

  /*
   * Haier
   */
  // Both reported by an anonymous SourceForge user
  // This is the 30 GiB model
  { "Haier", 0x1302, "Ibiza Rhapsody", 0x1016, DEVICE_FLAG_NONE },
  // This is the 4/8 GiB model
  { "Haier", 0x1302, "Ibiza Rhapsody", 0x1017, DEVICE_FLAG_NONE },

  /*
   * Panasonic
   */
  // Reported by dmizer
  { "Panasonic", 0x04da, "P905i", 0x2145, DEVICE_FLAG_NONE },

  /*
   * Polaroid
   */
  { "Polaroid", 0x0546, "Freescape/MPU-433158", 0x2035, DEVICE_FLAG_NONE },

  /*
   * Pioneer
   */
  // Reported by Dan Allen <dan.j.allen@gmail.com>
  { "Pioneer", 0x08e4, "XMP3", 0x0148, DEVICE_FLAG_NONE },

  /*
   * Slacker Inc.
   * Put in all evilness flags because it looks fragile.
   */
  // Reported by Pug Fantus <pugfantus@users.sourceforge.net>
  { "Slacker Inc.", 0x1bdc, "Slacker Portable Media Player", 0xfabf,
    DEVICE_FLAG_BROKEN_BATTERY_LEVEL | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST |
    DEVICE_FLAG_BROKEN_SET_OBJECT_PROPLIST | DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST },

  // Reported by Demadridsur <demadridsur@gmail.com>
  { "O2 Sistemas", 0x1e53, "ZoltarTV", 0x0006, DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST },

  // Reported by Sense Hofstede <qense@users.sourceforge.net>
  { "Perception Digital, Ltd", 0x0aa6, "Gigaware GX400", 0x9702, DEVICE_FLAG_NONE },
  /*
   * Other strange stuff.
   */
  { "Isabella", 0x0b20, "Her Prototype", 0xddee, DEVICE_FLAG_NONE }


text:
var connect = require('connect'),
	http = require('http'),
	directory = 'demo';

var staticServer = connect()
	// .use(function(req, res) {
	// 	res.end('nodejs sandbox!\n');
	// })
	.use(connect.static(directory));

http.createServer(staticServer).listen(8080);

console.log("Listening on port 8080...");


text:
require.config({
    paths: {
        angular: '../bower_components/angular/angular',
        angular_route: '../bower_components/angular-route/angular-route',
        semantic: '../bower_components/semantic-ui/build/packaged/javascript/semantic',
        jquery: '../bower_components/jquery/jquery'
    },
    shim: {
        angular: {
            exports: 'angular'
        },
        angular_route: {
            deps: ['angular'],
            exports: 'angular_route'
        },
        semantic : {
            deps: ['jquery'],
            exports: 'semantic'
        }
    }
});

require(['app'], function (app) {
    'use strict';

    console.log('main');
    app.init();

});


text:
Autorización
=============

La autorización es el proceso para verificar que un usuario tiene permitido realizar algo. Yii provee dos metodos de autorización:
 Filtro de Control de Acceso (Access Control Filter-ACF) y Control de Acceso Basado en Roles (Role-Based Access Control-RBAC).

## Filtro de Control de Acceso (ACF)

El Filtro de Control de Acceso (ACF) es un metodo simple de autorizacion implementado como [[yii\filters\AccessControl]] el cual
es la mejor opcion para ser usado en aplicaciones que requieren un control de acceso sencillo. Como su nombre lo indica, ACF es una accion
de [filter](structure-filters.md) que puede ser usada por un controlador o un módulo. Mientras un usuario este solicitando
la ejecucion de una accion, ACF se encargara de verificar en la lista de [[yii\filters\AccessControl::rules|access rules]]
para determinar si el usuario esta autorizado para acceder a la accion solicitada.

El codigo siguiente muestra como utilizar ACF en el controlador `site` :

```php
use yii\web\Controller;
use yii\filters\AccessControl;

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['login', 'logout', 'signup'],
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => ['login', 'signup'],
                        'roles' => ['?'],
                    ],
                    [
                        'allow' => true,
                        'actions' => ['logout'],
                        'roles' => ['@'],
                    ],
                ],
            ],
        ];
    }
    // ...
}
```

En el codigo anterior ACF esta unido al controlador `site` como un behavior. Esta es la forma tipica de la utilizacion del filtro en una accion.
La opción `only` especifica como ACF debe aplicarse a las acciones `login`, `logout` y `signup`.
Todas las otras acciones en el controlador `site` no son asunto del control de acceso. La lista de opciones de  `rules`
del [[yii\filters\AccessRule|access rules]], dice lo siguiente:

- Permitir a todos los Invitados (los usuarios que no estan autenticados) acceder a las acciones `login` y `signup`. La opcion `roles`
  contiene un signo de interrogacion `?` el cual es una especia de token que representa a los usuarios que sean  "usuarios invitados".
- Todos los usuarios autenticados pueden acceder a la accion `logout`. El caracter `@` es otro token especial que representa a todos los "usuarios autenticados".

ACF lleva a cabo la verificación de autorización mediante el examen de las reglas de acceso de uno en uno de arriba a abajo hasta que encuentra
una regla que se relaciones con el contexto de ejecucion. El valor `allow` de la regla de coincidencia luego serán utilizados para
juzgar si el usuario esta autorizado o no. Si ninguna de las reglas se relaciona, significa que el usuario no esta autorizado,
y ACF detendra la ejecucion de la accion..

Cuando ACF determina que un usuario no esta autorizado para acceder a una accion, Toma alguna de las siguientes medidas por default:

* Si el usuario es un invitado, llamara a [[yii\web\User::loginRequired()]] y redirigir al usuario mediante el navegador a la pagina de login.
* Si el usuario esta autenticado, arrojara una [[yii\web\ForbiddenHttpException]].

Puedes personalizar este comportamiento (behavior) mediante la configuracion de la propiedad [[yii\filters\AccessControl::denyCallback]], por ejemplo:

```php
[
    'class' => AccessControl::className(),
    ...
    'denyCallback' => function ($rule, $action) {
        throw new \Exception('You are not allowed to access this page');
    }
]
```

[[yii\filters\AccessRule|Access rules]] somporta algunas opciones. A continuacion se muestra un resumen de las opciones soportadas.
Tambien puedes extender [[yii\filters\AccessRule]]  para crear tus propias clases de reglas personalizadas.

 * [[yii\filters\AccessRule::allow|allow]]: Especifica si se trata de una regla para "permitir" ("allow") o de una regla "denegar" ("deny") .

 * [[yii\filters\AccessRule::actions|actions]]: especifica cual de las acciones de esta regla se relaciona. Este deberia ser una matriz de IDs de accion.
 La comparacion entre mayúsculas y minúsculas. Si esta opcion esta vacia (empty) o no esta asignada,
 significa que la regla se aplica a todas las acciones.

 * [[yii\filters\AccessRule::controllers|controllers]]: especifica a cual de los controladores se relaciona esta regla.
 Esta deberia ser un arreglo de IDs de controladores. Cada ID de controlador es prefijado con el modulo ID (si cualquier).
La comparacion se hace entre mayúsculas y minúsculas.Si esta opcion esta vacia o no esta asignada, significa que la regla aplica a todo el controlador.

 * [[yii\filters\AccessRule::roles|roles]]: especifica a que rol de los usuario esta regla se relaciona.
    Dos roles especiales son reconocidos, y ellos son verificados por medio de [[yii\web\User::isGuest]]

     - `?`: Esta relacionado con usuarios invitados (no autenticados).
     - `@`: Esta relacionado a usuarios que estan autenticados.

    Usando otros nombres de rol este disparara la invocacion de [[yii\web\User::can()]], el cual requiere que este habilitado RBAC
   (Sera descrito en la siguiente subsección). Si esta opcion esta vacia o no esta asignada, esta regla aplica para todos los roles.

 * [[yii\filters\AccessRule::ips|ips]]: esta especifica a cual [[yii\web\Request::userIP|client IP addresses]] esta regla se relaciona.
Una direccion IP puede contener el comodin `*` al final para que coincida con las direcciones IP con el mismo prefijo.
Por ejemplo, '192.168.*' se relaciona con todas las direcciones IP con el segmento '192.168.'. Si esta opcion esta vacia o no se asigna,
aplicara para todas las direcciones IP.

 * [[yii\filters\AccessRule::verbs|verbs]]: especifica el metodo de peticion por el cual la regla se relaciona (por ejemplo, `GET`, `POST`).
La comparacion se hace entre mayúsculas y minúsculas.

 * [[yii\filters\AccessRule::matchCallback|matchCallback]]: especifica una llamada a PHP para determinar si esta regla debe aplicar.

 * [[yii\filters\AccessRule::denyCallback|denyCallback]]: especifica una llamada a PHP para determinar cuando esta regla debe negar el acceso.

A continuación se muestra un ejemplo de como hacer uso de la opcion `matchCallback`, el cual permite escribir el acceso arbitrariamente.
comprobar la lógica:

```php
use yii\filters\AccessControl;

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['special-callback'],
                'rules' => [
                    [
                        'actions' => ['special-callback'],
                        'allow' => true,
                        'matchCallback' => function ($rule, $action) {
                            return date('d-m') === '31-10';
                        }
                    ],
                ],
            ],
        ];
    }

    // ¡match-callback es llamado! A esta pagina solo se puede acceder cada 31 de octubre
    public function actionSpecialCallback()
    {
        return $this->render('happy-halloween');
    }
}
```

## Control de Acceso Basado en Roles (Role Based Access Control-RBAC)

El Control de Acceso Basado en Roles (RBAC) provee un simple pero poderoso control de acceso centralizado. Por favor dirigete a
 [Wikipedia](http://en.wikipedia.org/wiki/Role-based_access_control) para mas detalles acerca de la comparacion de RBAC
con otros mas esquemas de control de acceso.

Yii implementa un RBAC General y Jerarquico, siguiendo el [NIST RBAC model](http://csrc.nist.gov/rbac/sandhu-ferraiolo-kuhn-00.pdf).
Se provee la funcionalidad del RBAC a través de [[yii\rbac\ManagerInterface|authManager]] [application component](structure-application-components.md).

El uso de RBAC implica dos partes del trabajo. La primera parte es la construcción de los datos de la autorización de RBAC, y la segunda
 parte es la de usar esos datos de autorizacion realizar la comprobación de acceso en lugares donde se necesita.

Para facilitar nuestra descripcion proxima, nosotros primero deberemos introducirnos en los conceptos basicos de RBAC

### Conceptos Basicos

Un rol representa una coleccion de *permisos* (e.j. creando posts, actualizando posts). Un rol puede ser asignado
a uno o multiples usuarios. Para comprobar si un usuario tiene un permiso específico, podemos comprobar si se ha asignado al usuario
con un rol que contiene este permiso.

Asociado con cada función o permoso, puede haber una *regla*. Una regla representa una pieza de codigo que debera ser
ejecutada durante el chequeo de acceso para determinar si el rol o permiso aplica para el usuario que intenta acceder.
Por ejemplo, el permiso "actualizar post" deberia tener una regla que cheque si el usuario que esta accediendo es el creador del post.
Durante el chequeo de acceso, si el usuario NO  es el creador del post, el/ella se considero que no tienen el permiso "actualizar post".

Ambos, roles y permisos pueden ser organizados en una jerarquia. En particular, un un rol puede contener a otros roles y permisos;
 y un permiso puede contener a otros permisos. Yii implementa un *orden parcial* jerarquico el cual incluye el
jerarquia mas especial en *arbol*. Un rol puede contener a uno o varios permisos,mas no viceversa.

### Configurando RBAC

Antes de partir para definir los datos de autorización y realizar la comprobación de acceso, tenemos que configurar el
componente [[yii\base\Application::authManager|authManager]] de la aplicacion. Yii provee dos tipos de manejadores de autorizacion:
[[yii\rbac\PhpManager]] y [[yii\rbac\DbManager]]. El primero utiliza un archivo de script de PHP para almacenar los datos de autorizacion,
mientras que el segundo almacena los datos de autorizacion en la base de datos. Puedes considerar el uso de la primera si su aplicación
no requiere papel muy dinámico y gestión de permisos.

#### Usando `PhpManager`

El codigo siguiente muestra cómo configurar el `authManager` en la configuracion de la aplicacion usando la clase [[yii\rbac\PhpManager]]:

```php
return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\PhpManager',
        ],
        // ...
    ],
];
```

El `authManager` (manejador de autenticación) puede accesarse ahora via `\Yii::$app->authManager`.

Por defecto, [[yii\rbac\PhpManager]] almacena los datos de RBAC bajo el directorio `@app/rbac`. Asegurese que el directorio
y todos los archivos en el tienen los permisos suficientes para ser escritor por el proceso del servidor Web y otorgueselos de ser necesarios online.

#### Usando `DbManager`

El codigo siguiente muestra como configurar `authManager` in la configuracion de la aplicacion para la clase [yii\rbac\DbManager]]:

```php
return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\DbManager',
        ],
        // ...
    ],
];
```
> Nota: Si estas usando yii2-basic-app (aplicacion basica de yii2), deberas configurar el archivo que esta en `config/console.php` para declarar
  `authManager` y necesitas adicionalmente declararlo en `config/web.php`.
> En el caso de yii2-advanced-app el  `authManager` debera ser declarado bajo el directorio `common/config/main.php`.

`DbManager` usa cuatro tablas en la base de datos donde almacena los datos de autorización:

- [[yii\rbac\DbManager::$itemTable|itemTable]]: La tabla para almacenar los items de autorizacion. Por default "auth_item".
- [[yii\rbac\DbManager::$itemChildTable|itemChildTable]]: La tabla donde se almacenan los items de autorizacion por jerarquia. Por defecto es "auth_item_child".
- [[yii\rbac\DbManager::$assignmentTable|assignmentTable]]: La tabla donde se almacenan las asignaciones a los items de autorizacion. Por default "auth_assignment".
- [[yii\rbac\DbManager::$ruleTable|ruleTable]]: La tabla donde se almacenan las reglas. Por defecto "auth_rule".

Antes de que puedas implementar necesitas crear las tablas respectivas en la base de datos. Para hacerlo, tu puedes usar las migraciones contenidas en `@yii/rbac/migrations`:

`yii migrate --migrationPath=@yii/rbac/migrations`

El `authManager` puede ahora ser accedido via `\Yii::$app->authManager`.

### Construyendo los Datos de Autorización

Construyendo los datos de autorización que tienen que ver con las siguientes tareas:

- definiendo roles y permisos;
- estableciendo relaciones entre roles y permisos;
- definiendo reglas;
- asociando reglas con roles y permisos;
- asignando roles a usuarios.

Dependiendo de la flexibilidad en la autorizacion que se requiera las tareas se pueden cumplir por caminos diferentes

Si la jerarquía de permisos no cambia en absoluto y que tiene un número fijo de usuarios puede crear un
[console command](tutorial-console.md#create-command) que va a inicializar los datos de autorización una vez a través de las API que ofrece via `authManager`:

```php
<?php
namespace app\commands;

use Yii;
use yii\console\Controller;

class RbacController extends Controller
{
    public function actionInit()
    {
        $auth = Yii::$app->authManager;

        // add "createPost" permission
        $createPost = $auth->createPermission('createPost');
        $createPost->description = 'Create a post';
        $auth->add($createPost);

        // add "updatePost" permission
        $updatePost = $auth->createPermission('updatePost');
        $updatePost->description = 'Update post';
        $auth->add($updatePost);

        // add "author" role and give this role the "createPost" permission
        $author = $auth->createRole('author');
        $auth->add($author);
        $auth->addChild($author, $createPost);

        // add "admin" role and give this role the "updatePost" permission
        // as well as the permissions of the "author" role
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $updatePost);
        $auth->addChild($admin, $author);

        // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
        // usually implemented in your User model.
        $auth->assign($author, 2);
        $auth->assign($admin, 1);
    }
}
```

> Note: Si estas usando la plantilla avanzada, necesitas poner tu `RbacController` dentro del directorio `console/controllers`
 y cambiar el namespace a `console/controllers`.

Despues, ejecutando el comando `yii rbac/init` obtendremos la siguiente jerarquia:

![Simple RBAC hierarchy](../guide/images/rbac-hierarchy-1.png "Simple RBAC hierarchy")

Autor puede crear un post, admin puede actualizar su mensaje y hacer todo lo posible autor.

Si tu aplicacion permite al usuario el registro necesitas asignar los roles necesarios para cada usuario nuevo registrado. Por ejemplo, en orden para todos los usuarios inscritos para convertirse en autores de si plantilla avanzada tienes que modificar `frontend\models\SignupForm::signup()`
as follows:

```php
public function signup()
{
    if ($this->validate()) {
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        $user->save(false);

        // the following three lines were added:
        $auth = Yii::$app->authManager;
        $authorRole = $auth->getRole('author');
        $auth->assign($authorRole, $user->getId());

        return $user;
    }

    return null;
}
```

Para aplicaciones que requieren un control de acceso complejo con una actualizacion constante en los datos de autorizacion , interfaces especiales de usuario
(e.j. admin panel) pueden necesitar ser desarrollado utilizando las API que ofrece `authManager`.

### Usando Reglas

Como se habia mencionado, las reglas agregan restricciones adicionales a los roles y permisos. Una regla es una clase extendida desde
[[yii\rbac\Rule]]. Debe implementar al metodo [[yii\rbac\Rule::execute()|execute()]]. En la jerarquia tenemos creado previamente
que autor no puede editar su propio post. Vamos a arreglarlo. Primero necesitamos una regla para comprobar que el usuario es el autor del post:

```php
namespace app\rbac;

use yii\rbac\Rule;

/**
 * Checks if authorID matches user passed via params
 */
class AuthorRule extends Rule
{
    public $name = 'isAuthor';

    /**
     * @param string|integer $user the user ID.
     * @param Item $item the role or permission that this rule is associated with
     * @param array $params parameters passed to ManagerInterface::checkAccess().
     * @return boolean a value indicating whether the rule permits the role or permission it is associated with.
     */
    public function execute($user, $item, $params)
    {
        return isset($params['post']) ? $params['post']->createdBy == $user : false;
    }
}
```

La regla anterior comprueba si el `post` es creado por `$user`. Debemos crear un permiso especial `updateOwnPost` codigo que hemos utilizado
anteriormente:

```php
$auth = Yii::$app->authManager;

// add the rule
$rule = new \app\rbac\AuthorRule;
$auth->add($rule);

// add the "updateOwnPost" permission and associate the rule with it.
$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);

// "updateOwnPost" will be used from "updatePost"
$auth->addChild($updateOwnPost, $updatePost);

// allow "author" to update their own posts
$auth->addChild($author, $updateOwnPost);
```

Now we have got the following hierarchy:

![RBAC hierarchy with a rule](../guide/images/rbac-hierarchy-2.png "RBAC hierarchy with a rule")

### Comprobación de acceso

Con los datos de autorizacion listos, la comprobacion de acceso es una simple llamada a el metodo [[yii\rbac\ManagerInterface::checkAccess()]].
Dado que la mayoría de comprobación de acceso está sobre el usuario actual, para mayor comodidad Yii proporciona un método de acceso directo
[[yii\web\User::can()]], que puede ser utilizado como el siguiente:

```php
if (\Yii::$app->user->can('createPost')) {
    // create post
}
```

Si el usuario actual es Jane con `ID=1` estamos empezando a `createPost` y tratando de obtener a `Jane`:

![Access check](../guide/images/rbac-access-check-1.png "Access check")

Con el fin de comprobar si un usuario puede actualizar un anuncio, necesitamos pasar un parámetro adicional que es requerido por `AuthorRule` descrito antes:

```php
if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post
}
```

Aquí es lo que sucede si el usuario actual es John:

![Access check](../guide/images/rbac-access-check-2.png "Access check")

Estamos comenzando con el `updatePost` y pasando por `updateOwnPost`. Con el fin de pasar a la comprobación de acceso, `AuthorRule`
debe devolver `true` desde el metodo `execute()`. el metodo recive estos `$params` desde la llamada al metodo `can()`  por lo que el valor es
`['post' => $post]`. Si todo está bien, vamos a obtener a `author` el cual es asignado a John.

En caso de Jane que es un poco más simple ya que es un admin:

![Access check](../guide/images/rbac-access-check-3.png "Access check")

### Usando los roles por defecto

Un rol por defecto es un rol que esta asignado *implicitamente* a *todos* los usuarios. La llamada a [[yii\rbac\ManagerInterface::assign()]]
no es necesaria, y los datos de autorización no contiene la información de asignación.

Un rol por defecto es usualmente asociado con una regla la cual determina si el rol aplica al usuario verificado.

Los roles por defecto se utilizan a menudo en aplicaciones que ya tienen algún tipo de asignación de funciones. Por ejemplo, una aplicación
puede tener una columna "grupo" en su tabla de usuario para representar a qué grupo de privilegio cada usuario pertenece.
Si cada grupo privilegio puede ser asignada a un rol de RBAC, se puede utilizar la función de rol por default de forma automática
asignar a cada usuario a una función RBAC. Usemos un ejemplo para mostrar cómo se puede hacer esto.

Suponga que en la tabla de usuario, usted tiene una columna `grupo` que utiliza para representar el grupo administrador y 2 del grupo autor.
Planea tener dos roles RBAC `admin` y `author` para representar los permisos de estos dos grupos, respectivamente.
Puede configurar los datos de la siguiente manera en el RBAC,

```php
namespace app\rbac;

use Yii;
use yii\rbac\Rule;

/**
 * Checks if user group matches
 */
class UserGroupRule extends Rule
{
    public $name = 'userGroup';

    public function execute($user, $item, $params)
    {
        if (!Yii::$app->user->isGuest) {
            $group = Yii::$app->user->identity->group;
            if ($item->name === 'admin') {
                return $group == 1;
            } elseif ($item->name === 'author') {
                return $group == 1 || $group == 2;
            }
        }
        return false;
    }
}

$auth = Yii::$app->authManager;

$rule = new \app\rbac\UserGroupRule;
$auth->add($rule);

$author = $auth->createRole('author');
$author->ruleName = $rule->name;
$auth->add($author);
// ... add permissions as children of $author ...

$admin = $auth->createRole('admin');
$admin->ruleName = $rule->name;
$auth->add($admin);
$auth->addChild($admin, $author);
// ... add permissions as children of $admin ...
```

Tenga en cuenta que en la anterior, porque "author" es agregado como un hijo de "admin", cuando implementes el metodo `execute()`
de la clase de la regla, por lo que necesitas jerarquizar respectivamente bien. Por eso cuando el nombre del rol es "author",
el metodo `execute()` debera regresar true si el grupo de usuario  es cualquiera 1 o 2 (significa que el usuario se encuentra en
cualquiera de los dos grupos "admin" o grupo "author").

Lo mas próximo, configura `authManager` enumerando los dos roles en [[yii\rbac\BaseManager::$defaultRoles]]:

```php
return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\PhpManager',
            'defaultRoles' => ['admin', 'author'],
        ],
        // ...
    ],
];
```

Ahora bien, si se realiza una comprobación de acceso, tanto del rol `admin` y  del rol `author` el cual debera ser evaluado bajo
las reglas asociadas con ellas. si la regla devuelve true, esto significa que la regla se aplica al usuario actual.
Basado en la aplicacion de la regla anterior, esto significa que si el valor un grupo `group` de un usuario es 1, el rol `admin`
se aplicaría al usuario; y si el valor de `group` es 2, el rol `author` se aplicaria.


text:
var expect = require('chai').expect;
var lodash = require('lodash');

var RTM_API_EVENTS = require('../../../lib/clients/events/rtm').EVENTS;
var getMemoryDataStore = require('../../utils/client').getMemoryDataStore;
var messageHandlers = require('../../../lib/data-store/message-handlers');

var getRTMMessageFixture = require('../../fixtures').getRTMMessage;
var rtmStartFixture = require('../../fixtures/rtm.start');

var ALICE_USER_ID = 'U0CJ5PC7L';
var TEST_CHANNEL_ID = 'C0CJ25PDM';
var TEST_GROUP_ID = 'G0CHZSXFW';

describe('RTM API Message Handlers: Channel, Group & DM Events', function () {

  var isArchivedChange = function (event, id, expected) {
    var baseChannel;
    var dataStore = getMemoryDataStore();

    messageHandlers[event](dataStore, getRTMMessageFixture(event));
    baseChannel = dataStore.getChannelGroupOrDMById(id);
    expect(baseChannel.is_archived).to.equal(expected);
  };

  var testBaseChannelMarked = function (event, baseChannelId) {
    var dataStore = getMemoryDataStore();
    var baseChannel = dataStore.getChannelGroupOrDMById(baseChannelId);
    var originalUnreads;
    var newUnreads;

    baseChannel.history.push({ ts: 1 });
    baseChannel.history.push({ ts: 2 });

    originalUnreads = baseChannel.recalcUnreads();
    expect(originalUnreads).to.equal(3);

    messageHandlers[event](dataStore, getRTMMessageFixture(event));
    newUnreads = baseChannel.recalcUnreads();

    expect(newUnreads).to.equal(0);
  };

  var testBaseChannelRename = function (event, baseChannelId, expected) {
    var dataStore = getMemoryDataStore();
    var baseChannel;

    messageHandlers[event](dataStore, getRTMMessageFixture(event));
    baseChannel = dataStore.getChannelGroupOrDMById(baseChannelId);
    expect(baseChannel.name).to.equal(expected);
  };

  var testBaseChannelJoined = function (event, baseChannelId, expectedUserId) {
    var dataStore = getMemoryDataStore();
    var baseChannel;

    messageHandlers[event](dataStore, getRTMMessageFixture(event));
    baseChannel = dataStore.getChannelGroupOrDMById(baseChannelId);
    expect(baseChannel.members).to.have.length(2);
    expect(baseChannel).to.have.deep.property('members[1]', expectedUserId);
  };

  var testBaseChannelLeft = function (event, baseChannelId, expectedUserId) {
    var dataStore = getMemoryDataStore();
    var baseChannel;

    messageHandlers[event](ALICE_USER_ID, '', dataStore, getRTMMessageFixture(event));
    baseChannel = dataStore.getChannelGroupOrDMById(baseChannelId);
    expect(baseChannel.members).to.not.contain(expectedUserId);

    return baseChannel;
  };

  describe('`channel_xxx` events', function () {

    it('sets isArchived to true when a `channel_archive` message is received', function () {
      isArchivedChange('channel_archive', TEST_CHANNEL_ID, true);
    });

    it('sets isArchived to false when a `channel_unarchive` message is received', function () {
      isArchivedChange('channel_unarchive', TEST_CHANNEL_ID, false);
    });

    it('renames a channel when a `channel_rename` message is received', function () {
      testBaseChannelRename('channel_rename', TEST_CHANNEL_ID, 'test-channel-rename');
    });

    it('creates a new channel when a `channel_created` message is received', function () {
      var dataStore = getMemoryDataStore();
      var channel;

      messageHandlers.channel_created(dataStore, getRTMMessageFixture('channel_created'));
      channel = dataStore.getChannelById('C0F3Q8LH5');
      expect(channel).to.not.equal(undefined);
    });

    it('deletes a channel when a `channel_deleted` message is received', function () {
      var dataStore = getMemoryDataStore();
      var channel;

      messageHandlers.channel_deleted(dataStore, getRTMMessageFixture('channel_deleted'));
      channel = dataStore.getChannelById(TEST_CHANNEL_ID);
      expect(channel).to.equal(undefined);
    });

    it('creates a Channel, replacing the existing one, on `channel_joined` msg', function () {
      testBaseChannelJoined('channel_joined', TEST_CHANNEL_ID, 'U0F3LFX6K');
    });

    it('removes a user from a channel when a `channel_left` message is received', function () {
      var channel = testBaseChannelLeft('channel_left', TEST_CHANNEL_ID, 'U0F3LFX6K');
      expect(channel.is_member).to.equal(false);
    });

    it('marks the channel as read when a `channel_marked` message is received', function () {
      testBaseChannelMarked('channel_marked', TEST_CHANNEL_ID);
    });

  });

  describe('`group_xxx` events', function () {

    it('sets isArchived to true when a `group_archive` message is received', function () {
      isArchivedChange('group_archive', TEST_GROUP_ID, true);
    });

    it('sets isArchived to false when a `group_unarchive` message is received', function () {
      isArchivedChange('group_unarchive', TEST_GROUP_ID, false);
    });

    it('marks the group as read when a `group_marked` message is received', function () {
      testBaseChannelMarked('group_marked', TEST_GROUP_ID);
    });

    it('renames a group when a `group_rename` message is received', function () {
      testBaseChannelRename('group_rename', TEST_GROUP_ID, 'test-group-rename');
    });

    it('creates a Group, replacing the existing one, on `group_joined` msg', function () {
      testBaseChannelJoined('group_joined', TEST_GROUP_ID, 'U0F3LFX6K');
    });

    describe('`group_left`', function () {
      it('removes the user from a group when a `group_left` message is received', function () {
        testBaseChannelLeft('group_left', TEST_GROUP_ID, 'U0F3LFX6K');
      });

      it('marks the group as archived when the last user leaves', function () {
        var group = testBaseChannelLeft('group_left', TEST_GROUP_ID, 'U0F3LFX6K');
        expect(group.is_archived).to.equal(true);
      });
    });

  });

  describe('`im_xxx` events', function () {

    var testDMOpenStatus = function (isOpen, event) {
      var dataStore = getMemoryDataStore();
      dataStore.getDMById(rtmStartFixture.ims[0].id).is_open = isOpen;
      messageHandlers[event](dataStore, getRTMMessageFixture(event));

      expect(dataStore.getDMById(rtmStartFixture.ims[0].id).is_open).to.equal(isOpen);
    };

    it(
      'sets isOpen to true on a DM channel when an `im_open` message is received',
      lodash.partial(testDMOpenStatus, true, RTM_API_EVENTS.IM_OPEN)
    );

    it(
      'sets isOpen to false on a DM channel when an `im_close` message is received',
      lodash.partial(testDMOpenStatus, false, RTM_API_EVENTS.IM_CLOSE)
    );

    it('adds a new DM object when an `im_created` message is received', function () {
      var dataStore = getMemoryDataStore();
      var dmChannel;

      messageHandlers.im_created(dataStore, getRTMMessageFixture('im_created'));
      dmChannel = dataStore.getDMById('D0CHZQWNP');
      expect(dmChannel).to.not.equal(undefined);
    });

    it('marks the DM channel as read when an `im_marked` message is received', function () {
      testBaseChannelMarked('im_marked', 'D0CHZQWNP');
    });

  });

});